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 = "#0";
66 static char *one = "#1";
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 /*-----------------------------------------------------------------*/
1697 D (emitcode (";", "genCpl ");
1701 /* assign asmOps to operand & result */
1702 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1703 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1705 /* special case if in bit space */
1706 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1707 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1708 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1709 emitcode ("cpl", "c");
1710 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1713 tlbl=newiTempLabel(NULL);
1714 emitcode ("cjne", "%s,#0x01,%05d$",
1715 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1716 emitcode ("", "%05d$:", tlbl->key+100);
1717 outBitC (IC_RESULT(ic));
1721 size = AOP_SIZE (IC_RESULT (ic));
1722 _startLazyDPSEvaluation ();
1725 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1727 emitcode ("cpl", "a");
1728 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1730 _endLazyDPSEvaluation ();
1734 /* release the aops */
1735 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1736 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1739 /*-----------------------------------------------------------------*/
1740 /* genUminusFloat - unary minus for floating points */
1741 /*-----------------------------------------------------------------*/
1743 genUminusFloat (operand * op, operand * result)
1745 int size, offset = 0;
1747 /* for this we just need to flip the
1748 first it then copy the rest in place */
1749 D (emitcode (";", "genUminusFloat");
1752 _startLazyDPSEvaluation ();
1753 size = AOP_SIZE (op) - 1;
1754 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1757 emitcode ("cpl", "acc.7");
1758 aopPut (AOP (result), "a", 3);
1762 aopPut (AOP (result),
1763 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1767 _endLazyDPSEvaluation ();
1770 /*-----------------------------------------------------------------*/
1771 /* genUminus - unary minus code generation */
1772 /*-----------------------------------------------------------------*/
1774 genUminus (iCode * ic)
1777 sym_link *optype, *rtype;
1779 D (emitcode (";", "genUminus ");
1784 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1785 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1787 /* if both in bit space then special
1789 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1790 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1793 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1794 emitcode ("cpl", "c");
1795 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1799 optype = operandType (IC_LEFT (ic));
1800 rtype = operandType (IC_RESULT (ic));
1802 /* if float then do float stuff */
1803 if (IS_FLOAT (optype))
1805 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1809 /* otherwise subtract from zero */
1810 size = AOP_SIZE (IC_LEFT (ic));
1812 _startLazyDPSEvaluation ();
1815 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1816 if (!strcmp (l, "a"))
1820 emitcode ("cpl", "a");
1821 emitcode ("addc", "a,#0");
1827 emitcode ("clr", "a");
1828 emitcode ("subb", "a,%s", l);
1830 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1832 _endLazyDPSEvaluation ();
1834 /* if any remaining bytes in the result */
1835 /* we just need to propagate the sign */
1836 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1838 emitcode ("rlc", "a");
1839 emitcode ("subb", "a,acc");
1841 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1845 /* release the aops */
1846 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1847 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1850 /*-----------------------------------------------------------------*/
1851 /* savermask - saves registers in the mask */
1852 /*-----------------------------------------------------------------*/
1853 static void savermask(bitVect *rs_mask)
1856 if (options.useXstack) {
1857 if (bitVectBitValue (rs_mask, R0_IDX))
1858 emitcode ("mov", "b,r0");
1859 emitcode ("mov", "r0,%s", spname);
1860 for (i = 0; i < ds390_nRegs; i++) {
1861 if (bitVectBitValue (rs_mask, i)) {
1863 emitcode ("mov", "a,b");
1865 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1866 emitcode ("movx", "@r0,a");
1867 emitcode ("inc", "r0");
1870 emitcode ("mov", "%s,r0", spname);
1871 if (bitVectBitValue (rs_mask, R0_IDX))
1872 emitcode ("mov", "r0,b");
1874 for (i = 0; i < ds390_nRegs; i++) {
1875 if (bitVectBitValue (rs_mask, i))
1876 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1881 /*-----------------------------------------------------------------*/
1882 /* saveRegisters - will look for a call and save the registers */
1883 /*-----------------------------------------------------------------*/
1885 saveRegisters (iCode * lic)
1891 for (ic = lic; ic; ic = ic->next)
1892 if (ic->op == CALL || ic->op == PCALL)
1897 fprintf (stderr, "found parameter push with no function call\n");
1901 /* if the registers have been saved already then
1903 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1905 /* special case if DPTR alive across a function call then must save it
1906 even though callee saves */
1907 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1909 rsave = newBitVect(ic->rMask->size);
1910 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1911 if (bitVectBitValue(ic->rMask,i))
1912 rsave = bitVectSetBit(rsave,i);
1914 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1916 /* safe the registers in use at this time but skip the
1917 ones for the result */
1918 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1919 ds390_rUmaskForOp (IC_RESULT(ic)));
1925 /*-----------------------------------------------------------------*/
1926 /* usavermask - restore registers with mask */
1927 /*-----------------------------------------------------------------*/
1928 static void unsavermask(bitVect *rs_mask)
1931 if (options.useXstack) {
1932 emitcode ("mov", "r0,%s", spname);
1933 for (i = ds390_nRegs; i >= 0; i--) {
1934 if (bitVectBitValue (rs_mask, i)) {
1935 emitcode ("dec", "r0");
1936 emitcode ("movx", "a,@r0");
1938 emitcode ("mov", "b,a");
1940 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1943 emitcode ("mov", "%s,r0", spname);
1944 if (bitVectBitValue (rs_mask, R0_IDX))
1945 emitcode ("mov", "r0,b");
1947 for (i = ds390_nRegs; i >= 0; i--) {
1948 if (bitVectBitValue (rs_mask, i))
1949 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1954 /*-----------------------------------------------------------------*/
1955 /* unsaveRegisters - pop the pushed registers */
1956 /*-----------------------------------------------------------------*/
1958 unsaveRegisters (iCode * ic)
1962 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1964 rsave = newBitVect(ic->rMask->size);
1965 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1966 if (bitVectBitValue(ic->rMask,i))
1967 rsave = bitVectSetBit(rsave,i);
1969 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1971 /* restore the registers in use at this time but skip the
1972 ones for the result */
1973 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1974 ds390_rUmaskForOp (IC_RESULT(ic)));
1980 /*-----------------------------------------------------------------*/
1982 /*-----------------------------------------------------------------*/
1984 pushSide (operand * oper, int size)
1987 _startLazyDPSEvaluation ();
1990 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1991 if (AOP_TYPE (oper) != AOP_REG &&
1992 AOP_TYPE (oper) != AOP_DIR &&
1995 emitcode ("mov", "a,%s", l);
1996 emitcode ("push", "acc");
1999 emitcode ("push", "%s", l);
2001 _endLazyDPSEvaluation ();
2004 /*-----------------------------------------------------------------*/
2005 /* assignResultValue - */
2006 /*-----------------------------------------------------------------*/
2008 assignResultValue (operand * oper)
2011 int size = AOP_SIZE (oper);
2013 _startLazyDPSEvaluation ();
2016 aopPut (AOP (oper), fReturn[offset], offset);
2019 _endLazyDPSEvaluation ();
2023 /*-----------------------------------------------------------------*/
2024 /* genXpush - pushes onto the external stack */
2025 /*-----------------------------------------------------------------*/
2027 genXpush (iCode * ic)
2029 asmop *aop = newAsmop (0);
2031 int size, offset = 0;
2033 D (emitcode (";", "genXpush ");
2036 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2037 r = getFreePtr (ic, &aop, FALSE);
2040 emitcode ("mov", "%s,_spx", r->name);
2042 size = AOP_SIZE (IC_LEFT (ic));
2043 _startLazyDPSEvaluation ();
2047 char *l = aopGet (AOP (IC_LEFT (ic)),
2048 offset++, FALSE, FALSE, TRUE);
2050 emitcode ("movx", "@%s,a", r->name);
2051 emitcode ("inc", "%s", r->name);
2054 _endLazyDPSEvaluation ();
2057 emitcode ("mov", "_spx,%s", r->name);
2059 freeAsmop (NULL, aop, ic, TRUE);
2060 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2063 /*-----------------------------------------------------------------*/
2064 /* genIpush - genrate code for pushing this gets a little complex */
2065 /*-----------------------------------------------------------------*/
2067 genIpush (iCode * ic)
2069 int size, offset = 0;
2072 D (emitcode (";", "genIpush ");
2075 /* if this is not a parm push : ie. it is spill push
2076 and spill push is always done on the local stack */
2080 /* and the item is spilt then do nothing */
2081 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2084 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2085 size = AOP_SIZE (IC_LEFT (ic));
2086 /* push it on the stack */
2087 _startLazyDPSEvaluation ();
2090 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2096 emitcode ("push", "%s", l);
2098 _endLazyDPSEvaluation ();
2102 /* this is a paramter push: in this case we call
2103 the routine to find the call and save those
2104 registers that need to be saved */
2107 /* if use external stack then call the external
2108 stack pushing routine */
2109 if (options.useXstack)
2115 /* then do the push */
2116 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2118 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2119 size = AOP_SIZE (IC_LEFT (ic));
2121 _startLazyDPSEvaluation ();
2124 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2125 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2126 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2129 emitcode ("mov", "a,%s", l);
2130 emitcode ("push", "acc");
2133 emitcode ("push", "%s", l);
2135 _endLazyDPSEvaluation ();
2137 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2140 /*-----------------------------------------------------------------*/
2141 /* genIpop - recover the registers: can happen only for spilling */
2142 /*-----------------------------------------------------------------*/
2144 genIpop (iCode * ic)
2148 D (emitcode (";", "genIpop ");
2152 /* if the temp was not pushed then */
2153 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2156 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2157 size = AOP_SIZE (IC_LEFT (ic));
2158 offset = (size - 1);
2159 _startLazyDPSEvaluation ();
2162 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2163 FALSE, TRUE, TRUE));
2165 _endLazyDPSEvaluation ();
2167 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2170 /*-----------------------------------------------------------------*/
2171 /* unsaveRBank - restores the resgister bank from stack */
2172 /*-----------------------------------------------------------------*/
2174 unsaveRBank (int bank, iCode * ic, bool popPsw)
2180 if (options.useXstack)
2184 /* Assume r0 is available for use. */
2185 r = ds390_regWithIdx (R0_IDX);;
2190 r = getFreePtr (ic, &aop, FALSE);
2192 emitcode ("mov", "%s,_spx", r->name);
2197 if (options.useXstack)
2199 emitcode ("movx", "a,@%s", r->name);
2200 emitcode ("mov", "psw,a");
2201 emitcode ("dec", "%s", r->name);
2205 emitcode ("pop", "psw");
2209 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2211 if (options.useXstack)
2213 emitcode ("movx", "a,@%s", r->name);
2214 emitcode ("mov", "(%s+%d),a",
2215 regs390[i].base, 8 * bank + regs390[i].offset);
2216 emitcode ("dec", "%s", r->name);
2220 emitcode ("pop", "(%s+%d)",
2221 regs390[i].base, 8 * bank + regs390[i].offset);
2224 if (options.useXstack)
2226 emitcode ("mov", "_spx,%s", r->name);
2231 freeAsmop (NULL, aop, ic, TRUE);
2235 /*-----------------------------------------------------------------*/
2236 /* saveRBank - saves an entire register bank on the stack */
2237 /*-----------------------------------------------------------------*/
2239 saveRBank (int bank, iCode * ic, bool pushPsw)
2245 if (options.useXstack)
2249 /* Assume r0 is available for use. */
2250 r = ds390_regWithIdx (R0_IDX);;
2255 r = getFreePtr (ic, &aop, FALSE);
2257 emitcode ("mov", "%s,_spx", r->name);
2260 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2262 if (options.useXstack)
2264 emitcode ("inc", "%s", r->name);
2265 emitcode ("mov", "a,(%s+%d)",
2266 regs390[i].base, 8 * bank + regs390[i].offset);
2267 emitcode ("movx", "@%s,a", r->name);
2270 emitcode ("push", "(%s+%d)",
2271 regs390[i].base, 8 * bank + regs390[i].offset);
2276 if (options.useXstack)
2278 emitcode ("mov", "a,psw");
2279 emitcode ("movx", "@%s,a", r->name);
2280 emitcode ("inc", "%s", r->name);
2281 emitcode ("mov", "_spx,%s", r->name);
2285 emitcode ("push", "psw");
2288 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2293 freeAsmop (NULL, aop, ic, TRUE);
2302 /*-----------------------------------------------------------------*/
2303 /* genCall - generates a call statement */
2304 /*-----------------------------------------------------------------*/
2306 genCall (iCode * ic)
2309 bool restoreBank = FALSE;
2310 bool swapBanks = FALSE;
2312 D (emitcode (";", "genCall "););
2314 /* if we are calling a not _naked function that is not using
2315 the same register bank then we need to save the
2316 destination registers on the stack */
2317 dtype = operandType (IC_LEFT (ic));
2318 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2319 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2320 IFFUNC_ISISR (currFunc->type))
2324 /* This is unexpected; the bank should have been saved in
2327 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2333 /* if caller saves & we have not saved then */
2337 /* if send set is not empty the assign */
2338 /* We've saved all the registers we care about;
2339 * therefore, we may clobber any register not used
2340 * in the calling convention (i.e. anything not in
2347 for (sic = setFirstItem (_G.sendSet); sic;
2348 sic = setNextItem (_G.sendSet))
2350 int size, offset = 0;
2352 // we know that dpl(hxb) is the result, so
2353 _startLazyDPSEvaluation ();
2354 size=getSize(operandType(IC_LEFT(sic)));
2356 aopOp (IC_LEFT (sic), sic, FALSE,
2357 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2359 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2363 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2364 FALSE, FALSE, TRUE);
2365 if (strcmp (l, fReturn[offset]))
2367 emitcode ("mov", "%s,%s",
2373 _endLazyDPSEvaluation ();
2374 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2381 emitcode ("mov", "psw,#!constbyte",
2382 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2386 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2387 OP_SYMBOL (IC_LEFT (ic))->rname :
2388 OP_SYMBOL (IC_LEFT (ic))->name));
2392 emitcode ("mov", "psw,#!constbyte",
2393 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2396 /* if we need assign a result value */
2397 if ((IS_ITEMP (IC_RESULT (ic)) &&
2398 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2399 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2400 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2401 IS_TRUE_SYMOP (IC_RESULT (ic)))
2403 if (isOperandInFarSpace (IC_RESULT (ic))
2404 && getSize (operandType (IC_RESULT (ic))) <= 2)
2406 int size = getSize (operandType (IC_RESULT (ic)));
2408 /* Special case for 1 or 2 byte return in far space. */
2412 emitcode ("mov", "b,%s", fReturn[1]);
2415 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2416 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2420 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2427 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2430 assignResultValue (IC_RESULT (ic));
2432 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2436 /* adjust the stack for parameters if
2438 if (ic->parmBytes) {
2440 if (options.stack10bit) {
2441 if (ic->parmBytes <= 4) {
2442 emitcode(";","stack adjustment for parms");
2443 for (i=0; i < ic->parmBytes ; i++) {
2444 emitcode("pop","acc");
2447 emitcode ("clr","c");
2448 emitcode ("mov","a,sp");
2449 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2450 emitcode ("mov","sp,a");
2451 emitcode ("mov","a,esp");
2452 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2453 emitcode ("mov","esp,a");
2456 if (ic->parmBytes > 3) {
2457 emitcode ("mov", "a,%s", spname);
2458 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2459 emitcode ("mov", "%s,a", spname);
2461 for (i = 0; i < ic->parmBytes; i++)
2462 emitcode ("dec", "%s", spname);
2466 /* if we hade saved some registers then unsave them */
2468 unsaveRegisters (ic);
2470 /* if register bank was saved then pop them */
2472 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2475 /*-----------------------------------------------------------------*/
2476 /* genPcall - generates a call by pointer statement */
2477 /*-----------------------------------------------------------------*/
2479 genPcall (iCode * ic)
2482 symbol *rlbl = newiTempLabel (NULL);
2483 bool restoreBank=FALSE;
2485 D (emitcode (";", "genPcall ");
2489 /* if caller saves & we have not saved then */
2493 /* if we are calling a function that is not using
2494 the same register bank then we need to save the
2495 destination registers on the stack */
2496 dtype = operandType (IC_LEFT (ic));
2497 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2498 IFFUNC_ISISR (currFunc->type) &&
2499 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2500 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2504 /* push the return address on to the stack */
2505 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2506 emitcode ("push", "acc");
2507 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2508 emitcode ("push", "acc");
2510 if (options.model == MODEL_FLAT24)
2512 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2513 emitcode ("push", "acc");
2516 /* now push the calling address */
2517 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2519 pushSide (IC_LEFT (ic), FPTRSIZE);
2521 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2523 /* if send set is not empty the assign */
2528 for (sic = setFirstItem (_G.sendSet); sic;
2529 sic = setNextItem (_G.sendSet))
2531 int size, offset = 0;
2533 // we know that dpl(hxb) is the result, so
2534 _startLazyDPSEvaluation ();
2535 size=getSize(operandType(IC_LEFT(sic)));
2537 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2539 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2543 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2544 FALSE, FALSE, TRUE);
2545 if (strcmp (l, fReturn[offset]))
2547 emitcode ("mov", "%s,%s",
2553 _endLazyDPSEvaluation ();
2554 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2559 emitcode ("ret", "");
2560 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2563 /* if we need assign a result value */
2564 if ((IS_ITEMP (IC_RESULT (ic)) &&
2565 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2566 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2567 IS_TRUE_SYMOP (IC_RESULT (ic)))
2571 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2574 assignResultValue (IC_RESULT (ic));
2576 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2579 /* adjust the stack for parameters if
2584 if (ic->parmBytes > 3)
2586 emitcode ("mov", "a,%s", spname);
2587 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2588 emitcode ("mov", "%s,a", spname);
2591 for (i = 0; i < ic->parmBytes; i++)
2592 emitcode ("dec", "%s", spname);
2596 /* if register bank was saved then unsave them */
2598 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2600 /* if we hade saved some registers then
2603 unsaveRegisters (ic);
2607 /*-----------------------------------------------------------------*/
2608 /* resultRemat - result is rematerializable */
2609 /*-----------------------------------------------------------------*/
2611 resultRemat (iCode * ic)
2613 if (SKIP_IC (ic) || ic->op == IFX)
2616 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2618 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2619 if (sym->remat && !POINTER_SET (ic))
2626 #if defined(__BORLANDC__) || defined(_MSC_VER)
2627 #define STRCASECMP stricmp
2629 #define STRCASECMP strcasecmp
2632 /*-----------------------------------------------------------------*/
2633 /* inExcludeList - return 1 if the string is in exclude Reg list */
2634 /*-----------------------------------------------------------------*/
2636 inExcludeList (char *s)
2640 if (options.excludeRegs[i] &&
2641 STRCASECMP (options.excludeRegs[i], "none") == 0)
2644 for (i = 0; options.excludeRegs[i]; i++)
2646 if (options.excludeRegs[i] &&
2647 STRCASECMP (s, options.excludeRegs[i]) == 0)
2653 /*-----------------------------------------------------------------*/
2654 /* genFunction - generated code for function entry */
2655 /*-----------------------------------------------------------------*/
2657 genFunction (iCode * ic)
2661 bool switchedPSW = FALSE;
2663 D (emitcode (";", "genFunction "););
2666 /* create the function header */
2667 emitcode (";", "-----------------------------------------");
2668 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2669 emitcode (";", "-----------------------------------------");
2671 emitcode ("", "%s:", sym->rname);
2672 ftype = operandType (IC_LEFT (ic));
2674 if (IFFUNC_ISNAKED(ftype))
2676 emitcode(";", "naked function: no prologue.");
2680 if (options.stack_probe)
2681 emitcode ("lcall","__stack_probe");
2682 /* if critical function then turn interrupts off */
2683 if (IFFUNC_ISCRITICAL (ftype))
2684 emitcode ("clr", "ea");
2686 /* here we need to generate the equates for the
2687 register bank if required */
2688 if (FUNC_REGBANK (ftype) != rbank)
2692 rbank = FUNC_REGBANK (ftype);
2693 for (i = 0; i < ds390_nRegs; i++)
2695 if (regs390[i].print) {
2696 if (strcmp (regs390[i].base, "0") == 0)
2697 emitcode ("", "%s !equ !constbyte",
2699 8 * rbank + regs390[i].offset);
2701 emitcode ("", "%s !equ %s + !constbyte",
2704 8 * rbank + regs390[i].offset);
2709 /* if this is an interrupt service routine then
2710 save acc, b, dpl, dph */
2711 if (IFFUNC_ISISR (sym->type))
2714 if (!inExcludeList ("acc"))
2715 emitcode ("push", "acc");
2716 if (!inExcludeList ("b"))
2717 emitcode ("push", "b");
2718 if (!inExcludeList ("dpl"))
2719 emitcode ("push", "dpl");
2720 if (!inExcludeList ("dph"))
2721 emitcode ("push", "dph");
2722 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2724 emitcode ("push", "dpx");
2725 /* Make sure we're using standard DPTR */
2726 emitcode ("push", "dps");
2727 emitcode ("mov", "dps,#0");
2728 if (options.stack10bit)
2730 /* This ISR could conceivably use DPTR2. Better save it. */
2731 emitcode ("push", "dpl1");
2732 emitcode ("push", "dph1");
2733 emitcode ("push", "dpx1");
2734 emitcode ("push", DP2_RESULT_REG);
2737 /* if this isr has no bank i.e. is going to
2738 run with bank 0 , then we need to save more
2740 if (!FUNC_REGBANK (sym->type))
2743 /* if this function does not call any other
2744 function then we can be economical and
2745 save only those registers that are used */
2746 if (!IFFUNC_HASFCALL(sym->type))
2750 /* if any registers used */
2753 /* save the registers used */
2754 for (i = 0; i < sym->regsUsed->size; i++)
2756 if (bitVectBitValue (sym->regsUsed, i) ||
2757 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2758 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2765 /* this function has a function call cannot
2766 determines register usage so we will have to push the
2768 saveRBank (0, ic, FALSE);
2773 /* This ISR uses a non-zero bank.
2775 * We assume that the bank is available for our
2778 * However, if this ISR calls a function which uses some
2779 * other bank, we must save that bank entirely.
2781 unsigned long banksToSave = 0;
2783 if (IFFUNC_HASFCALL(sym->type))
2786 #define MAX_REGISTER_BANKS 4
2791 for (i = ic; i; i = i->next)
2793 if (i->op == ENDFUNCTION)
2795 /* we got to the end OK. */
2803 dtype = operandType (IC_LEFT(i));
2805 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2807 /* Mark this bank for saving. */
2808 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2810 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2814 banksToSave |= (1 << FUNC_REGBANK(dtype));
2817 /* And note that we don't need to do it in
2825 /* This is a mess; we have no idea what
2826 * register bank the called function might
2829 * The only thing I can think of to do is
2830 * throw a warning and hope.
2832 werror(W_FUNCPTR_IN_USING_ISR);
2836 if (banksToSave && options.useXstack)
2838 /* Since we aren't passing it an ic,
2839 * saveRBank will assume r0 is available to abuse.
2841 * So switch to our (trashable) bank now, so
2842 * the caller's R0 isn't trashed.
2844 emitcode ("push", "psw");
2845 emitcode ("mov", "psw,#!constbyte",
2846 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2850 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2852 if (banksToSave & (1 << ix))
2854 saveRBank(ix, NULL, FALSE);
2858 // jwk: this needs a closer look
2859 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2864 /* if callee-save to be used for this function
2865 then save the registers being used in this function */
2866 if (IFFUNC_CALLEESAVES(sym->type))
2870 /* if any registers used */
2873 /* save the registers used */
2874 for (i = 0; i < sym->regsUsed->size; i++)
2876 if (bitVectBitValue (sym->regsUsed, i) ||
2877 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2879 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2887 /* set the register bank to the desired value */
2888 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2891 emitcode ("push", "psw");
2892 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2895 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2896 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2897 if (options.stack10bit) {
2898 emitcode ("push","_bpx");
2899 emitcode ("push","_bpx+1");
2900 emitcode ("mov","_bpx,%s",spname);
2901 emitcode ("mov","_bpx+1,esp");
2902 emitcode ("anl","_bpx+1,#3");
2904 if (options.useXstack) {
2905 emitcode ("mov", "r0,%s", spname);
2906 emitcode ("mov", "a,_bp");
2907 emitcode ("movx", "@r0,a");
2908 emitcode ("inc", "%s", spname);
2910 /* set up the stack */
2911 emitcode ("push", "_bp"); /* save the callers stack */
2913 emitcode ("mov", "_bp,%s", spname);
2917 /* adjust the stack for the function */
2920 if (options.stack10bit) {
2921 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2922 assert (sym->recvSize <= 4);
2923 emitcode ("mov","a,sp");
2924 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2925 emitcode ("mov","sp,a");
2926 emitcode ("mov","a,esp");
2927 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2928 emitcode ("mov","esp,a");
2931 werror (W_STACK_OVERFLOW, sym->name);
2933 if (i > 3 && sym->recvSize < 4) {
2935 emitcode ("mov", "a,sp");
2936 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2937 emitcode ("mov", "sp,a");
2941 emitcode ("inc", "sp");
2948 emitcode ("mov", "a,_spx");
2949 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2950 emitcode ("mov", "_spx,a");
2955 /*-----------------------------------------------------------------*/
2956 /* genEndFunction - generates epilogue for functions */
2957 /*-----------------------------------------------------------------*/
2959 genEndFunction (iCode * ic)
2961 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2963 D (emitcode (";", "genEndFunction "););
2965 if (IFFUNC_ISNAKED(sym->type))
2967 emitcode(";", "naked function: no epilogue.");
2971 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2972 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2974 if (options.stack10bit) {
2975 emitcode ("mov", "sp,_bpx", spname);
2976 emitcode ("mov", "esp,_bpx+1", spname);
2978 emitcode ("mov", "%s,_bp", spname);
2982 /* if use external stack but some variables were
2983 added to the local stack then decrement the
2985 if (options.useXstack && sym->stack) {
2986 emitcode ("mov", "a,sp");
2987 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2988 emitcode ("mov", "sp,a");
2992 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2993 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2995 if (options.useXstack) {
2996 emitcode ("mov", "r0,%s", spname);
2997 emitcode ("movx", "a,@r0");
2998 emitcode ("mov", "_bp,a");
2999 emitcode ("dec", "%s", spname);
3001 if (options.stack10bit) {
3002 emitcode ("pop", "_bpx+1");
3003 emitcode ("pop", "_bpx");
3005 emitcode ("pop", "_bp");
3010 /* restore the register bank */
3011 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3013 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3014 || !options.useXstack)
3016 /* Special case of ISR using non-zero bank with useXstack
3019 emitcode ("pop", "psw");
3023 if (IFFUNC_ISISR (sym->type))
3026 /* now we need to restore the registers */
3027 /* if this isr has no bank i.e. is going to
3028 run with bank 0 , then we need to save more
3030 if (!FUNC_REGBANK (sym->type))
3032 /* if this function does not call any other
3033 function then we can be economical and
3034 save only those registers that are used */
3035 if (!IFFUNC_HASFCALL(sym->type))
3039 /* if any registers used */
3042 /* save the registers used */
3043 for (i = sym->regsUsed->size; i >= 0; i--)
3045 if (bitVectBitValue (sym->regsUsed, i) ||
3046 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3047 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3054 /* this function has a function call cannot
3055 determines register usage so we will have to pop the
3057 unsaveRBank (0, ic, FALSE);
3062 /* This ISR uses a non-zero bank.
3064 * Restore any register banks saved by genFunction
3067 // jwk: this needs a closer look
3068 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3071 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3073 if (savedBanks & (1 << ix))
3075 unsaveRBank(ix, NULL, FALSE);
3079 if (options.useXstack)
3081 /* Restore bank AFTER calling unsaveRBank,
3082 * since it can trash r0.
3084 emitcode ("pop", "psw");
3088 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3090 if (options.stack10bit)
3092 emitcode ("pop", DP2_RESULT_REG);
3093 emitcode ("pop", "dpx1");
3094 emitcode ("pop", "dph1");
3095 emitcode ("pop", "dpl1");
3097 emitcode ("pop", "dps");
3098 emitcode ("pop", "dpx");
3100 if (!inExcludeList ("dph"))
3101 emitcode ("pop", "dph");
3102 if (!inExcludeList ("dpl"))
3103 emitcode ("pop", "dpl");
3104 if (!inExcludeList ("b"))
3105 emitcode ("pop", "b");
3106 if (!inExcludeList ("acc"))
3107 emitcode ("pop", "acc");
3109 if (IFFUNC_ISCRITICAL (sym->type))
3110 emitcode ("setb", "ea");
3112 /* if debug then send end of function */
3113 if (options.debug && currFunc) {
3115 emitcode ("", "C$%s$%d$%d$%d ==.",
3116 FileBaseName (ic->filename), currFunc->lastLine,
3117 ic->level, ic->block);
3118 if (IS_STATIC (currFunc->etype))
3119 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3121 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3125 emitcode ("reti", "");
3129 if (IFFUNC_ISCRITICAL (sym->type))
3130 emitcode ("setb", "ea");
3132 if (IFFUNC_CALLEESAVES(sym->type))
3136 /* if any registers used */
3139 /* save the registers used */
3140 for (i = sym->regsUsed->size; i >= 0; i--)
3142 if (bitVectBitValue (sym->regsUsed, i) ||
3143 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3144 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3150 /* if debug then send end of function */
3151 if (options.debug && currFunc)
3154 emitcode ("", "C$%s$%d$%d$%d ==.",
3155 FileBaseName (ic->filename), currFunc->lastLine,
3156 ic->level, ic->block);
3157 if (IS_STATIC (currFunc->etype))
3158 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3160 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3164 emitcode ("ret", "");
3169 /*-----------------------------------------------------------------*/
3170 /* genJavaNativeRet - generate code for return JavaNative */
3171 /*-----------------------------------------------------------------*/
3172 static void genJavaNativeRet(iCode *ic)
3176 aopOp (IC_LEFT (ic), ic, FALSE,
3177 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3178 size = AOP_SIZE (IC_LEFT (ic));
3182 /* it is assigned to GPR0-R3 then push them */
3183 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3184 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3185 for (i = 0 ; i < size ; i++ ) {
3186 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3188 for (i = (size-1) ; i >= 0 ; i--) {
3189 emitcode ("pop","a%s",javaRet[i]);
3192 for (i = 0 ; i < size ; i++)
3193 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3195 for (i = size ; i < 4 ; i++ )
3196 emitcode ("mov","%s,#0",javaRet[i]);
3200 /*-----------------------------------------------------------------*/
3201 /* genRet - generate code for return statement */
3202 /*-----------------------------------------------------------------*/
3206 int size, offset = 0, pushed = 0;
3208 D (emitcode (";", "genRet ");
3211 /* if we have no return value then
3212 just generate the "ret" */
3216 /* if this is a JavaNative function then return
3217 value in different register */
3218 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3219 genJavaNativeRet(ic);
3222 /* we have something to return then
3223 move the return value into place */
3224 aopOp (IC_LEFT (ic), ic, FALSE,
3225 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3226 size = AOP_SIZE (IC_LEFT (ic));
3228 _startLazyDPSEvaluation ();
3232 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3234 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3235 FALSE, TRUE, FALSE);
3236 emitcode ("push", "%s", l);
3241 /* Since A is the last element of fReturn,
3242 * is is OK to clobber it in the aopGet.
3244 l = aopGet (AOP (IC_LEFT (ic)), offset,
3245 FALSE, FALSE, TRUE);
3246 if (strcmp (fReturn[offset], l))
3247 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3250 _endLazyDPSEvaluation ();
3257 if (strcmp (fReturn[pushed], "a"))
3258 emitcode ("pop", fReturn[pushed]);
3260 emitcode ("pop", "acc");
3263 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3266 /* generate a jump to the return label
3267 if the next is not the return statement */
3268 if (!(ic->next && ic->next->op == LABEL &&
3269 IC_LABEL (ic->next) == returnLabel))
3271 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3275 /*-----------------------------------------------------------------*/
3276 /* genLabel - generates a label */
3277 /*-----------------------------------------------------------------*/
3279 genLabel (iCode * ic)
3281 /* special case never generate */
3282 if (IC_LABEL (ic) == entryLabel)
3285 D (emitcode (";", "genLabel ");
3288 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3291 /*-----------------------------------------------------------------*/
3292 /* genGoto - generates a ljmp */
3293 /*-----------------------------------------------------------------*/
3295 genGoto (iCode * ic)
3297 D (emitcode (";", "genGoto ");
3299 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3302 /*-----------------------------------------------------------------*/
3303 /* findLabelBackwards: walks back through the iCode chain looking */
3304 /* for the given label. Returns number of iCode instructions */
3305 /* between that label and given ic. */
3306 /* Returns zero if label not found. */
3307 /*-----------------------------------------------------------------*/
3309 findLabelBackwards (iCode * ic, int key)
3318 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3320 /* printf("findLabelBackwards = %d\n", count); */
3328 /*-----------------------------------------------------------------*/
3329 /* genPlusIncr :- does addition with increment if possible */
3330 /*-----------------------------------------------------------------*/
3332 genPlusIncr (iCode * ic)
3334 unsigned int icount;
3335 unsigned int size = getDataSize (IC_RESULT (ic));
3337 /* will try to generate an increment */
3338 /* if the right side is not a literal
3340 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3343 /* if the literal value of the right hand side
3344 is greater than 4 then it is not worth it */
3345 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3348 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3349 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3351 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3355 /* if increment 16 bits in register */
3357 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3358 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3359 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3367 /* If the next instruction is a goto and the goto target
3368 * is <= 5 instructions previous to this, we can generate
3369 * jumps straight to that target.
3371 if (ic->next && ic->next->op == GOTO
3372 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3375 emitcode (";", "tail increment optimized (range %d)", labelRange);
3376 tlbl = IC_LABEL (ic->next);
3381 tlbl = newiTempLabel (NULL);
3384 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3385 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3386 IS_AOP_PREG (IC_RESULT (ic)))
3387 emitcode ("cjne", "%s,#0,!tlabel"
3388 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3392 emitcode ("clr", "a");
3393 emitcode ("cjne", "a,%s,!tlabel"
3394 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3398 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3401 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3402 IS_AOP_PREG (IC_RESULT (ic)))
3403 emitcode ("cjne", "%s,#0,!tlabel"
3404 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3407 emitcode ("cjne", "a,%s,!tlabel"
3408 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3411 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3415 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3416 IS_AOP_PREG (IC_RESULT (ic)))
3417 emitcode ("cjne", "%s,#0,!tlabel"
3418 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3422 emitcode ("cjne", "a,%s,!tlabel"
3423 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3426 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3431 emitcode ("", "!tlabeldef", tlbl->key + 100);
3436 /* if the sizes are greater than 1 then we cannot */
3437 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3438 AOP_SIZE (IC_LEFT (ic)) > 1)
3441 /* we can if the aops of the left & result match or
3442 if they are in registers and the registers are the
3445 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3446 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3447 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3452 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3453 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3454 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3459 _startLazyDPSEvaluation ();
3462 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3464 _endLazyDPSEvaluation ();
3473 /*-----------------------------------------------------------------*/
3474 /* outBitAcc - output a bit in acc */
3475 /*-----------------------------------------------------------------*/
3477 outBitAcc (operand * result)
3479 symbol *tlbl = newiTempLabel (NULL);
3480 /* if the result is a bit */
3481 if (AOP_TYPE (result) == AOP_CRY)
3483 aopPut (AOP (result), "a", 0);
3487 emitcode ("jz", "!tlabel", tlbl->key + 100);
3488 emitcode ("mov", "a,%s", one);
3489 emitcode ("", "!tlabeldef", tlbl->key + 100);
3494 /*-----------------------------------------------------------------*/
3495 /* genPlusBits - generates code for addition of two bits */
3496 /*-----------------------------------------------------------------*/
3498 genPlusBits (iCode * ic)
3500 D (emitcode (";", "genPlusBits ");
3502 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3504 symbol *lbl = newiTempLabel (NULL);
3505 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3506 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3507 emitcode ("cpl", "c");
3508 emitcode ("", "!tlabeldef", (lbl->key + 100));
3509 outBitC (IC_RESULT (ic));
3513 emitcode ("clr", "a");
3514 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3515 emitcode ("rlc", "a");
3516 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3517 emitcode ("addc", "a,#0");
3518 outAcc (IC_RESULT (ic));
3523 adjustArithmeticResult (iCode * ic)
3525 if (opIsGptr (IC_RESULT (ic)) &&
3526 opIsGptr (IC_LEFT (ic)) &&
3527 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3529 aopPut (AOP (IC_RESULT (ic)),
3530 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3534 if (opIsGptr (IC_RESULT (ic)) &&
3535 opIsGptr (IC_RIGHT (ic)) &&
3536 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3538 aopPut (AOP (IC_RESULT (ic)),
3539 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3543 if (opIsGptr (IC_RESULT (ic)) &&
3544 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3545 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3546 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3547 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3550 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3551 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3555 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3556 // Please don't bring it back without a really good reason.
3557 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3558 // (because all three operands are in far space).
3559 #define AOP_OP_3(ic) \
3560 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3561 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3562 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3563 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3564 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3565 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3567 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3569 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3573 // Macro to aopOp all three operands of an ic. If this cannot be done,
3574 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3575 // will be set TRUE. The caller must then handle the case specially, noting
3576 // that the IC_RESULT operand is not aopOp'd.
3577 #define AOP_OP_3_NOFATAL(ic, rc) \
3578 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3579 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3580 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3581 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3582 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3584 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3589 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3590 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3592 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3593 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3595 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3597 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3601 // aopOp the left & right operands of an ic.
3602 #define AOP_OP_2(ic) \
3603 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3604 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3606 // convienience macro.
3607 #define AOP_SET_LOCALS(ic) \
3608 left = IC_LEFT(ic); \
3609 right = IC_RIGHT(ic); \
3610 result = IC_RESULT(ic);
3613 // Given an integer value of pushedSize bytes on the stack,
3614 // adjust it to be resultSize bytes, either by discarding
3615 // the most significant bytes or by zero-padding.
3617 // On exit from this macro, pushedSize will have been adjusted to
3618 // equal resultSize, and ACC may be trashed.
3619 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3620 /* If the pushed data is bigger than the result, \
3621 * simply discard unused bytes. Icky, but works. \
3623 while (pushedSize > resultSize) \
3625 D (emitcode (";", "discarding unused result byte."););\
3626 emitcode ("pop", "acc"); \
3629 if (pushedSize < resultSize) \
3631 emitcode ("clr", "a"); \
3632 /* Conversly, we haven't pushed enough here. \
3633 * just zero-pad, and all is well. \
3635 while (pushedSize < resultSize) \
3637 emitcode("push", "acc"); \
3641 assert(pushedSize == resultSize);
3643 /*-----------------------------------------------------------------*/
3644 /* genPlus - generates code for addition */
3645 /*-----------------------------------------------------------------*/
3647 genPlus (iCode * ic)
3649 int size, offset = 0;
3650 bool pushResult = FALSE;
3653 D (emitcode (";", "genPlus "););
3655 /* special cases :- */
3656 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3657 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3658 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3659 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3661 while (size--) emitcode ("inc","dptr");
3663 emitcode ("mov","a,dpl");
3664 emitcode ("add","a,#!constbyte",size & 0xff);
3665 emitcode ("mov","dpl,a");
3666 emitcode ("mov","a,dph");
3667 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3668 emitcode ("mov","dph,a");
3669 emitcode ("mov","a,dpx");
3670 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3671 emitcode ("mov","dpx,a");
3673 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3676 if ( IS_SYMOP(IC_LEFT(ic)) &&
3677 OP_SYMBOL(IC_LEFT(ic))->remat &&
3678 isOperandInFarSpace(IC_RIGHT(ic))) {
3679 operand *op = IC_RIGHT(ic);
3680 IC_RIGHT(ic) = IC_LEFT(ic);
3684 AOP_OP_3_NOFATAL (ic, pushResult);
3687 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3692 /* if literal, literal on the right or
3693 if left requires ACC or right is already
3695 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3696 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3697 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3699 operand *t = IC_RIGHT (ic);
3700 IC_RIGHT (ic) = IC_LEFT (ic);
3702 emitcode (";", "Swapped plus args.");
3705 /* if both left & right are in bit
3707 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3708 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3714 /* if left in bit space & right literal */
3715 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3716 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3718 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3719 /* if result in bit space */
3720 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3722 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3723 emitcode ("cpl", "c");
3724 outBitC (IC_RESULT (ic));
3728 size = getDataSize (IC_RESULT (ic));
3729 _startLazyDPSEvaluation ();
3732 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3733 emitcode ("addc", "a,#0");
3734 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3736 _endLazyDPSEvaluation ();
3741 /* if I can do an increment instead
3742 of add then GOOD for ME */
3743 if (genPlusIncr (ic) == TRUE)
3745 emitcode (";", "did genPlusIncr");
3750 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3752 _startLazyDPSEvaluation ();
3755 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3757 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3759 emitcode ("add", "a,%s",
3760 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3762 emitcode ("addc", "a,%s",
3763 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3767 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3769 /* right is going to use ACC or we would have taken the
3772 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3774 D(emitcode(";", "+ AOP_ACC special case."););
3775 emitcode("xch", "a, %s", DP2_RESULT_REG);
3777 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3780 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3783 emitcode("add", "a, %s", DP2_RESULT_REG);
3787 emitcode ("add", "a,%s",
3788 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3793 emitcode ("addc", "a,%s",
3794 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3799 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3803 emitcode ("push", "acc");
3807 _endLazyDPSEvaluation ();
3811 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3813 size = getDataSize (IC_LEFT (ic));
3814 rSize = getDataSize (IC_RESULT (ic));
3816 ADJUST_PUSHED_RESULT(size, rSize);
3818 _startLazyDPSEvaluation ();
3821 emitcode ("pop", "acc");
3822 aopPut (AOP (IC_RESULT (ic)), "a", size);
3824 _endLazyDPSEvaluation ();
3827 adjustArithmeticResult (ic);
3830 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3831 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3832 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3835 /*-----------------------------------------------------------------*/
3836 /* genMinusDec :- does subtraction with deccrement if possible */
3837 /*-----------------------------------------------------------------*/
3839 genMinusDec (iCode * ic)
3841 unsigned int icount;
3842 unsigned int size = getDataSize (IC_RESULT (ic));
3844 /* will try to generate an increment */
3845 /* if the right side is not a literal
3847 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3850 /* if the literal value of the right hand side
3851 is greater than 4 then it is not worth it */
3852 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3855 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3856 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3858 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3862 /* if decrement 16 bits in register */
3863 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3864 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3865 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3873 /* If the next instruction is a goto and the goto target
3874 * is <= 5 instructions previous to this, we can generate
3875 * jumps straight to that target.
3877 if (ic->next && ic->next->op == GOTO
3878 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3881 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3882 tlbl = IC_LABEL (ic->next);
3887 tlbl = newiTempLabel (NULL);
3891 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3892 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3893 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3894 IS_AOP_PREG (IC_RESULT (ic)))
3895 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3896 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3900 emitcode ("mov", "a,#!constbyte",0xff);
3901 emitcode ("cjne", "a,%s,!tlabel"
3902 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3905 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3908 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3909 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3910 IS_AOP_PREG (IC_RESULT (ic)))
3911 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3912 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3916 emitcode ("cjne", "a,%s,!tlabel"
3917 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3920 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3924 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3925 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3926 IS_AOP_PREG (IC_RESULT (ic)))
3927 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3928 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3932 emitcode ("cjne", "a,%s,!tlabel"
3933 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3936 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3940 emitcode ("", "!tlabeldef", tlbl->key + 100);
3945 /* if the sizes are greater than 1 then we cannot */
3946 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3947 AOP_SIZE (IC_LEFT (ic)) > 1)
3950 /* we can if the aops of the left & result match or
3951 if they are in registers and the registers are the
3954 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3955 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3956 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3959 _startLazyDPSEvaluation ();
3962 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3964 _endLazyDPSEvaluation ();
3972 /*-----------------------------------------------------------------*/
3973 /* addSign - complete with sign */
3974 /*-----------------------------------------------------------------*/
3976 addSign (operand * result, int offset, int sign)
3978 int size = (getDataSize (result) - offset);
3981 _startLazyDPSEvaluation();
3984 emitcode ("rlc", "a");
3985 emitcode ("subb", "a,acc");
3988 aopPut (AOP (result), "a", offset++);
3995 aopPut (AOP (result), zero, offset++);
3998 _endLazyDPSEvaluation();
4002 /*-----------------------------------------------------------------*/
4003 /* genMinusBits - generates code for subtraction of two bits */
4004 /*-----------------------------------------------------------------*/
4006 genMinusBits (iCode * ic)
4008 symbol *lbl = newiTempLabel (NULL);
4010 D (emitcode (";", "genMinusBits "););
4012 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4014 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4015 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4016 emitcode ("cpl", "c");
4017 emitcode ("", "!tlabeldef", (lbl->key + 100));
4018 outBitC (IC_RESULT (ic));
4022 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4023 emitcode ("subb", "a,acc");
4024 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4025 emitcode ("inc", "a");
4026 emitcode ("", "!tlabeldef", (lbl->key + 100));
4027 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4028 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4032 /*-----------------------------------------------------------------*/
4033 /* genMinus - generates code for subtraction */
4034 /*-----------------------------------------------------------------*/
4036 genMinus (iCode * ic)
4038 int size, offset = 0;
4040 unsigned long lit = 0L;
4041 bool pushResult = FALSE;
4043 D (emitcode (";", "genMinus "););
4045 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4046 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4047 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4048 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4054 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4056 /* special cases :- */
4057 /* if both left & right are in bit space */
4058 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4059 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4065 /* if I can do an decrement instead
4066 of subtract then GOOD for ME */
4067 if (genMinusDec (ic) == TRUE)
4072 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4074 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4080 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4085 /* if literal, add a,#-lit, else normal subb */
4086 _startLazyDPSEvaluation ();
4089 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4090 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4091 emitcode ("subb", "a,%s",
4092 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4095 /* first add without previous c */
4097 if (!size && lit==-1) {
4098 emitcode ("dec", "a");
4100 emitcode ("add", "a,#!constbyte",
4101 (unsigned int) (lit & 0x0FFL));
4104 emitcode ("addc", "a,#!constbyte",
4105 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4111 emitcode ("push", "acc");
4115 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4119 _endLazyDPSEvaluation ();
4123 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4125 size = getDataSize (IC_LEFT (ic));
4126 rSize = getDataSize (IC_RESULT (ic));
4128 ADJUST_PUSHED_RESULT(size, rSize);
4130 _startLazyDPSEvaluation ();
4133 emitcode ("pop", "acc");
4134 aopPut (AOP (IC_RESULT (ic)), "a", size);
4136 _endLazyDPSEvaluation ();
4139 adjustArithmeticResult (ic);
4142 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4143 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4144 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4148 /*-----------------------------------------------------------------*/
4149 /* genMultbits :- multiplication of bits */
4150 /*-----------------------------------------------------------------*/
4152 genMultbits (operand * left,
4157 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4158 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4159 aopOp(result, ic, TRUE, FALSE);
4164 /*-----------------------------------------------------------------*/
4165 /* genMultOneByte : 8*8=8/16 bit multiplication */
4166 /*-----------------------------------------------------------------*/
4168 genMultOneByte (operand * left,
4173 sym_link *opetype = operandType (result);
4177 /* (if two literals: the value is computed before) */
4178 /* if one literal, literal on the right */
4179 if (AOP_TYPE (left) == AOP_LIT)
4184 emitcode (";", "swapped left and right");
4187 if (SPEC_USIGN(opetype)
4188 // ignore the sign of left and right, what else can we do?
4189 || (SPEC_USIGN(operandType(left)) &&
4190 SPEC_USIGN(operandType(right)))) {
4191 // just an unsigned 8*8=8/16 multiply
4192 //emitcode (";","unsigned");
4193 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4194 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4195 emitcode ("mul", "ab");
4197 _G.accInUse++; _G.bInUse++;
4198 aopOp(result, ic, TRUE, FALSE);
4200 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4202 // this should never happen
4203 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4204 AOP_SIZE(result), __FILE__, lineno);
4208 aopPut (AOP (result), "a", 0);
4209 _G.accInUse--; _G.bInUse--;
4210 if (AOP_SIZE(result)==2)
4212 aopPut (AOP (result), "b", 1);
4217 // we have to do a signed multiply
4219 emitcode (";", "signed");
4220 emitcode ("clr", "F0"); // reset sign flag
4221 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4223 lbl=newiTempLabel(NULL);
4224 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4225 // left side is negative, 8-bit two's complement, this fails for -128
4226 emitcode ("setb", "F0"); // set sign flag
4227 emitcode ("cpl", "a");
4228 emitcode ("inc", "a");
4230 emitcode ("", "!tlabeldef", lbl->key+100);
4233 if (AOP_TYPE(right)==AOP_LIT) {
4234 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4235 /* AND literal negative */
4236 if ((int) val < 0) {
4237 emitcode ("cpl", "F0"); // complement sign flag
4238 emitcode ("mov", "b,#!constbyte", -val);
4240 emitcode ("mov", "b,#!constbyte", val);
4243 lbl=newiTempLabel(NULL);
4244 emitcode ("mov", "b,a");
4245 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4246 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4247 // right side is negative, 8-bit two's complement
4248 emitcode ("cpl", "F0"); // complement sign flag
4249 emitcode ("cpl", "a");
4250 emitcode ("inc", "a");
4251 emitcode ("", "!tlabeldef", lbl->key+100);
4253 emitcode ("mul", "ab");
4255 _G.accInUse++;_G.bInUse++;
4256 aopOp(result, ic, TRUE, FALSE);
4258 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4260 // this should never happen
4261 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4262 AOP_SIZE(result), __FILE__, lineno);
4266 lbl=newiTempLabel(NULL);
4267 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4268 // only ONE op was negative, we have to do a 8/16-bit two's complement
4269 emitcode ("cpl", "a"); // lsb
4270 if (AOP_SIZE(result)==1) {
4271 emitcode ("inc", "a");
4273 emitcode ("add", "a,#1");
4274 emitcode ("xch", "a,b");
4275 emitcode ("cpl", "a"); // msb
4276 emitcode ("addc", "a,#0");
4277 emitcode ("xch", "a,b");
4280 emitcode ("", "!tlabeldef", lbl->key+100);
4281 aopPut (AOP (result), "a", 0);
4282 _G.accInUse--;_G.bInUse--;
4283 if (AOP_SIZE(result)==2) {
4284 aopPut (AOP (result), "b", 1);
4288 /*-----------------------------------------------------------------*/
4289 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4290 /*-----------------------------------------------------------------*/
4291 static void genMultTwoByte (operand *left, operand *right,
4292 operand *result, iCode *ic)
4294 sym_link *retype = getSpec(operandType(right));
4295 sym_link *letype = getSpec(operandType(left));
4296 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4299 if (AOP_TYPE (left) == AOP_LIT) {
4304 /* save EA bit in F1 */
4305 lbl = newiTempLabel(NULL);
4306 emitcode ("setb","F1");
4307 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4308 emitcode ("clr","F1");
4309 emitcode("","!tlabeldef",lbl->key+100);
4311 /* load up MB with right */
4313 emitcode("clr","F0");
4314 if (AOP_TYPE(right) == AOP_LIT) {
4315 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4317 emitcode("setb","F0");
4320 emitcode ("mov","mb,#!constbyte",val & 0xff);
4321 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4323 lbl = newiTempLabel(NULL);
4324 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4325 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4326 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4327 emitcode ("xch", "a,b");
4328 emitcode ("cpl","a");
4329 emitcode ("add", "a,#1");
4330 emitcode ("xch", "a,b");
4331 emitcode ("cpl", "a"); // msb
4332 emitcode ("addc", "a,#0");
4333 emitcode ("setb","F0");
4334 emitcode ("","!tlabeldef",lbl->key+100);
4335 emitcode ("mov","mb,b");
4336 emitcode ("mov","mb,a");
4339 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4340 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4342 /* load up MA with left */
4344 lbl = newiTempLabel(NULL);
4345 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4346 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4347 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4348 emitcode ("xch", "a,b");
4349 emitcode ("cpl","a");
4350 emitcode ("add", "a,#1");
4351 emitcode ("xch", "a,b");
4352 emitcode ("cpl", "a"); // msb
4353 emitcode ("addc","a,#0");
4354 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4355 emitcode ("setb","F0");
4356 emitcode ("","!tlabeldef",lbl->key+100);
4357 emitcode ("mov","ma,b");
4358 emitcode ("mov","ma,a");
4360 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4361 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4363 /* wait for multiplication to finish */
4364 lbl = newiTempLabel(NULL);
4365 emitcode("","!tlabeldef", lbl->key+100);
4366 emitcode("mov","a,mcnt1");
4367 emitcode("anl","a,#!constbyte",0x80);
4368 emitcode("jnz","!tlabel",lbl->key+100);
4370 freeAsmop (left, NULL, ic, TRUE);
4371 freeAsmop (right, NULL, ic,TRUE);
4372 aopOp(result, ic, TRUE, FALSE);
4374 /* if unsigned then simple */
4376 emitcode ("mov","a,ma");
4377 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4378 emitcode ("mov","a,ma");
4379 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4380 aopPut(AOP(result),"ma",1);
4381 aopPut(AOP(result),"ma",0);
4383 emitcode("push","ma");
4384 emitcode("push","ma");
4385 emitcode("push","ma");
4387 /* negate result if needed */
4388 lbl = newiTempLabel(NULL);
4389 emitcode("jnb","F0,!tlabel",lbl->key+100);
4390 emitcode("cpl","a");
4391 emitcode("add","a,#1");
4392 emitcode("","!tlabeldef", lbl->key+100);
4393 if (AOP_TYPE(result) == AOP_ACC)
4395 D(emitcode(";", "ACC special case."););
4396 /* We know result is the only live aop, and
4397 * it's obviously not a DPTR2, so AP is available.
4399 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4403 aopPut(AOP(result),"a",0);
4406 emitcode("pop","acc");
4407 lbl = newiTempLabel(NULL);
4408 emitcode("jnb","F0,!tlabel",lbl->key+100);
4409 emitcode("cpl","a");
4410 emitcode("addc","a,#0");
4411 emitcode("","!tlabeldef", lbl->key+100);
4412 aopPut(AOP(result),"a",1);
4413 emitcode("pop","acc");
4414 if (AOP_SIZE(result) >= 3) {
4415 lbl = newiTempLabel(NULL);
4416 emitcode("jnb","F0,!tlabel",lbl->key+100);
4417 emitcode("cpl","a");
4418 emitcode("addc","a,#0");
4419 emitcode("","!tlabeldef", lbl->key+100);
4420 aopPut(AOP(result),"a",2);
4422 emitcode("pop","acc");
4423 if (AOP_SIZE(result) >= 4) {
4424 lbl = newiTempLabel(NULL);
4425 emitcode("jnb","F0,!tlabel",lbl->key+100);
4426 emitcode("cpl","a");
4427 emitcode("addc","a,#0");
4428 emitcode("","!tlabeldef", lbl->key+100);
4429 aopPut(AOP(result),"a",3);
4431 if (AOP_TYPE(result) == AOP_ACC)
4433 /* We stashed the result away above. */
4434 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4438 freeAsmop (result, NULL, ic, TRUE);
4440 /* restore EA bit in F1 */
4441 lbl = newiTempLabel(NULL);
4442 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4443 emitcode ("setb","EA");
4444 emitcode("","!tlabeldef",lbl->key+100);
4448 /*-----------------------------------------------------------------*/
4449 /* genMult - generates code for multiplication */
4450 /*-----------------------------------------------------------------*/
4452 genMult (iCode * ic)
4454 operand *left = IC_LEFT (ic);
4455 operand *right = IC_RIGHT (ic);
4456 operand *result = IC_RESULT (ic);
4458 D (emitcode (";", "genMult "););
4460 /* assign the amsops */
4463 /* special cases first */
4465 if (AOP_TYPE (left) == AOP_CRY &&
4466 AOP_TYPE (right) == AOP_CRY)
4468 genMultbits (left, right, result, ic);
4472 /* if both are of size == 1 */
4473 if (AOP_SIZE (left) == 1 &&
4474 AOP_SIZE (right) == 1)
4476 genMultOneByte (left, right, result, ic);
4480 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4481 /* use the ds390 ARITHMETIC accel UNIT */
4482 genMultTwoByte (left, right, result, ic);
4485 /* should have been converted to function call */
4489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4490 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4491 freeAsmop (result, NULL, ic, TRUE);
4494 /*-----------------------------------------------------------------*/
4495 /* genDivbits :- division of bits */
4496 /*-----------------------------------------------------------------*/
4498 genDivbits (operand * left,
4506 /* the result must be bit */
4507 LOAD_AB_FOR_DIV (left, right, l);
4508 emitcode ("div", "ab");
4509 emitcode ("rrc", "a");
4510 aopOp(result, ic, TRUE, FALSE);
4512 aopPut (AOP (result), "c", 0);
4515 /*-----------------------------------------------------------------*/
4516 /* genDivOneByte : 8 bit division */
4517 /*-----------------------------------------------------------------*/
4519 genDivOneByte (operand * left,
4524 sym_link *opetype = operandType (result);
4530 /* signed or unsigned */
4531 if (SPEC_USIGN (opetype))
4533 /* unsigned is easy */
4534 LOAD_AB_FOR_DIV (left, right, l);
4535 emitcode ("div", "ab");
4538 aopOp(result, ic, TRUE, FALSE);
4539 aopPut (AOP (result), "a", 0);
4542 size = AOP_SIZE (result) - 1;
4546 aopPut (AOP (result), zero, offset++);
4551 /* signed is a little bit more difficult */
4553 /* save the signs of the operands */
4554 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4556 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4557 emitcode ("push", "acc"); /* save it on the stack */
4559 /* now sign adjust for both left & right */
4560 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4562 lbl = newiTempLabel (NULL);
4563 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4564 emitcode ("cpl", "a");
4565 emitcode ("inc", "a");
4566 emitcode ("", "!tlabeldef", (lbl->key + 100));
4567 emitcode ("mov", "b,a");
4569 /* sign adjust left side */
4570 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4573 lbl = newiTempLabel (NULL);
4574 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4575 emitcode ("cpl", "a");
4576 emitcode ("inc", "a");
4577 emitcode ("", "!tlabeldef", (lbl->key + 100));
4579 /* now the division */
4580 emitcode ("nop", "; workaround for DS80C390 div bug.");
4581 emitcode ("div", "ab");
4582 /* we are interested in the lower order
4584 emitcode ("mov", "b,a");
4585 lbl = newiTempLabel (NULL);
4586 emitcode ("pop", "acc");
4587 /* if there was an over flow we don't
4588 adjust the sign of the result */
4589 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4590 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4592 emitcode ("clr", "a");
4593 emitcode ("subb", "a,b");
4594 emitcode ("mov", "b,a");
4595 emitcode ("", "!tlabeldef", (lbl->key + 100));
4597 /* now we are done */
4598 _G.accInUse++; _G.bInUse++;
4599 aopOp(result, ic, TRUE, FALSE);
4601 aopPut (AOP (result), "b", 0);
4603 size = AOP_SIZE (result) - 1;
4607 emitcode ("mov", "c,b.7");
4608 emitcode ("subb", "a,acc");
4612 aopPut (AOP (result), "a", offset++);
4614 _G.accInUse--; _G.bInUse--;
4618 /*-----------------------------------------------------------------*/
4619 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4620 /*-----------------------------------------------------------------*/
4621 static void genDivTwoByte (operand *left, operand *right,
4622 operand *result, iCode *ic)
4624 sym_link *retype = getSpec(operandType(right));
4625 sym_link *letype = getSpec(operandType(left));
4626 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4629 /* save EA bit in F1 */
4630 lbl = newiTempLabel(NULL);
4631 emitcode ("setb","F1");
4632 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4633 emitcode ("clr","F1");
4634 emitcode("","!tlabeldef",lbl->key+100);
4636 /* load up MA with left */
4638 emitcode("clr","F0");
4639 lbl = newiTempLabel(NULL);
4640 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4641 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4642 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4643 emitcode ("xch", "a,b");
4644 emitcode ("cpl","a");
4645 emitcode ("add", "a,#1");
4646 emitcode ("xch", "a,b");
4647 emitcode ("cpl", "a"); // msb
4648 emitcode ("addc","a,#0");
4649 emitcode ("setb","F0");
4650 emitcode ("","!tlabeldef",lbl->key+100);
4651 emitcode ("mov","ma,b");
4652 emitcode ("mov","ma,a");
4654 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4655 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4658 /* load up MB with right */
4660 if (AOP_TYPE(right) == AOP_LIT) {
4661 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4663 lbl = newiTempLabel(NULL);
4664 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4665 emitcode("setb","F0");
4666 emitcode ("","!tlabeldef",lbl->key+100);
4669 emitcode ("mov","mb,#!constbyte",val & 0xff);
4670 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4672 lbl = newiTempLabel(NULL);
4673 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4674 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4675 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4676 emitcode ("xch", "a,b");
4677 emitcode ("cpl","a");
4678 emitcode ("add", "a,#1");
4679 emitcode ("xch", "a,b");
4680 emitcode ("cpl", "a"); // msb
4681 emitcode ("addc", "a,#0");
4682 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4683 emitcode ("setb","F0");
4684 emitcode ("","!tlabeldef",lbl->key+100);
4685 emitcode ("mov","mb,b");
4686 emitcode ("mov","mb,a");
4689 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4690 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4693 /* wait for multiplication to finish */
4694 lbl = newiTempLabel(NULL);
4695 emitcode("","!tlabeldef", lbl->key+100);
4696 emitcode("mov","a,mcnt1");
4697 emitcode("anl","a,#!constbyte",0x80);
4698 emitcode("jnz","!tlabel",lbl->key+100);
4700 freeAsmop (left, NULL, ic, TRUE);
4701 freeAsmop (right, NULL, ic,TRUE);
4702 aopOp(result, ic, TRUE, FALSE);
4704 /* if unsigned then simple */
4706 aopPut(AOP(result),"ma",1);
4707 aopPut(AOP(result),"ma",0);
4709 emitcode("push","ma");
4711 /* negate result if needed */
4712 lbl = newiTempLabel(NULL);
4713 emitcode("jnb","F0,!tlabel",lbl->key+100);
4714 emitcode("cpl","a");
4715 emitcode("add","a,#1");
4716 emitcode("","!tlabeldef", lbl->key+100);
4717 aopPut(AOP(result),"a",0);
4718 emitcode("pop","acc");
4719 lbl = newiTempLabel(NULL);
4720 emitcode("jnb","F0,!tlabel",lbl->key+100);
4721 emitcode("cpl","a");
4722 emitcode("addc","a,#0");
4723 emitcode("","!tlabeldef", lbl->key+100);
4724 aopPut(AOP(result),"a",1);
4726 freeAsmop (result, NULL, ic, TRUE);
4727 /* restore EA bit in F1 */
4728 lbl = newiTempLabel(NULL);
4729 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4730 emitcode ("setb","EA");
4731 emitcode("","!tlabeldef",lbl->key+100);
4735 /*-----------------------------------------------------------------*/
4736 /* genDiv - generates code for division */
4737 /*-----------------------------------------------------------------*/
4741 operand *left = IC_LEFT (ic);
4742 operand *right = IC_RIGHT (ic);
4743 operand *result = IC_RESULT (ic);
4745 D (emitcode (";", "genDiv "););
4747 /* assign the amsops */
4750 /* special cases first */
4752 if (AOP_TYPE (left) == AOP_CRY &&
4753 AOP_TYPE (right) == AOP_CRY)
4755 genDivbits (left, right, result, ic);
4759 /* if both are of size == 1 */
4760 if (AOP_SIZE (left) == 1 &&
4761 AOP_SIZE (right) == 1)
4763 genDivOneByte (left, right, result, ic);
4767 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4768 /* use the ds390 ARITHMETIC accel UNIT */
4769 genDivTwoByte (left, right, result, ic);
4772 /* should have been converted to function call */
4775 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4776 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4777 freeAsmop (result, NULL, ic, TRUE);
4780 /*-----------------------------------------------------------------*/
4781 /* genModbits :- modulus of bits */
4782 /*-----------------------------------------------------------------*/
4784 genModbits (operand * left,
4792 /* the result must be bit */
4793 LOAD_AB_FOR_DIV (left, right, l);
4794 emitcode ("div", "ab");
4795 emitcode ("mov", "a,b");
4796 emitcode ("rrc", "a");
4797 aopOp(result, ic, TRUE, FALSE);
4798 aopPut (AOP (result), "c", 0);
4801 /*-----------------------------------------------------------------*/
4802 /* genModOneByte : 8 bit modulus */
4803 /*-----------------------------------------------------------------*/
4805 genModOneByte (operand * left,
4810 sym_link *opetype = operandType (result);
4814 /* signed or unsigned */
4815 if (SPEC_USIGN (opetype))
4817 /* unsigned is easy */
4818 LOAD_AB_FOR_DIV (left, right, l);
4819 emitcode ("div", "ab");
4820 aopOp(result, ic, TRUE, FALSE);
4821 aopPut (AOP (result), "b", 0);
4825 /* signed is a little bit more difficult */
4827 /* save the signs of the operands */
4828 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4831 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4832 emitcode ("push", "acc"); /* save it on the stack */
4834 /* now sign adjust for both left & right */
4835 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4838 lbl = newiTempLabel (NULL);
4839 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4840 emitcode ("cpl", "a");
4841 emitcode ("inc", "a");
4842 emitcode ("", "!tlabeldef", (lbl->key + 100));
4843 emitcode ("mov", "b,a");
4845 /* sign adjust left side */
4846 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4849 lbl = newiTempLabel (NULL);
4850 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4851 emitcode ("cpl", "a");
4852 emitcode ("inc", "a");
4853 emitcode ("", "!tlabeldef", (lbl->key + 100));
4855 /* now the multiplication */
4856 emitcode ("nop", "; workaround for DS80C390 div bug.");
4857 emitcode ("div", "ab");
4858 /* we are interested in the lower order
4860 lbl = newiTempLabel (NULL);
4861 emitcode ("pop", "acc");
4862 /* if there was an over flow we don't
4863 adjust the sign of the result */
4864 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4865 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4867 emitcode ("clr", "a");
4868 emitcode ("subb", "a,b");
4869 emitcode ("mov", "b,a");
4870 emitcode ("", "!tlabeldef", (lbl->key + 100));
4873 /* now we are done */
4874 aopOp(result, ic, TRUE, FALSE);
4875 aopPut (AOP (result), "b", 0);
4880 /*-----------------------------------------------------------------*/
4881 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4882 /*-----------------------------------------------------------------*/
4883 static void genModTwoByte (operand *left, operand *right,
4884 operand *result, iCode *ic)
4886 sym_link *retype = getSpec(operandType(right));
4887 sym_link *letype = getSpec(operandType(left));
4888 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4891 /* load up MA with left */
4892 /* save EA bit in F1 */
4893 lbl = newiTempLabel(NULL);
4894 emitcode ("setb","F1");
4895 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4896 emitcode ("clr","F1");
4897 emitcode("","!tlabeldef",lbl->key+100);
4900 lbl = newiTempLabel(NULL);
4901 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4902 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4903 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4904 emitcode ("xch", "a,b");
4905 emitcode ("cpl","a");
4906 emitcode ("add", "a,#1");
4907 emitcode ("xch", "a,b");
4908 emitcode ("cpl", "a"); // msb
4909 emitcode ("addc","a,#0");
4910 emitcode ("","!tlabeldef",lbl->key+100);
4911 emitcode ("mov","ma,b");
4912 emitcode ("mov","ma,a");
4914 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4915 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4918 /* load up MB with right */
4920 if (AOP_TYPE(right) == AOP_LIT) {
4921 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4925 emitcode ("mov","mb,#!constbyte",val & 0xff);
4926 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4928 lbl = newiTempLabel(NULL);
4929 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4930 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4931 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4932 emitcode ("xch", "a,b");
4933 emitcode ("cpl","a");
4934 emitcode ("add", "a,#1");
4935 emitcode ("xch", "a,b");
4936 emitcode ("cpl", "a"); // msb
4937 emitcode ("addc", "a,#0");
4938 emitcode ("","!tlabeldef",lbl->key+100);
4939 emitcode ("mov","mb,b");
4940 emitcode ("mov","mb,a");
4943 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4944 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4947 /* wait for multiplication to finish */
4948 lbl = newiTempLabel(NULL);
4949 emitcode("","!tlabeldef", lbl->key+100);
4950 emitcode("mov","a,mcnt1");
4951 emitcode("anl","a,#!constbyte",0x80);
4952 emitcode("jnz","!tlabel",lbl->key+100);
4954 freeAsmop (left, NULL, ic, TRUE);
4955 freeAsmop (right, NULL, ic,TRUE);
4956 aopOp(result, ic, TRUE, FALSE);
4958 aopPut(AOP(result),"mb",1);
4959 aopPut(AOP(result),"mb",0);
4960 freeAsmop (result, NULL, ic, TRUE);
4962 /* restore EA bit in F1 */
4963 lbl = newiTempLabel(NULL);
4964 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4965 emitcode ("setb","EA");
4966 emitcode("","!tlabeldef",lbl->key+100);
4970 /*-----------------------------------------------------------------*/
4971 /* genMod - generates code for division */
4972 /*-----------------------------------------------------------------*/
4976 operand *left = IC_LEFT (ic);
4977 operand *right = IC_RIGHT (ic);
4978 operand *result = IC_RESULT (ic);
4980 D (emitcode (";", "genMod "); );
4982 /* assign the amsops */
4985 /* special cases first */
4987 if (AOP_TYPE (left) == AOP_CRY &&
4988 AOP_TYPE (right) == AOP_CRY)
4990 genModbits (left, right, result, ic);
4994 /* if both are of size == 1 */
4995 if (AOP_SIZE (left) == 1 &&
4996 AOP_SIZE (right) == 1)
4998 genModOneByte (left, right, result, ic);
5002 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5003 /* use the ds390 ARITHMETIC accel UNIT */
5004 genModTwoByte (left, right, result, ic);
5008 /* should have been converted to function call */
5012 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5013 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5014 freeAsmop (result, NULL, ic, TRUE);
5017 /*-----------------------------------------------------------------*/
5018 /* genIfxJump :- will create a jump depending on the ifx */
5019 /*-----------------------------------------------------------------*/
5021 genIfxJump (iCode * ic, char *jval)
5024 symbol *tlbl = newiTempLabel (NULL);
5027 D (emitcode (";", "genIfxJump ");
5030 /* if true label then we jump if condition
5034 jlbl = IC_TRUE (ic);
5035 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5036 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5040 /* false label is present */
5041 jlbl = IC_FALSE (ic);
5042 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5043 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5045 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5046 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5048 emitcode (inst, "!tlabel", tlbl->key + 100);
5049 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5050 emitcode ("", "!tlabeldef", tlbl->key + 100);
5052 /* mark the icode as generated */
5056 /*-----------------------------------------------------------------*/
5057 /* genCmp :- greater or less than comparison */
5058 /*-----------------------------------------------------------------*/
5060 genCmp (operand * left, operand * right,
5061 iCode * ic, iCode * ifx, int sign)
5063 int size, offset = 0;
5064 unsigned long lit = 0L;
5067 D (emitcode (";", "genCmp");
5070 result = IC_RESULT (ic);
5072 /* if left & right are bit variables */
5073 if (AOP_TYPE (left) == AOP_CRY &&
5074 AOP_TYPE (right) == AOP_CRY)
5076 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5077 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5081 /* subtract right from left if at the
5082 end the carry flag is set then we know that
5083 left is greater than right */
5084 size = max (AOP_SIZE (left), AOP_SIZE (right));
5086 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5087 if ((size == 1) && !sign &&
5088 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5090 symbol *lbl = newiTempLabel (NULL);
5091 emitcode ("cjne", "%s,%s,!tlabel",
5092 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5093 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5095 emitcode ("", "!tlabeldef", lbl->key + 100);
5099 if (AOP_TYPE (right) == AOP_LIT)
5101 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5102 /* optimize if(x < 0) or if(x >= 0) */
5111 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5113 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5114 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5116 aopOp (result, ic, FALSE, FALSE);
5118 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5120 freeAsmop (result, NULL, ic, TRUE);
5121 genIfxJump (ifx, "acc.7");
5126 emitcode ("rlc", "a");
5128 goto release_freedLR;
5136 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5137 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5138 //emitcode (";", "genCmp #2");
5139 if (sign && (size == 0))
5141 //emitcode (";", "genCmp #3");
5142 emitcode ("xrl", "a,#!constbyte",0x80);
5143 if (AOP_TYPE (right) == AOP_LIT)
5145 unsigned long lit = (unsigned long)
5146 floatFromVal (AOP (right)->aopu.aop_lit);
5147 //emitcode (";", "genCmp #3.1");
5148 emitcode ("subb", "a,#!constbyte",
5149 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5153 //emitcode (";", "genCmp #3.2");
5154 if (AOP_NEEDSACC (right))
5156 emitcode ("push", "acc");
5158 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5159 FALSE, FALSE, FALSE));
5160 emitcode ("xrl", "b,#!constbyte",0x80);
5161 if (AOP_NEEDSACC (right))
5163 emitcode ("pop", "acc");
5165 emitcode ("subb", "a,b");
5172 //emitcode (";", "genCmp #4");
5173 if (AOP_NEEDSACC (right))
5176 //emitcode (";", "genCmp #4.1");
5177 emitcode ("xch", "a, b");
5178 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5179 emitcode ("xch", "a, b");
5184 //emitcode (";", "genCmp #4.2");
5185 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5188 emitcode ("subb", "a,%s", s);
5195 /* Don't need the left & right operands any more; do need the result. */
5196 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5197 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5199 aopOp (result, ic, FALSE, FALSE);
5203 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5209 /* if the result is used in the next
5210 ifx conditional branch then generate
5211 code a little differently */
5214 genIfxJump (ifx, "c");
5220 /* leave the result in acc */
5222 freeAsmop (result, NULL, ic, TRUE);
5225 /*-----------------------------------------------------------------*/
5226 /* genCmpGt :- greater than comparison */
5227 /*-----------------------------------------------------------------*/
5229 genCmpGt (iCode * ic, iCode * ifx)
5231 operand *left, *right;
5232 sym_link *letype, *retype;
5235 D (emitcode (";", "genCmpGt ");
5238 left = IC_LEFT (ic);
5239 right = IC_RIGHT (ic);
5241 letype = getSpec (operandType (left));
5242 retype = getSpec (operandType (right));
5243 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5245 /* assign the left & right amsops */
5248 genCmp (right, left, ic, ifx, sign);
5251 /*-----------------------------------------------------------------*/
5252 /* genCmpLt - less than comparisons */
5253 /*-----------------------------------------------------------------*/
5255 genCmpLt (iCode * ic, iCode * ifx)
5257 operand *left, *right;
5258 sym_link *letype, *retype;
5261 D (emitcode (";", "genCmpLt "););
5263 left = IC_LEFT (ic);
5264 right = IC_RIGHT (ic);
5266 letype = getSpec (operandType (left));
5267 retype = getSpec (operandType (right));
5268 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5270 /* assign the left & right amsops */
5273 genCmp (left, right, ic, ifx, sign);
5276 /*-----------------------------------------------------------------*/
5277 /* gencjneshort - compare and jump if not equal */
5278 /*-----------------------------------------------------------------*/
5280 gencjneshort (operand * left, operand * right, symbol * lbl)
5282 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5284 unsigned long lit = 0L;
5286 D (emitcode (";", "gencjneshort");
5289 /* if the left side is a literal or
5290 if the right is in a pointer register and left
5292 if ((AOP_TYPE (left) == AOP_LIT) ||
5293 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5300 if (AOP_TYPE (right) == AOP_LIT)
5301 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5303 if (opIsGptr (left) || opIsGptr (right))
5305 /* We are comparing a generic pointer to something.
5306 * Exclude the generic type byte from the comparison.
5309 D (emitcode (";", "cjneshort: generic ptr special case.");
5314 /* if the right side is a literal then anything goes */
5315 if (AOP_TYPE (right) == AOP_LIT &&
5316 AOP_TYPE (left) != AOP_DIR)
5320 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5322 emitcode ("cjne", "a,%s,!tlabel",
5323 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5329 /* if the right side is in a register or in direct space or
5330 if the left is a pointer register & right is not */
5331 else if (AOP_TYPE (right) == AOP_REG ||
5332 AOP_TYPE (right) == AOP_DIR ||
5333 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5334 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5338 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5339 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5340 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5341 emitcode ("jnz", "!tlabel", lbl->key + 100);
5343 emitcode ("cjne", "a,%s,!tlabel",
5344 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5351 /* right is a pointer reg need both a & b */
5354 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5355 if (strcmp (l, "b"))
5356 emitcode ("mov", "b,%s", l);
5357 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5358 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5364 /*-----------------------------------------------------------------*/
5365 /* gencjne - compare and jump if not equal */
5366 /*-----------------------------------------------------------------*/
5368 gencjne (operand * left, operand * right, symbol * lbl)
5370 symbol *tlbl = newiTempLabel (NULL);
5372 D (emitcode (";", "gencjne");
5375 gencjneshort (left, right, lbl);
5377 emitcode ("mov", "a,%s", one);
5378 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5379 emitcode ("", "!tlabeldef", lbl->key + 100);
5380 emitcode ("clr", "a");
5381 emitcode ("", "!tlabeldef", tlbl->key + 100);
5384 /*-----------------------------------------------------------------*/
5385 /* genCmpEq - generates code for equal to */
5386 /*-----------------------------------------------------------------*/
5388 genCmpEq (iCode * ic, iCode * ifx)
5390 operand *left, *right, *result;
5392 D (emitcode (";", "genCmpEq ");
5396 AOP_SET_LOCALS (ic);
5398 /* if literal, literal on the right or
5399 if the right is in a pointer register and left
5401 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5402 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5404 operand *t = IC_RIGHT (ic);
5405 IC_RIGHT (ic) = IC_LEFT (ic);
5409 if (ifx && /* !AOP_SIZE(result) */
5410 OP_SYMBOL (result) &&
5411 OP_SYMBOL (result)->regType == REG_CND)
5414 /* if they are both bit variables */
5415 if (AOP_TYPE (left) == AOP_CRY &&
5416 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5418 if (AOP_TYPE (right) == AOP_LIT)
5420 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5423 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5424 emitcode ("cpl", "c");
5428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5432 emitcode ("clr", "c");
5434 /* AOP_TYPE(right) == AOP_CRY */
5438 symbol *lbl = newiTempLabel (NULL);
5439 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5440 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5441 emitcode ("cpl", "c");
5442 emitcode ("", "!tlabeldef", (lbl->key + 100));
5444 /* if true label then we jump if condition
5446 tlbl = newiTempLabel (NULL);
5449 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5450 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5454 emitcode ("jc", "!tlabel", tlbl->key + 100);
5455 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5457 emitcode ("", "!tlabeldef", tlbl->key + 100);
5461 tlbl = newiTempLabel (NULL);
5462 gencjneshort (left, right, tlbl);
5465 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5466 emitcode ("", "!tlabeldef", tlbl->key + 100);
5470 symbol *lbl = newiTempLabel (NULL);
5471 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5472 emitcode ("", "!tlabeldef", tlbl->key + 100);
5473 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5474 emitcode ("", "!tlabeldef", lbl->key + 100);
5477 /* mark the icode as generated */
5480 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5481 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5485 /* if they are both bit variables */
5486 if (AOP_TYPE (left) == AOP_CRY &&
5487 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5489 if (AOP_TYPE (right) == AOP_LIT)
5491 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5494 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5495 emitcode ("cpl", "c");
5499 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5503 emitcode ("clr", "c");
5505 /* AOP_TYPE(right) == AOP_CRY */
5509 symbol *lbl = newiTempLabel (NULL);
5510 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5511 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5512 emitcode ("cpl", "c");
5513 emitcode ("", "!tlabeldef", (lbl->key + 100));
5516 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5517 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5519 aopOp (result, ic, TRUE, FALSE);
5522 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5529 genIfxJump (ifx, "c");
5532 /* if the result is used in an arithmetic operation
5533 then put the result in place */
5538 gencjne (left, right, newiTempLabel (NULL));
5540 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5541 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5543 aopOp (result, ic, TRUE, FALSE);
5545 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5547 aopPut (AOP (result), "a", 0);
5552 genIfxJump (ifx, "a");
5555 /* if the result is used in an arithmetic operation
5556 then put the result in place */
5557 if (AOP_TYPE (result) != AOP_CRY)
5559 /* leave the result in acc */
5563 freeAsmop (result, NULL, ic, TRUE);
5566 /*-----------------------------------------------------------------*/
5567 /* ifxForOp - returns the icode containing the ifx for operand */
5568 /*-----------------------------------------------------------------*/
5570 ifxForOp (operand * op, iCode * ic)
5572 /* if true symbol then needs to be assigned */
5573 if (IS_TRUE_SYMOP (op))
5576 /* if this has register type condition and
5577 the next instruction is ifx with the same operand
5578 and live to of the operand is upto the ifx only then */
5580 ic->next->op == IFX &&
5581 IC_COND (ic->next)->key == op->key &&
5582 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5587 /*-----------------------------------------------------------------*/
5588 /* hasInc - operand is incremented before any other use */
5589 /*-----------------------------------------------------------------*/
5591 hasInc (operand *op, iCode *ic, int osize)
5593 sym_link *type = operandType(op);
5594 sym_link *retype = getSpec (type);
5595 iCode *lic = ic->next;
5598 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5599 if (!IS_SYMOP(op)) return NULL;
5601 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5602 if (IS_AGGREGATE(type->next)) return NULL;
5603 if (osize != (isize = getSize(type->next))) return NULL;
5606 /* if operand of the form op = op + <sizeof *op> */
5607 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5608 isOperandEqual(IC_RESULT(lic),op) &&
5609 isOperandLiteral(IC_RIGHT(lic)) &&
5610 operandLitValue(IC_RIGHT(lic)) == isize) {
5613 /* if the operand used or deffed */
5614 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5617 /* if GOTO or IFX */
5618 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5624 /*-----------------------------------------------------------------*/
5625 /* genAndOp - for && operation */
5626 /*-----------------------------------------------------------------*/
5628 genAndOp (iCode * ic)
5630 operand *left, *right, *result;
5633 D (emitcode (";", "genAndOp "););
5635 /* note here that && operations that are in an
5636 if statement are taken away by backPatchLabels
5637 only those used in arthmetic operations remain */
5639 AOP_SET_LOCALS (ic);
5641 /* if both are bit variables */
5642 if (AOP_TYPE (left) == AOP_CRY &&
5643 AOP_TYPE (right) == AOP_CRY)
5645 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5646 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5648 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5650 aopOp (result,ic,FALSE, FALSE);
5655 tlbl = newiTempLabel (NULL);
5657 emitcode ("jz", "!tlabel", tlbl->key + 100);
5659 emitcode ("", "!tlabeldef", tlbl->key + 100);
5660 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5661 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5663 aopOp (result,ic,FALSE, FALSE);
5666 freeAsmop (result, NULL, ic, TRUE);
5670 /*-----------------------------------------------------------------*/
5671 /* genOrOp - for || operation */
5672 /*-----------------------------------------------------------------*/
5674 genOrOp (iCode * ic)
5676 operand *left, *right, *result;
5679 D (emitcode (";", "genOrOp "););
5681 /* note here that || operations that are in an
5682 if statement are taken away by backPatchLabels
5683 only those used in arthmetic operations remain */
5685 AOP_SET_LOCALS (ic);
5687 /* if both are bit variables */
5688 if (AOP_TYPE (left) == AOP_CRY &&
5689 AOP_TYPE (right) == AOP_CRY)
5691 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5692 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5693 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5694 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5696 aopOp (result,ic,FALSE, FALSE);
5702 tlbl = newiTempLabel (NULL);
5704 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5706 emitcode ("", "!tlabeldef", tlbl->key + 100);
5707 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5708 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5710 aopOp (result,ic,FALSE, FALSE);
5715 freeAsmop (result, NULL, ic, TRUE);
5718 /*-----------------------------------------------------------------*/
5719 /* isLiteralBit - test if lit == 2^n */
5720 /*-----------------------------------------------------------------*/
5722 isLiteralBit (unsigned long lit)
5724 unsigned long pw[32] =
5725 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5726 0x100L, 0x200L, 0x400L, 0x800L,
5727 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5728 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5729 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5730 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5731 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5734 for (idx = 0; idx < 32; idx++)
5740 /*-----------------------------------------------------------------*/
5741 /* continueIfTrue - */
5742 /*-----------------------------------------------------------------*/
5744 continueIfTrue (iCode * ic)
5747 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5751 /*-----------------------------------------------------------------*/
5753 /*-----------------------------------------------------------------*/
5755 jumpIfTrue (iCode * ic)
5758 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5762 /*-----------------------------------------------------------------*/
5763 /* jmpTrueOrFalse - */
5764 /*-----------------------------------------------------------------*/
5766 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5768 // ugly but optimized by peephole
5771 symbol *nlbl = newiTempLabel (NULL);
5772 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5773 emitcode ("", "!tlabeldef", tlbl->key + 100);
5774 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5775 emitcode ("", "!tlabeldef", nlbl->key + 100);
5779 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5780 emitcode ("", "!tlabeldef", tlbl->key + 100);
5785 // Generate code to perform a bit-wise logic operation
5786 // on two operands in far space (assumed to already have been
5787 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5788 // in far space. This requires pushing the result on the stack
5789 // then popping it into the result.
5791 genFarFarLogicOp(iCode *ic, char *logicOp)
5793 int size, resultSize, compSize;
5797 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5798 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5799 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5801 _startLazyDPSEvaluation();
5802 for (size = compSize; (size--); offset++)
5804 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5805 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5806 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5808 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5809 emitcode ("push", "acc");
5811 _endLazyDPSEvaluation();
5813 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5814 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5815 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5817 resultSize = AOP_SIZE(IC_RESULT(ic));
5819 ADJUST_PUSHED_RESULT(compSize, resultSize);
5821 _startLazyDPSEvaluation();
5824 emitcode ("pop", "acc");
5825 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5827 _endLazyDPSEvaluation();
5828 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5832 /*-----------------------------------------------------------------*/
5833 /* genAnd - code for and */
5834 /*-----------------------------------------------------------------*/
5836 genAnd (iCode * ic, iCode * ifx)
5838 operand *left, *right, *result;
5839 int size, offset = 0;
5840 unsigned long lit = 0L;
5845 D (emitcode (";", "genAnd "););
5847 AOP_OP_3_NOFATAL (ic, pushResult);
5848 AOP_SET_LOCALS (ic);
5852 genFarFarLogicOp(ic, "anl");
5857 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5859 AOP_TYPE (left), AOP_TYPE (right));
5860 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5862 AOP_SIZE (left), AOP_SIZE (right));
5865 /* if left is a literal & right is not then exchange them */
5866 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5867 #ifdef LOGIC_OPS_BROKEN
5868 || AOP_NEEDSACC (left)
5872 operand *tmp = right;
5877 /* if result = right then exchange them */
5878 if (sameRegs (AOP (result), AOP (right)))
5880 operand *tmp = right;
5885 /* if right is bit then exchange them */
5886 if (AOP_TYPE (right) == AOP_CRY &&
5887 AOP_TYPE (left) != AOP_CRY)
5889 operand *tmp = right;
5893 if (AOP_TYPE (right) == AOP_LIT)
5894 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5896 size = AOP_SIZE (result);
5899 // result = bit & yy;
5900 if (AOP_TYPE (left) == AOP_CRY)
5902 // c = bit & literal;
5903 if (AOP_TYPE (right) == AOP_LIT)
5907 if (size && sameRegs (AOP (result), AOP (left)))
5910 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5915 if (size && (AOP_TYPE (result) == AOP_CRY))
5917 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5920 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5925 emitcode ("clr", "c");
5930 if (AOP_TYPE (right) == AOP_CRY)
5933 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5934 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5939 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5941 emitcode ("rrc", "a");
5942 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5950 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5951 genIfxJump (ifx, "c");
5955 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5956 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5957 if ((AOP_TYPE (right) == AOP_LIT) &&
5958 (AOP_TYPE (result) == AOP_CRY) &&
5959 (AOP_TYPE (left) != AOP_CRY))
5961 int posbit = isLiteralBit (lit);
5966 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5969 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5975 sprintf (buffer, "acc.%d", posbit & 0x07);
5976 genIfxJump (ifx, buffer);
5983 symbol *tlbl = newiTempLabel (NULL);
5984 int sizel = AOP_SIZE (left);
5986 emitcode ("setb", "c");
5989 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5991 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5993 if ((posbit = isLiteralBit (bytelit)) != 0)
5994 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5997 if (bytelit != 0x0FFL)
5998 emitcode ("anl", "a,%s",
5999 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6000 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6005 // bit = left & literal
6008 emitcode ("clr", "c");
6009 emitcode ("", "!tlabeldef", tlbl->key + 100);
6011 // if(left & literal)
6015 jmpTrueOrFalse (ifx, tlbl);
6023 /* if left is same as result */
6024 if (sameRegs (AOP (result), AOP (left)))
6026 for (; size--; offset++)
6028 if (AOP_TYPE (right) == AOP_LIT)
6030 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6032 else if (bytelit == 0)
6033 aopPut (AOP (result), zero, offset);
6034 else if (IS_AOP_PREG (result))
6036 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6037 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6038 aopPut (AOP (result), "a", offset);
6041 emitcode ("anl", "%s,%s",
6042 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6043 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6047 if (AOP_TYPE (left) == AOP_ACC)
6048 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6051 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6052 if (IS_AOP_PREG (result))
6054 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6055 aopPut (AOP (result), "a", offset);
6059 emitcode ("anl", "%s,a",
6060 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6067 // left & result in different registers
6068 if (AOP_TYPE (result) == AOP_CRY)
6071 // if(size), result in bit
6072 // if(!size && ifx), conditional oper: if(left & right)
6073 symbol *tlbl = newiTempLabel (NULL);
6074 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6076 emitcode ("setb", "c");
6079 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6080 emitcode ("anl", "a,%s",
6081 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6083 if (AOP_TYPE(left)==AOP_ACC) {
6084 emitcode("mov", "b,a");
6085 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6086 emitcode("anl", "a,b");
6088 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6089 emitcode ("anl", "a,%s",
6090 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6093 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6099 emitcode ("", "!tlabeldef", tlbl->key + 100);
6103 jmpTrueOrFalse (ifx, tlbl);
6107 for (; (size--); offset++)
6110 // result = left & right
6111 if (AOP_TYPE (right) == AOP_LIT)
6113 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6115 aopPut (AOP (result),
6116 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6120 else if (bytelit == 0)
6122 aopPut (AOP (result), zero, offset);
6125 D (emitcode (";", "better literal AND."););
6126 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6127 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6128 FALSE, FALSE, FALSE));
6133 // faster than result <- left, anl result,right
6134 // and better if result is SFR
6135 if (AOP_TYPE (left) == AOP_ACC)
6137 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6138 FALSE, FALSE, FALSE));
6142 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6143 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6145 emitcode("mov", "b,a");
6149 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6150 emitcode ("anl", "a,%s", rOp);
6153 aopPut (AOP (result), "a", offset);
6159 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6160 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6161 freeAsmop (result, NULL, ic, TRUE);
6165 /*-----------------------------------------------------------------*/
6166 /* genOr - code for or */
6167 /*-----------------------------------------------------------------*/
6169 genOr (iCode * ic, iCode * ifx)
6171 operand *left, *right, *result;
6172 int size, offset = 0;
6173 unsigned long lit = 0L;
6176 D (emitcode (";", "genOr "););
6178 AOP_OP_3_NOFATAL (ic, pushResult);
6179 AOP_SET_LOCALS (ic);
6183 genFarFarLogicOp(ic, "orl");
6189 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6191 AOP_TYPE (left), AOP_TYPE (right));
6192 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6194 AOP_SIZE (left), AOP_SIZE (right));
6197 /* if left is a literal & right is not then exchange them */
6198 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6199 #ifdef LOGIC_OPS_BROKEN
6200 || AOP_NEEDSACC (left) // I think this is a net loss now.
6204 operand *tmp = right;
6209 /* if result = right then exchange them */
6210 if (sameRegs (AOP (result), AOP (right)))
6212 operand *tmp = right;
6217 /* if right is bit then exchange them */
6218 if (AOP_TYPE (right) == AOP_CRY &&
6219 AOP_TYPE (left) != AOP_CRY)
6221 operand *tmp = right;
6225 if (AOP_TYPE (right) == AOP_LIT)
6226 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6228 size = AOP_SIZE (result);
6232 if (AOP_TYPE (left) == AOP_CRY)
6234 if (AOP_TYPE (right) == AOP_LIT)
6236 // c = bit & literal;
6239 // lit != 0 => result = 1
6240 if (AOP_TYPE (result) == AOP_CRY)
6243 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6245 continueIfTrue (ifx);
6248 emitcode ("setb", "c");
6252 // lit == 0 => result = left
6253 if (size && sameRegs (AOP (result), AOP (left)))
6255 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6260 if (AOP_TYPE (right) == AOP_CRY)
6263 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6264 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6269 symbol *tlbl = newiTempLabel (NULL);
6270 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6271 emitcode ("setb", "c");
6272 emitcode ("jb", "%s,!tlabel",
6273 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6275 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6276 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6278 jmpTrueOrFalse (ifx, tlbl);
6284 emitcode ("", "!tlabeldef", tlbl->key + 100);
6293 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6294 genIfxJump (ifx, "c");
6298 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6299 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6300 if ((AOP_TYPE (right) == AOP_LIT) &&
6301 (AOP_TYPE (result) == AOP_CRY) &&
6302 (AOP_TYPE (left) != AOP_CRY))
6308 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6310 continueIfTrue (ifx);
6315 // lit = 0, result = boolean(left)
6317 emitcode ("setb", "c");
6321 symbol *tlbl = newiTempLabel (NULL);
6322 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6324 emitcode ("", "!tlabeldef", tlbl->key + 100);
6328 genIfxJump (ifx, "a");
6336 /* if left is same as result */
6337 if (sameRegs (AOP (result), AOP (left)))
6339 for (; size--; offset++)
6341 if (AOP_TYPE (right) == AOP_LIT)
6343 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6349 if (IS_AOP_PREG (left))
6351 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6352 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6353 aopPut (AOP (result), "a", offset);
6357 emitcode ("orl", "%s,%s",
6358 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6359 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6365 if (AOP_TYPE (left) == AOP_ACC)
6367 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6372 if (IS_AOP_PREG (left))
6374 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6375 aopPut (AOP (result), "a", offset);
6379 emitcode ("orl", "%s,a",
6380 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6388 // left & result in different registers
6389 if (AOP_TYPE (result) == AOP_CRY)
6392 // if(size), result in bit
6393 // if(!size && ifx), conditional oper: if(left | right)
6394 symbol *tlbl = newiTempLabel (NULL);
6395 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6397 emitcode ("setb", "c");
6400 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6401 emitcode ("orl", "a,%s",
6402 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6404 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6405 emitcode ("orl", "a,%s",
6406 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6408 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6414 emitcode ("", "!tlabeldef", tlbl->key + 100);
6418 jmpTrueOrFalse (ifx, tlbl);
6422 _startLazyDPSEvaluation();
6423 for (; (size--); offset++)
6426 // result = left & right
6427 if (AOP_TYPE (right) == AOP_LIT)
6429 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6431 aopPut (AOP (result),
6432 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6436 D (emitcode (";", "better literal OR."););
6437 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6438 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6439 FALSE, FALSE, FALSE));
6444 // faster than result <- left, anl result,right
6445 // and better if result is SFR
6446 if (AOP_TYPE (left) == AOP_ACC)
6448 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6449 FALSE, FALSE, FALSE));
6453 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6455 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6457 emitcode("mov", "b,a");
6461 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6462 emitcode ("orl", "a,%s", rOp);
6465 aopPut (AOP (result), "a", offset);
6467 _endLazyDPSEvaluation();
6472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474 freeAsmop (result, NULL, ic, TRUE);
6477 /*-----------------------------------------------------------------*/
6478 /* genXor - code for xclusive or */
6479 /*-----------------------------------------------------------------*/
6481 genXor (iCode * ic, iCode * ifx)
6483 operand *left, *right, *result;
6484 int size, offset = 0;
6485 unsigned long lit = 0L;
6488 D (emitcode (";", "genXor "););
6490 AOP_OP_3_NOFATAL (ic, pushResult);
6491 AOP_SET_LOCALS (ic);
6495 genFarFarLogicOp(ic, "xrl");
6500 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6502 AOP_TYPE (left), AOP_TYPE (right));
6503 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6505 AOP_SIZE (left), AOP_SIZE (right));
6508 /* if left is a literal & right is not ||
6509 if left needs acc & right does not */
6510 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6511 #ifdef LOGIC_OPS_BROKEN
6512 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6516 operand *tmp = right;
6521 /* if result = right then exchange them */
6522 if (sameRegs (AOP (result), AOP (right)))
6524 operand *tmp = right;
6529 /* if right is bit then exchange them */
6530 if (AOP_TYPE (right) == AOP_CRY &&
6531 AOP_TYPE (left) != AOP_CRY)
6533 operand *tmp = right;
6537 if (AOP_TYPE (right) == AOP_LIT)
6538 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6540 size = AOP_SIZE (result);
6544 if (AOP_TYPE (left) == AOP_CRY)
6546 if (AOP_TYPE (right) == AOP_LIT)
6548 // c = bit & literal;
6551 // lit>>1 != 0 => result = 1
6552 if (AOP_TYPE (result) == AOP_CRY)
6555 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6557 continueIfTrue (ifx);
6560 emitcode ("setb", "c");
6567 // lit == 0, result = left
6568 if (size && sameRegs (AOP (result), AOP (left)))
6570 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6574 // lit == 1, result = not(left)
6575 if (size && sameRegs (AOP (result), AOP (left)))
6577 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6582 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6583 emitcode ("cpl", "c");
6592 symbol *tlbl = newiTempLabel (NULL);
6593 if (AOP_TYPE (right) == AOP_CRY)
6596 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6600 int sizer = AOP_SIZE (right);
6602 // if val>>1 != 0, result = 1
6603 emitcode ("setb", "c");
6606 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6608 // test the msb of the lsb
6609 emitcode ("anl", "a,#!constbyte",0xfe);
6610 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6614 emitcode ("rrc", "a");
6616 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6617 emitcode ("cpl", "c");
6618 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6625 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626 genIfxJump (ifx, "c");
6630 if (sameRegs (AOP (result), AOP (left)))
6632 /* if left is same as result */
6633 for (; size--; offset++)
6635 if (AOP_TYPE (right) == AOP_LIT)
6637 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6639 else if (IS_AOP_PREG (left))
6641 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6642 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6643 aopPut (AOP (result), "a", offset);
6646 emitcode ("xrl", "%s,%s",
6647 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6648 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6652 if (AOP_TYPE (left) == AOP_ACC)
6653 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6656 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6657 if (IS_AOP_PREG (left))
6659 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6660 aopPut (AOP (result), "a", offset);
6663 emitcode ("xrl", "%s,a",
6664 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6671 // left & result in different registers
6672 if (AOP_TYPE (result) == AOP_CRY)
6675 // if(size), result in bit
6676 // if(!size && ifx), conditional oper: if(left ^ right)
6677 symbol *tlbl = newiTempLabel (NULL);
6678 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6681 emitcode ("setb", "c");
6684 if ((AOP_TYPE (right) == AOP_LIT) &&
6685 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6687 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6691 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6692 emitcode ("xrl", "a,%s",
6693 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6695 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6696 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6698 emitcode("mov", "b,a");
6702 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6703 emitcode ("xrl", "a,%s", rOp);
6706 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6712 emitcode ("", "!tlabeldef", tlbl->key + 100);
6716 jmpTrueOrFalse (ifx, tlbl);
6720 for (; (size--); offset++)
6723 // result = left & right
6724 if (AOP_TYPE (right) == AOP_LIT)
6726 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6728 aopPut (AOP (result),
6729 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6733 D (emitcode (";", "better literal XOR."););
6734 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6735 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6736 FALSE, FALSE, FALSE));
6740 // faster than result <- left, anl result,right
6741 // and better if result is SFR
6742 if (AOP_TYPE (left) == AOP_ACC)
6744 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6745 FALSE, FALSE, FALSE));
6749 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6750 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6752 emitcode("mov", "b,a");
6756 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6757 emitcode ("xrl", "a,%s", rOp);
6760 aopPut (AOP (result), "a", offset);
6767 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6768 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6769 freeAsmop (result, NULL, ic, TRUE);
6772 /*-----------------------------------------------------------------*/
6773 /* genInline - write the inline code out */
6774 /*-----------------------------------------------------------------*/
6776 genInline (iCode * ic)
6778 char *buffer, *bp, *bp1;
6780 D (emitcode (";", "genInline ");
6783 _G.inLine += (!options.asmpeep);
6785 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6786 strcpy (buffer, IC_INLINE (ic));
6788 /* emit each line as a code */
6813 /* emitcode("",buffer); */
6814 _G.inLine -= (!options.asmpeep);
6817 /*-----------------------------------------------------------------*/
6818 /* genRRC - rotate right with carry */
6819 /*-----------------------------------------------------------------*/
6823 operand *left, *result;
6824 int size, offset = 0;
6827 D (emitcode (";", "genRRC ");
6830 /* rotate right with carry */
6831 left = IC_LEFT (ic);
6832 result = IC_RESULT (ic);
6833 aopOp (left, ic, FALSE, FALSE);
6834 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6836 /* move it to the result */
6837 size = AOP_SIZE (result);
6841 _startLazyDPSEvaluation ();
6844 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6846 emitcode ("rrc", "a");
6847 if (AOP_SIZE (result) > 1)
6848 aopPut (AOP (result), "a", offset--);
6850 _endLazyDPSEvaluation ();
6852 /* now we need to put the carry into the
6853 highest order byte of the result */
6854 if (AOP_SIZE (result) > 1)
6856 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6859 emitcode ("mov", "acc.7,c");
6860 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6861 freeAsmop (left, NULL, ic, TRUE);
6862 freeAsmop (result, NULL, ic, TRUE);
6865 /*-----------------------------------------------------------------*/
6866 /* genRLC - generate code for rotate left with carry */
6867 /*-----------------------------------------------------------------*/
6871 operand *left, *result;
6872 int size, offset = 0;
6875 D (emitcode (";", "genRLC ");
6878 /* rotate right with carry */
6879 left = IC_LEFT (ic);
6880 result = IC_RESULT (ic);
6881 aopOp (left, ic, FALSE, FALSE);
6882 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6884 /* move it to the result */
6885 size = AOP_SIZE (result);
6889 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6891 emitcode ("add", "a,acc");
6892 if (AOP_SIZE (result) > 1)
6894 aopPut (AOP (result), "a", offset++);
6897 _startLazyDPSEvaluation ();
6900 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6902 emitcode ("rlc", "a");
6903 if (AOP_SIZE (result) > 1)
6904 aopPut (AOP (result), "a", offset++);
6906 _endLazyDPSEvaluation ();
6908 /* now we need to put the carry into the
6909 highest order byte of the result */
6910 if (AOP_SIZE (result) > 1)
6912 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6915 emitcode ("mov", "acc.0,c");
6916 aopPut (AOP (result), "a", 0);
6917 freeAsmop (left, NULL, ic, TRUE);
6918 freeAsmop (result, NULL, ic, TRUE);
6921 /*-----------------------------------------------------------------*/
6922 /* genGetHbit - generates code get highest order bit */
6923 /*-----------------------------------------------------------------*/
6925 genGetHbit (iCode * ic)
6927 operand *left, *result;
6928 left = IC_LEFT (ic);
6929 result = IC_RESULT (ic);
6930 aopOp (left, ic, FALSE, FALSE);
6931 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6933 D (emitcode (";", "genGetHbit ");
6936 /* get the highest order byte into a */
6937 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6938 if (AOP_TYPE (result) == AOP_CRY)
6940 emitcode ("rlc", "a");
6945 emitcode ("rl", "a");
6946 emitcode ("anl", "a,#1");
6951 freeAsmop (left, NULL, ic, TRUE);
6952 freeAsmop (result, NULL, ic, TRUE);
6955 /*-----------------------------------------------------------------*/
6956 /* AccRol - rotate left accumulator by known count */
6957 /*-----------------------------------------------------------------*/
6959 AccRol (int shCount)
6961 shCount &= 0x0007; // shCount : 0..7
6968 emitcode ("rl", "a");
6971 emitcode ("rl", "a");
6972 emitcode ("rl", "a");
6975 emitcode ("swap", "a");
6976 emitcode ("rr", "a");
6979 emitcode ("swap", "a");
6982 emitcode ("swap", "a");
6983 emitcode ("rl", "a");
6986 emitcode ("rr", "a");
6987 emitcode ("rr", "a");
6990 emitcode ("rr", "a");
6995 /*-----------------------------------------------------------------*/
6996 /* AccLsh - left shift accumulator by known count */
6997 /*-----------------------------------------------------------------*/
6999 AccLsh (int shCount)
7004 emitcode ("add", "a,acc");
7005 else if (shCount == 2)
7007 emitcode ("add", "a,acc");
7008 emitcode ("add", "a,acc");
7012 /* rotate left accumulator */
7014 /* and kill the lower order bits */
7015 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7020 /*-----------------------------------------------------------------*/
7021 /* AccRsh - right shift accumulator by known count */
7022 /*-----------------------------------------------------------------*/
7024 AccRsh (int shCount)
7031 emitcode ("rrc", "a");
7035 /* rotate right accumulator */
7036 AccRol (8 - shCount);
7037 /* and kill the higher order bits */
7038 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7043 #ifdef BETTER_LITERAL_SHIFT
7044 /*-----------------------------------------------------------------*/
7045 /* AccSRsh - signed right shift accumulator by known count */
7046 /*-----------------------------------------------------------------*/
7048 AccSRsh (int shCount)
7055 emitcode ("mov", "c,acc.7");
7056 emitcode ("rrc", "a");
7058 else if (shCount == 2)
7060 emitcode ("mov", "c,acc.7");
7061 emitcode ("rrc", "a");
7062 emitcode ("mov", "c,acc.7");
7063 emitcode ("rrc", "a");
7067 tlbl = newiTempLabel (NULL);
7068 /* rotate right accumulator */
7069 AccRol (8 - shCount);
7070 /* and kill the higher order bits */
7071 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7072 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7073 emitcode ("orl", "a,#!constbyte",
7074 (unsigned char) ~SRMask[shCount]);
7075 emitcode ("", "!tlabeldef", tlbl->key + 100);
7081 #ifdef BETTER_LITERAL_SHIFT
7082 /*-----------------------------------------------------------------*/
7083 /* shiftR1Left2Result - shift right one byte from left to result */
7084 /*-----------------------------------------------------------------*/
7086 shiftR1Left2Result (operand * left, int offl,
7087 operand * result, int offr,
7088 int shCount, int sign)
7090 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7091 /* shift right accumulator */
7096 aopPut (AOP (result), "a", offr);
7100 #ifdef BETTER_LITERAL_SHIFT
7101 /*-----------------------------------------------------------------*/
7102 /* shiftL1Left2Result - shift left one byte from left to result */
7103 /*-----------------------------------------------------------------*/
7105 shiftL1Left2Result (operand * left, int offl,
7106 operand * result, int offr, int shCount)
7108 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7109 /* shift left accumulator */
7111 aopPut (AOP (result), "a", offr);
7115 #ifdef BETTER_LITERAL_SHIFT
7116 /*-----------------------------------------------------------------*/
7117 /* movLeft2Result - move byte from left to result */
7118 /*-----------------------------------------------------------------*/
7120 movLeft2Result (operand * left, int offl,
7121 operand * result, int offr, int sign)
7124 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7126 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7128 if (*l == '@' && (IS_AOP_PREG (result)))
7130 emitcode ("mov", "a,%s", l);
7131 aopPut (AOP (result), "a", offr);
7137 aopPut (AOP (result), l, offr);
7141 /* MSB sign in acc.7 ! */
7142 if (getDataSize (left) == offl + 1)
7144 emitcode ("mov", "a,%s", l);
7145 aopPut (AOP (result), "a", offr);
7153 #ifdef BETTER_LITERAL_SHIFT
7154 /*-----------------------------------------------------------------*/
7155 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7156 /*-----------------------------------------------------------------*/
7160 emitcode ("rrc", "a");
7161 emitcode ("xch", "a,%s", x);
7162 emitcode ("rrc", "a");
7163 emitcode ("xch", "a,%s", x);
7167 #ifdef BETTER_LITERAL_SHIFT
7169 /*-----------------------------------------------------------------*/
7170 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7171 /*-----------------------------------------------------------------*/
7175 emitcode ("xch", "a,%s", x);
7176 emitcode ("rlc", "a");
7177 emitcode ("xch", "a,%s", x);
7178 emitcode ("rlc", "a");
7182 #ifdef BETTER_LITERAL_SHIFT
7183 /*-----------------------------------------------------------------*/
7184 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7185 /*-----------------------------------------------------------------*/
7189 emitcode ("xch", "a,%s", x);
7190 emitcode ("add", "a,acc");
7191 emitcode ("xch", "a,%s", x);
7192 emitcode ("rlc", "a");
7196 #ifdef BETTER_LITERAL_SHIFT
7197 /*-----------------------------------------------------------------*/
7198 /* AccAXLsh - left shift a:x by known count (0..7) */
7199 /*-----------------------------------------------------------------*/
7201 AccAXLsh (char *x, int shCount)
7216 case 5: // AAAAABBB:CCCCCDDD
7218 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7220 emitcode ("anl", "a,#!constbyte",
7221 SLMask[shCount]); // BBB00000:CCCCCDDD
7223 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7225 AccRol (shCount); // DDDCCCCC:BBB00000
7227 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7229 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7231 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7233 emitcode ("anl", "a,#!constbyte",
7234 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7236 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7238 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7241 case 6: // AAAAAABB:CCCCCCDD
7242 emitcode ("anl", "a,#!constbyte",
7243 SRMask[shCount]); // 000000BB:CCCCCCDD
7244 emitcode ("mov", "c,acc.0"); // c = B
7245 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7247 AccAXRrl1 (x); // BCCCCCCD:D000000B
7248 AccAXRrl1 (x); // BBCCCCCC:DD000000
7250 emitcode("rrc","a");
7251 emitcode("xch","a,%s", x);
7252 emitcode("rrc","a");
7253 emitcode("mov","c,acc.0"); //<< get correct bit
7254 emitcode("xch","a,%s", x);
7256 emitcode("rrc","a");
7257 emitcode("xch","a,%s", x);
7258 emitcode("rrc","a");
7259 emitcode("xch","a,%s", x);
7262 case 7: // a:x <<= 7
7264 emitcode ("anl", "a,#!constbyte",
7265 SRMask[shCount]); // 0000000B:CCCCCCCD
7267 emitcode ("mov", "c,acc.0"); // c = B
7269 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7271 AccAXRrl1 (x); // BCCCCCCC:D0000000
7280 #ifdef BETTER_LITERAL_SHIFT
7282 /*-----------------------------------------------------------------*/
7283 /* AccAXRsh - right shift a:x known count (0..7) */
7284 /*-----------------------------------------------------------------*/
7286 AccAXRsh (char *x, int shCount)
7294 AccAXRrl1 (x); // 0->a:x
7299 AccAXRrl1 (x); // 0->a:x
7302 AccAXRrl1 (x); // 0->a:x
7307 case 5: // AAAAABBB:CCCCCDDD = a:x
7309 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7311 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7313 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7315 emitcode ("anl", "a,#!constbyte",
7316 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7318 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7320 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7322 emitcode ("anl", "a,#!constbyte",
7323 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7325 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7327 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7329 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7332 case 6: // AABBBBBB:CCDDDDDD
7334 emitcode ("mov", "c,acc.7");
7335 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7337 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7339 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7341 emitcode ("anl", "a,#!constbyte",
7342 SRMask[shCount]); // 000000AA:BBBBBBCC
7345 case 7: // ABBBBBBB:CDDDDDDD
7347 emitcode ("mov", "c,acc.7"); // c = A
7349 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7351 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7353 emitcode ("anl", "a,#!constbyte",
7354 SRMask[shCount]); // 0000000A:BBBBBBBC
7363 #ifdef BETTER_LITERAL_SHIFT
7364 /*-----------------------------------------------------------------*/
7365 /* AccAXRshS - right shift signed a:x known count (0..7) */
7366 /*-----------------------------------------------------------------*/
7368 AccAXRshS (char *x, int shCount)
7376 emitcode ("mov", "c,acc.7");
7377 AccAXRrl1 (x); // s->a:x
7381 emitcode ("mov", "c,acc.7");
7382 AccAXRrl1 (x); // s->a:x
7384 emitcode ("mov", "c,acc.7");
7385 AccAXRrl1 (x); // s->a:x
7390 case 5: // AAAAABBB:CCCCCDDD = a:x
7392 tlbl = newiTempLabel (NULL);
7393 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7395 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7397 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7399 emitcode ("anl", "a,#!constbyte",
7400 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7402 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7404 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7406 emitcode ("anl", "a,#!constbyte",
7407 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7409 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7411 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7413 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7415 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7416 emitcode ("orl", "a,#!constbyte",
7417 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7419 emitcode ("", "!tlabeldef", tlbl->key + 100);
7420 break; // SSSSAAAA:BBBCCCCC
7422 case 6: // AABBBBBB:CCDDDDDD
7424 tlbl = newiTempLabel (NULL);
7425 emitcode ("mov", "c,acc.7");
7426 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7428 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7430 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7432 emitcode ("anl", "a,#!constbyte",
7433 SRMask[shCount]); // 000000AA:BBBBBBCC
7435 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7436 emitcode ("orl", "a,#!constbyte",
7437 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7439 emitcode ("", "!tlabeldef", tlbl->key + 100);
7441 case 7: // ABBBBBBB:CDDDDDDD
7443 tlbl = newiTempLabel (NULL);
7444 emitcode ("mov", "c,acc.7"); // c = A
7446 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7448 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7450 emitcode ("anl", "a,#!constbyte",
7451 SRMask[shCount]); // 0000000A:BBBBBBBC
7453 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7454 emitcode ("orl", "a,#!constbyte",
7455 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7457 emitcode ("", "!tlabeldef", tlbl->key + 100);
7465 #ifdef BETTER_LITERAL_SHIFT
7467 _loadLeftIntoAx(char **lsb,
7473 // Get the initial value from left into a pair of registers.
7474 // MSB must be in A, LSB can be any register.
7476 // If the result is held in registers, it is an optimization
7477 // if the LSB can be held in the register which will hold the,
7478 // result LSB since this saves us from having to copy it into
7479 // the result following AccAXLsh.
7481 // If the result is addressed indirectly, this is not a gain.
7482 if (AOP_NEEDSACC(result))
7486 _startLazyDPSEvaluation();
7487 if (AOP_TYPE(left) == AOP_DPTR2)
7490 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7491 // get LSB in DP2_RESULT_REG.
7492 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7493 assert(!strcmp(leftByte, DP2_RESULT_REG));
7497 // get LSB into DP2_RESULT_REG
7498 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7499 if (strcmp(leftByte, DP2_RESULT_REG))
7502 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7505 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7506 assert(strcmp(leftByte, DP2_RESULT_REG));
7509 _endLazyDPSEvaluation();
7510 *lsb = DP2_RESULT_REG;
7514 if (sameRegs (AOP (result), AOP (left)) &&
7515 ((offl + MSB16) == offr))
7517 /* don't crash result[offr] */
7518 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7519 emitcode ("xch", "a,%s",
7520 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7524 movLeft2Result (left, offl, result, offr, 0);
7525 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7527 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7528 assert(strcmp(*lsb,"a"));
7533 _storeAxResults(char *lsb,
7537 _startLazyDPSEvaluation();
7538 if (AOP_NEEDSACC(result))
7540 /* We have to explicitly update the result LSB.
7542 emitcode("xch","a,%s", lsb);
7543 aopPut(AOP(result), "a", offr);
7544 emitcode("mov","a,%s", lsb);
7546 if (getDataSize (result) > 1)
7548 aopPut (AOP (result), "a", offr + MSB16);
7550 _endLazyDPSEvaluation();
7553 /*-----------------------------------------------------------------*/
7554 /* shiftL2Left2Result - shift left two bytes from left to result */
7555 /*-----------------------------------------------------------------*/
7557 shiftL2Left2Result (operand * left, int offl,
7558 operand * result, int offr, int shCount)
7562 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7564 AccAXLsh (lsb, shCount);
7566 _storeAxResults(lsb, result, offr);
7570 #ifdef BETTER_LITERAL_SHIFT
7571 /*-----------------------------------------------------------------*/
7572 /* shiftR2Left2Result - shift right two bytes from left to result */
7573 /*-----------------------------------------------------------------*/
7575 shiftR2Left2Result (operand * left, int offl,
7576 operand * result, int offr,
7577 int shCount, int sign)
7581 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7583 /* a:x >> shCount (x = lsb(result)) */
7586 AccAXRshS(lsb, shCount);
7590 AccAXRsh(lsb, shCount);
7593 _storeAxResults(lsb, result, offr);
7599 /*-----------------------------------------------------------------*/
7600 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7601 /*-----------------------------------------------------------------*/
7603 shiftLLeftOrResult (operand * left, int offl,
7604 operand * result, int offr, int shCount)
7606 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7607 /* shift left accumulator */
7609 /* or with result */
7610 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7611 /* back to result */
7612 aopPut (AOP (result), "a", offr);
7618 /*-----------------------------------------------------------------*/
7619 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7620 /*-----------------------------------------------------------------*/
7622 shiftRLeftOrResult (operand * left, int offl,
7623 operand * result, int offr, int shCount)
7625 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7626 /* shift right accumulator */
7628 /* or with result */
7629 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7630 /* back to result */
7631 aopPut (AOP (result), "a", offr);
7635 #ifdef BETTER_LITERAL_SHIFT
7636 /*-----------------------------------------------------------------*/
7637 /* genlshOne - left shift a one byte quantity by known count */
7638 /*-----------------------------------------------------------------*/
7640 genlshOne (operand * result, operand * left, int shCount)
7642 D (emitcode (";", "genlshOne "););
7643 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7647 #ifdef BETTER_LITERAL_SHIFT
7648 /*-----------------------------------------------------------------*/
7649 /* genlshTwo - left shift two bytes by known amount != 0 */
7650 /*-----------------------------------------------------------------*/
7652 genlshTwo (operand * result, operand * left, int shCount)
7656 D (emitcode (";", "genlshTwo "););
7658 size = getDataSize (result);
7660 /* if shCount >= 8 */
7665 _startLazyDPSEvaluation();
7671 _endLazyDPSEvaluation();
7672 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7673 aopPut (AOP (result), zero, LSB);
7677 movLeft2Result (left, LSB, result, MSB16, 0);
7678 aopPut (AOP (result), zero, LSB);
7679 _endLazyDPSEvaluation();
7684 aopPut (AOP (result), zero, LSB);
7685 _endLazyDPSEvaluation();
7689 /* 1 <= shCount <= 7 */
7694 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7698 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7706 /*-----------------------------------------------------------------*/
7707 /* shiftLLong - shift left one long from left to result */
7708 /* offl = LSB or MSB16 */
7709 /*-----------------------------------------------------------------*/
7711 shiftLLong (operand * left, operand * result, int offr)
7714 int size = AOP_SIZE (result);
7716 if (size >= LSB + offr)
7718 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7720 emitcode ("add", "a,acc");
7721 if (sameRegs (AOP (left), AOP (result)) &&
7722 size >= MSB16 + offr && offr != LSB)
7723 emitcode ("xch", "a,%s",
7724 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7726 aopPut (AOP (result), "a", LSB + offr);
7729 if (size >= MSB16 + offr)
7731 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7733 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7736 emitcode ("rlc", "a");
7737 if (sameRegs (AOP (left), AOP (result)) &&
7738 size >= MSB24 + offr && offr != LSB)
7739 emitcode ("xch", "a,%s",
7740 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7742 aopPut (AOP (result), "a", MSB16 + offr);
7745 if (size >= MSB24 + offr)
7747 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7749 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7752 emitcode ("rlc", "a");
7753 if (sameRegs (AOP (left), AOP (result)) &&
7754 size >= MSB32 + offr && offr != LSB)
7755 emitcode ("xch", "a,%s",
7756 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7758 aopPut (AOP (result), "a", MSB24 + offr);
7761 if (size > MSB32 + offr)
7763 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7765 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7768 emitcode ("rlc", "a");
7769 aopPut (AOP (result), "a", MSB32 + offr);
7772 aopPut (AOP (result), zero, LSB);
7778 /*-----------------------------------------------------------------*/
7779 /* genlshFour - shift four byte by a known amount != 0 */
7780 /*-----------------------------------------------------------------*/
7782 genlshFour (operand * result, operand * left, int shCount)
7786 D (emitcode (";", "genlshFour ");
7789 size = AOP_SIZE (result);
7791 /* if shifting more that 3 bytes */
7796 /* lowest order of left goes to the highest
7797 order of the destination */
7798 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7800 movLeft2Result (left, LSB, result, MSB32, 0);
7801 aopPut (AOP (result), zero, LSB);
7802 aopPut (AOP (result), zero, MSB16);
7803 aopPut (AOP (result), zero, MSB24);
7807 /* more than two bytes */
7808 else if (shCount >= 16)
7810 /* lower order two bytes goes to higher order two bytes */
7812 /* if some more remaining */
7814 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7817 movLeft2Result (left, MSB16, result, MSB32, 0);
7818 movLeft2Result (left, LSB, result, MSB24, 0);
7820 aopPut (AOP (result), zero, MSB16);
7821 aopPut (AOP (result), zero, LSB);
7825 /* if more than 1 byte */
7826 else if (shCount >= 8)
7828 /* lower order three bytes goes to higher order three bytes */
7833 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7835 movLeft2Result (left, LSB, result, MSB16, 0);
7841 movLeft2Result (left, MSB24, result, MSB32, 0);
7842 movLeft2Result (left, MSB16, result, MSB24, 0);
7843 movLeft2Result (left, LSB, result, MSB16, 0);
7844 aopPut (AOP (result), zero, LSB);
7846 else if (shCount == 1)
7847 shiftLLong (left, result, MSB16);
7850 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7851 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7852 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7853 aopPut (AOP (result), zero, LSB);
7858 /* 1 <= shCount <= 7 */
7859 else if (shCount <= 2)
7861 shiftLLong (left, result, LSB);
7863 shiftLLong (result, result, LSB);
7865 /* 3 <= shCount <= 7, optimize */
7868 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7869 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7870 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7875 #ifdef BETTER_LITERAL_SHIFT
7876 /*-----------------------------------------------------------------*/
7877 /* genLeftShiftLiteral - left shifting by known count */
7878 /*-----------------------------------------------------------------*/
7880 genLeftShiftLiteral (operand * left,
7885 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7888 size = getSize (operandType (result));
7890 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7892 /* We only handle certain easy cases so far. */
7894 && (shCount < (size * 8))
7898 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7902 freeAsmop (right, NULL, ic, TRUE);
7904 aopOp(left, ic, FALSE, FALSE);
7905 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7908 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7910 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7911 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7913 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7916 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7918 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7919 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7921 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7927 emitcode ("; shift left ", "result %d, left %d", size,
7931 /* I suppose that the left size >= result size */
7934 _startLazyDPSEvaluation();
7937 movLeft2Result (left, size, result, size, 0);
7939 _endLazyDPSEvaluation();
7941 else if (shCount >= (size * 8))
7943 _startLazyDPSEvaluation();
7946 aopPut (AOP (result), zero, size);
7948 _endLazyDPSEvaluation();
7955 genlshOne (result, left, shCount);
7959 genlshTwo (result, left, shCount);
7963 genlshFour (result, left, shCount);
7967 fprintf(stderr, "*** ack! mystery literal shift!\n");
7971 freeAsmop (left, NULL, ic, TRUE);
7972 freeAsmop (result, NULL, ic, TRUE);
7977 /*-----------------------------------------------------------------*/
7978 /* genLeftShift - generates code for left shifting */
7979 /*-----------------------------------------------------------------*/
7981 genLeftShift (iCode * ic)
7983 operand *left, *right, *result;
7986 symbol *tlbl, *tlbl1;
7988 D (emitcode (";", "genLeftShift "););
7990 right = IC_RIGHT (ic);
7991 left = IC_LEFT (ic);
7992 result = IC_RESULT (ic);
7994 aopOp (right, ic, FALSE, FALSE);
7997 #ifdef BETTER_LITERAL_SHIFT
7998 /* if the shift count is known then do it
7999 as efficiently as possible */
8000 if (AOP_TYPE (right) == AOP_LIT)
8002 if (genLeftShiftLiteral (left, right, result, ic))
8009 /* shift count is unknown then we have to form
8010 a loop get the loop count in B : Note: we take
8011 only the lower order byte since shifting
8012 more that 32 bits make no sense anyway, ( the
8013 largest size of an object can be only 32 bits ) */
8015 if (AOP_TYPE (right) == AOP_LIT)
8017 /* Really should be handled by genLeftShiftLiteral,
8018 * but since I'm too lazy to fix that today, at least we can make
8019 * some small improvement.
8021 emitcode("mov", "b,#!constbyte",
8022 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8026 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8027 emitcode ("inc", "b");
8029 freeAsmop (right, NULL, ic, TRUE);
8030 aopOp (left, ic, FALSE, FALSE);
8031 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8033 /* now move the left to the result if they are not the
8035 if (!sameRegs (AOP (left), AOP (result)) &&
8036 AOP_SIZE (result) > 1)
8039 size = AOP_SIZE (result);
8041 _startLazyDPSEvaluation ();
8044 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8045 if (*l == '@' && (IS_AOP_PREG (result)))
8048 emitcode ("mov", "a,%s", l);
8049 aopPut (AOP (result), "a", offset);
8052 aopPut (AOP (result), l, offset);
8055 _endLazyDPSEvaluation ();
8058 tlbl = newiTempLabel (NULL);
8059 size = AOP_SIZE (result);
8061 tlbl1 = newiTempLabel (NULL);
8063 /* if it is only one byte then */
8066 symbol *tlbl1 = newiTempLabel (NULL);
8068 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8070 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8071 emitcode ("", "!tlabeldef", tlbl->key + 100);
8072 emitcode ("add", "a,acc");
8073 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8074 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8075 aopPut (AOP (result), "a", 0);
8079 reAdjustPreg (AOP (result));
8081 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8082 emitcode ("", "!tlabeldef", tlbl->key + 100);
8083 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8085 emitcode ("add", "a,acc");
8086 aopPut (AOP (result), "a", offset++);
8087 _startLazyDPSEvaluation ();
8090 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8092 emitcode ("rlc", "a");
8093 aopPut (AOP (result), "a", offset++);
8095 _endLazyDPSEvaluation ();
8096 reAdjustPreg (AOP (result));
8098 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8099 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8101 freeAsmop (left, NULL, ic, TRUE);
8102 freeAsmop (result, NULL, ic, TRUE);
8105 #ifdef BETTER_LITERAL_SHIFT
8106 /*-----------------------------------------------------------------*/
8107 /* genrshOne - right shift a one byte quantity by known count */
8108 /*-----------------------------------------------------------------*/
8110 genrshOne (operand * result, operand * left,
8111 int shCount, int sign)
8113 D (emitcode (";", "genrshOne"););
8114 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8118 #ifdef BETTER_LITERAL_SHIFT
8119 /*-----------------------------------------------------------------*/
8120 /* genrshTwo - right shift two bytes by known amount != 0 */
8121 /*-----------------------------------------------------------------*/
8123 genrshTwo (operand * result, operand * left,
8124 int shCount, int sign)
8126 D (emitcode (";", "genrshTwo"););
8128 /* if shCount >= 8 */
8132 _startLazyDPSEvaluation();
8135 shiftR1Left2Result (left, MSB16, result, LSB,
8140 movLeft2Result (left, MSB16, result, LSB, sign);
8142 addSign (result, MSB16, sign);
8143 _endLazyDPSEvaluation();
8146 /* 1 <= shCount <= 7 */
8149 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8156 /*-----------------------------------------------------------------*/
8157 /* shiftRLong - shift right one long from left to result */
8158 /* offl = LSB or MSB16 */
8159 /*-----------------------------------------------------------------*/
8161 shiftRLong (operand * left, int offl,
8162 operand * result, int sign)
8164 int isSameRegs=sameRegs(AOP(left),AOP(result));
8166 if (isSameRegs && offl>1) {
8167 // we are in big trouble, but this shouldn't happen
8168 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8171 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8176 emitcode ("rlc", "a");
8177 emitcode ("subb", "a,acc");
8178 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8180 aopPut (AOP(result), zero, MSB32);
8185 emitcode ("clr", "c");
8187 emitcode ("mov", "c,acc.7");
8190 emitcode ("rrc", "a");
8192 if (isSameRegs && offl==MSB16) {
8193 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8195 aopPut (AOP (result), "a", MSB32);
8196 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8199 emitcode ("rrc", "a");
8200 if (isSameRegs && offl==1) {
8201 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8203 aopPut (AOP (result), "a", MSB24);
8204 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8206 emitcode ("rrc", "a");
8207 aopPut (AOP (result), "a", MSB16 - offl);
8211 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8212 emitcode ("rrc", "a");
8213 aopPut (AOP (result), "a", LSB);
8220 /*-----------------------------------------------------------------*/
8221 /* genrshFour - shift four byte by a known amount != 0 */
8222 /*-----------------------------------------------------------------*/
8224 genrshFour (operand * result, operand * left,
8225 int shCount, int sign)
8227 D (emitcode (";", "genrshFour");
8230 /* if shifting more that 3 bytes */
8235 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8237 movLeft2Result (left, MSB32, result, LSB, sign);
8238 addSign (result, MSB16, sign);
8240 else if (shCount >= 16)
8244 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8247 movLeft2Result (left, MSB24, result, LSB, 0);
8248 movLeft2Result (left, MSB32, result, MSB16, sign);
8250 addSign (result, MSB24, sign);
8252 else if (shCount >= 8)
8256 shiftRLong (left, MSB16, result, sign);
8257 else if (shCount == 0)
8259 movLeft2Result (left, MSB16, result, LSB, 0);
8260 movLeft2Result (left, MSB24, result, MSB16, 0);
8261 movLeft2Result (left, MSB32, result, MSB24, sign);
8262 addSign (result, MSB32, sign);
8266 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8267 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8268 /* the last shift is signed */
8269 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8270 addSign (result, MSB32, sign);
8274 { /* 1 <= shCount <= 7 */
8277 shiftRLong (left, LSB, result, sign);
8279 shiftRLong (result, LSB, result, sign);
8283 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8284 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8285 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8291 #ifdef BETTER_LITERAL_SHIFT
8292 /*-----------------------------------------------------------------*/
8293 /* genRightShiftLiteral - right shifting by known count */
8294 /*-----------------------------------------------------------------*/
8296 genRightShiftLiteral (operand * left,
8302 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8305 size = getSize (operandType (result));
8307 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8309 /* We only handle certain easy cases so far. */
8311 && (shCount < (size * 8))
8315 D(emitcode (";", "genRightShiftLiteral wimping out"););
8319 freeAsmop (right, NULL, ic, TRUE);
8321 aopOp (left, ic, FALSE, FALSE);
8322 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8325 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8329 /* test the LEFT size !!! */
8331 /* I suppose that the left size >= result size */
8334 size = getDataSize (result);
8335 _startLazyDPSEvaluation();
8338 movLeft2Result (left, size, result, size, 0);
8340 _endLazyDPSEvaluation();
8342 else if (shCount >= (size * 8))
8346 /* get sign in acc.7 */
8347 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8349 addSign (result, LSB, sign);
8356 genrshOne (result, left, shCount, sign);
8360 genrshTwo (result, left, shCount, sign);
8364 genrshFour (result, left, shCount, sign);
8371 freeAsmop (left, NULL, ic, TRUE);
8372 freeAsmop (result, NULL, ic, TRUE);
8378 /*-----------------------------------------------------------------*/
8379 /* genSignedRightShift - right shift of signed number */
8380 /*-----------------------------------------------------------------*/
8382 genSignedRightShift (iCode * ic)
8384 operand *right, *left, *result;
8387 symbol *tlbl, *tlbl1;
8389 D (emitcode (";", "genSignedRightShift "););
8391 /* we do it the hard way put the shift count in b
8392 and loop thru preserving the sign */
8394 right = IC_RIGHT (ic);
8395 left = IC_LEFT (ic);
8396 result = IC_RESULT (ic);
8398 aopOp (right, ic, FALSE, FALSE);
8400 #ifdef BETTER_LITERAL_SHIFT
8401 if (AOP_TYPE (right) == AOP_LIT)
8403 if (genRightShiftLiteral (left, right, result, ic, 1))
8409 /* shift count is unknown then we have to form
8410 a loop get the loop count in B : Note: we take
8411 only the lower order byte since shifting
8412 more that 32 bits make no sense anyway, ( the
8413 largest size of an object can be only 32 bits ) */
8415 if (AOP_TYPE (right) == AOP_LIT)
8417 /* Really should be handled by genRightShiftLiteral,
8418 * but since I'm too lazy to fix that today, at least we can make
8419 * some small improvement.
8421 emitcode("mov", "b,#!constbyte",
8422 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8426 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8427 emitcode ("inc", "b");
8429 freeAsmop (right, NULL, ic, TRUE);
8430 aopOp (left, ic, FALSE, FALSE);
8431 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8433 /* now move the left to the result if they are not the
8435 if (!sameRegs (AOP (left), AOP (result)) &&
8436 AOP_SIZE (result) > 1)
8439 size = AOP_SIZE (result);
8441 _startLazyDPSEvaluation ();
8444 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8445 if (*l == '@' && IS_AOP_PREG (result))
8448 emitcode ("mov", "a,%s", l);
8449 aopPut (AOP (result), "a", offset);
8452 aopPut (AOP (result), l, offset);
8455 _endLazyDPSEvaluation ();
8458 /* mov the highest order bit to OVR */
8459 tlbl = newiTempLabel (NULL);
8460 tlbl1 = newiTempLabel (NULL);
8462 size = AOP_SIZE (result);
8464 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8465 emitcode ("rlc", "a");
8466 emitcode ("mov", "ov,c");
8467 /* if it is only one byte then */
8470 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8472 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8473 emitcode ("", "!tlabeldef", tlbl->key + 100);
8474 emitcode ("mov", "c,ov");
8475 emitcode ("rrc", "a");
8476 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8477 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8478 aopPut (AOP (result), "a", 0);
8482 reAdjustPreg (AOP (result));
8483 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8484 emitcode ("", "!tlabeldef", tlbl->key + 100);
8485 emitcode ("mov", "c,ov");
8486 _startLazyDPSEvaluation ();
8489 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8491 emitcode ("rrc", "a");
8492 aopPut (AOP (result), "a", offset--);
8494 _endLazyDPSEvaluation ();
8495 reAdjustPreg (AOP (result));
8496 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8497 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8500 freeAsmop (left, NULL, ic, TRUE);
8501 freeAsmop (result, NULL, ic, TRUE);
8504 /*-----------------------------------------------------------------*/
8505 /* genRightShift - generate code for right shifting */
8506 /*-----------------------------------------------------------------*/
8508 genRightShift (iCode * ic)
8510 operand *right, *left, *result;
8514 symbol *tlbl, *tlbl1;
8516 D (emitcode (";", "genRightShift "););
8518 /* if signed then we do it the hard way preserve the
8519 sign bit moving it inwards */
8520 retype = getSpec (operandType (IC_RESULT (ic)));
8522 if (!SPEC_USIGN (retype))
8524 genSignedRightShift (ic);
8528 /* signed & unsigned types are treated the same : i.e. the
8529 signed is NOT propagated inwards : quoting from the
8530 ANSI - standard : "for E1 >> E2, is equivalent to division
8531 by 2**E2 if unsigned or if it has a non-negative value,
8532 otherwise the result is implementation defined ", MY definition
8533 is that the sign does not get propagated */
8535 right = IC_RIGHT (ic);
8536 left = IC_LEFT (ic);
8537 result = IC_RESULT (ic);
8539 aopOp (right, ic, FALSE, FALSE);
8541 #ifdef BETTER_LITERAL_SHIFT
8542 /* if the shift count is known then do it
8543 as efficiently as possible */
8544 if (AOP_TYPE (right) == AOP_LIT)
8546 if (genRightShiftLiteral (left, right, result, ic, 0))
8553 /* shift count is unknown then we have to form
8554 a loop get the loop count in B : Note: we take
8555 only the lower order byte since shifting
8556 more that 32 bits make no sense anyway, ( the
8557 largest size of an object can be only 32 bits ) */
8559 if (AOP_TYPE (right) == AOP_LIT)
8561 /* Really should be handled by genRightShiftLiteral,
8562 * but since I'm too lazy to fix that today, at least we can make
8563 * some small improvement.
8565 emitcode("mov", "b,#!constbyte",
8566 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8570 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8571 emitcode ("inc", "b");
8573 freeAsmop (right, NULL, ic, TRUE);
8574 aopOp (left, ic, FALSE, FALSE);
8575 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8577 /* now move the left to the result if they are not the
8579 if (!sameRegs (AOP (left), AOP (result)) &&
8580 AOP_SIZE (result) > 1)
8583 size = AOP_SIZE (result);
8585 _startLazyDPSEvaluation ();
8588 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8589 if (*l == '@' && IS_AOP_PREG (result))
8592 emitcode ("mov", "a,%s", l);
8593 aopPut (AOP (result), "a", offset);
8596 aopPut (AOP (result), l, offset);
8599 _endLazyDPSEvaluation ();
8602 tlbl = newiTempLabel (NULL);
8603 tlbl1 = newiTempLabel (NULL);
8604 size = AOP_SIZE (result);
8607 /* if it is only one byte then */
8610 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8612 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8613 emitcode ("", "!tlabeldef", tlbl->key + 100);
8615 emitcode ("rrc", "a");
8616 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8617 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8618 aopPut (AOP (result), "a", 0);
8622 reAdjustPreg (AOP (result));
8623 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8624 emitcode ("", "!tlabeldef", tlbl->key + 100);
8626 _startLazyDPSEvaluation ();
8629 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8631 emitcode ("rrc", "a");
8632 aopPut (AOP (result), "a", offset--);
8634 _endLazyDPSEvaluation ();
8635 reAdjustPreg (AOP (result));
8637 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8638 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8641 freeAsmop (left, NULL, ic, TRUE);
8642 freeAsmop (result, NULL, ic, TRUE);
8645 /*-----------------------------------------------------------------*/
8646 /* genUnpackBits - generates code for unpacking bits */
8647 /*-----------------------------------------------------------------*/
8649 genUnpackBits (operand * result, char *rname, int ptype)
8656 D (emitcode (";", "genUnpackBits ");
8659 etype = getSpec (operandType (result));
8661 /* read the first byte */
8667 emitcode ("mov", "a,@%s", rname);
8671 emitcode ("movx", "a,@%s", rname);
8675 emitcode ("movx", "a,@dptr");
8679 emitcode ("clr", "a");
8680 emitcode ("movc", "a,@a+dptr");
8684 emitcode ("lcall", "__gptrget");
8688 /* if we have bitdisplacement then it fits */
8689 /* into this byte completely or if length is */
8690 /* less than a byte */
8691 if ((shCnt = SPEC_BSTR (etype)) ||
8692 (SPEC_BLEN (etype) <= 8))
8695 /* shift right acc */
8698 emitcode ("anl", "a,#!constbyte",
8699 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8700 aopPut (AOP (result), "a", offset);
8704 /* bit field did not fit in a byte */
8705 rlen = SPEC_BLEN (etype) - 8;
8706 aopPut (AOP (result), "a", offset++);
8715 emitcode ("inc", "%s", rname);
8716 emitcode ("mov", "a,@%s", rname);
8720 emitcode ("inc", "%s", rname);
8721 emitcode ("movx", "a,@%s", rname);
8725 emitcode ("inc", "dptr");
8726 emitcode ("movx", "a,@dptr");
8730 emitcode ("clr", "a");
8731 emitcode ("inc", "dptr");
8732 emitcode ("movc", "a,@a+dptr");
8736 emitcode ("inc", "dptr");
8737 emitcode ("lcall", "__gptrget");
8742 /* if we are done */
8746 aopPut (AOP (result), "a", offset++);
8752 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8753 aopPut (AOP (result), "a", offset);
8760 /*-----------------------------------------------------------------*/
8761 /* genDataPointerGet - generates code when ptr offset is known */
8762 /*-----------------------------------------------------------------*/
8764 genDataPointerGet (operand * left,
8770 int size, offset = 0;
8771 aopOp (result, ic, TRUE, FALSE);
8773 /* get the string representation of the name */
8774 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8775 size = AOP_SIZE (result);
8776 _startLazyDPSEvaluation ();
8780 sprintf (buffer, "(%s + %d)", l + 1, offset);
8782 sprintf (buffer, "%s", l + 1);
8783 aopPut (AOP (result), buffer, offset++);
8785 _endLazyDPSEvaluation ();
8787 freeAsmop (left, NULL, ic, TRUE);
8788 freeAsmop (result, NULL, ic, TRUE);
8791 /*-----------------------------------------------------------------*/
8792 /* genNearPointerGet - emitcode for near pointer fetch */
8793 /*-----------------------------------------------------------------*/
8795 genNearPointerGet (operand * left,
8803 sym_link *rtype, *retype, *letype;
8804 sym_link *ltype = operandType (left);
8807 rtype = operandType (result);
8808 retype = getSpec (rtype);
8809 letype = getSpec (ltype);
8811 aopOp (left, ic, FALSE, FALSE);
8813 /* if left is rematerialisable and
8814 result is not bit variable type and
8815 the left is pointer to data space i.e
8816 lower 128 bytes of space */
8817 if (AOP_TYPE (left) == AOP_IMMD &&
8818 !IS_BITVAR (retype) &&
8819 !IS_BITVAR (letype) &&
8820 DCL_TYPE (ltype) == POINTER)
8822 genDataPointerGet (left, result, ic);
8826 /* if the value is already in a pointer register
8827 then don't need anything more */
8828 if (!AOP_INPREG (AOP (left)))
8830 /* otherwise get a free pointer register */
8832 preg = getFreePtr (ic, &aop, FALSE);
8833 emitcode ("mov", "%s,%s",
8835 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8839 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8841 freeAsmop (left, NULL, ic, TRUE);
8842 aopOp (result, ic, FALSE, FALSE);
8844 /* if bitfield then unpack the bits */
8845 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8846 genUnpackBits (result, rname, POINTER);
8849 /* we have can just get the values */
8850 int size = AOP_SIZE (result);
8855 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8858 emitcode ("mov", "a,@%s", rname);
8859 aopPut (AOP (result), "a", offset);
8863 sprintf (buffer, "@%s", rname);
8864 aopPut (AOP (result), buffer, offset);
8868 emitcode ("inc", "%s", rname);
8872 /* now some housekeeping stuff */
8875 /* we had to allocate for this iCode */
8876 if (pi) { /* post increment present */
8877 aopPut(AOP ( left ),rname,0);
8879 freeAsmop (NULL, aop, ic, TRUE);
8883 /* we did not allocate which means left
8884 already in a pointer register, then
8885 if size > 0 && this could be used again
8886 we have to point it back to where it
8888 if (AOP_SIZE (result) > 1 &&
8889 !OP_SYMBOL (left)->remat &&
8890 (OP_SYMBOL (left)->liveTo > ic->seq ||
8894 int size = AOP_SIZE (result) - 1;
8896 emitcode ("dec", "%s", rname);
8901 freeAsmop (result, NULL, ic, TRUE);
8902 if (pi) pi->generated = 1;
8905 /*-----------------------------------------------------------------*/
8906 /* genPagedPointerGet - emitcode for paged pointer fetch */
8907 /*-----------------------------------------------------------------*/
8909 genPagedPointerGet (operand * left,
8917 sym_link *rtype, *retype, *letype;
8919 rtype = operandType (result);
8920 retype = getSpec (rtype);
8921 letype = getSpec (operandType (left));
8922 aopOp (left, ic, FALSE, FALSE);
8924 /* if the value is already in a pointer register
8925 then don't need anything more */
8926 if (!AOP_INPREG (AOP (left)))
8928 /* otherwise get a free pointer register */
8930 preg = getFreePtr (ic, &aop, FALSE);
8931 emitcode ("mov", "%s,%s",
8933 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8937 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8939 freeAsmop (left, NULL, ic, TRUE);
8940 aopOp (result, ic, FALSE, FALSE);
8942 /* if bitfield then unpack the bits */
8943 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8944 genUnpackBits (result, rname, PPOINTER);
8947 /* we have can just get the values */
8948 int size = AOP_SIZE (result);
8954 emitcode ("movx", "a,@%s", rname);
8955 aopPut (AOP (result), "a", offset);
8960 emitcode ("inc", "%s", rname);
8964 /* now some housekeeping stuff */
8967 /* we had to allocate for this iCode */
8968 if (pi) aopPut ( AOP (left), rname, 0);
8969 freeAsmop (NULL, aop, ic, TRUE);
8973 /* we did not allocate which means left
8974 already in a pointer register, then
8975 if size > 0 && this could be used again
8976 we have to point it back to where it
8978 if (AOP_SIZE (result) > 1 &&
8979 !OP_SYMBOL (left)->remat &&
8980 (OP_SYMBOL (left)->liveTo > ic->seq ||
8984 int size = AOP_SIZE (result) - 1;
8986 emitcode ("dec", "%s", rname);
8991 freeAsmop (result, NULL, ic, TRUE);
8992 if (pi) pi->generated = 1;
8995 /*-----------------------------------------------------------------*/
8996 /* genFarPointerGet - gget value from far space */
8997 /*-----------------------------------------------------------------*/
8999 genFarPointerGet (operand * left,
9000 operand * result, iCode * ic, iCode *pi)
9002 int size, offset, dopi=1;
9003 sym_link *retype = getSpec (operandType (result));
9004 sym_link *letype = getSpec (operandType (left));
9005 D (emitcode (";", "genFarPointerGet");
9008 aopOp (left, ic, FALSE, FALSE);
9010 /* if the operand is already in dptr
9011 then we do nothing else we move the value to dptr */
9012 if (AOP_TYPE (left) != AOP_STR)
9014 /* if this is remateriazable */
9015 if (AOP_TYPE (left) == AOP_IMMD)
9017 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9021 /* we need to get it byte by byte */
9022 _startLazyDPSEvaluation ();
9023 if (AOP_TYPE (left) != AOP_DPTR)
9025 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9026 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9027 if (options.model == MODEL_FLAT24)
9028 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9032 /* We need to generate a load to DPTR indirect through DPTR. */
9033 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9035 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9036 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9037 if (options.model == MODEL_FLAT24)
9038 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9039 emitcode ("pop", "dph");
9040 emitcode ("pop", "dpl");
9043 _endLazyDPSEvaluation ();
9046 /* so dptr know contains the address */
9047 aopOp (result, ic, FALSE, TRUE);
9049 /* if bit then unpack */
9050 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9051 genUnpackBits (result, "dptr", FPOINTER);
9054 size = AOP_SIZE (result);
9057 _startLazyDPSEvaluation ();
9064 emitcode ("movx", "a,@dptr");
9065 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9066 emitcode ("inc", "dptr");
9068 aopPut (AOP (result), "a", offset++);
9070 _endLazyDPSEvaluation ();
9072 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9073 aopPut ( AOP (left), "dpl", 0);
9074 aopPut ( AOP (left), "dph", 1);
9075 if (options.model == MODEL_FLAT24)
9076 aopPut ( AOP (left), "dpx", 2);
9078 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9079 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9081 size = AOP_SIZE (result) - 1;
9082 while (size--) emitcode ("lcall","__decdptr");
9085 freeAsmop (left, NULL, ic, TRUE);
9086 freeAsmop (result, NULL, ic, TRUE);
9089 /*-----------------------------------------------------------------*/
9090 /* emitcodePointerGet - gget value from code space */
9091 /*-----------------------------------------------------------------*/
9093 emitcodePointerGet (operand * left,
9094 operand * result, iCode * ic, iCode *pi)
9096 int size, offset, dopi=1;
9097 sym_link *retype = getSpec (operandType (result));
9099 aopOp (left, ic, FALSE, FALSE);
9101 /* if the operand is already in dptr
9102 then we do nothing else we move the value to dptr */
9103 if (AOP_TYPE (left) != AOP_STR)
9105 /* if this is remateriazable */
9106 if (AOP_TYPE (left) == AOP_IMMD)
9108 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9111 { /* we need to get it byte by byte */
9112 _startLazyDPSEvaluation ();
9113 if (AOP_TYPE (left) != AOP_DPTR)
9115 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9116 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9117 if (options.model == MODEL_FLAT24)
9118 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9122 /* We need to generate a load to DPTR indirect through DPTR. */
9123 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9125 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9126 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9127 if (options.model == MODEL_FLAT24)
9128 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9129 emitcode ("pop", "dph");
9130 emitcode ("pop", "dpl");
9133 _endLazyDPSEvaluation ();
9136 /* so dptr know contains the address */
9137 aopOp (result, ic, FALSE, TRUE);
9139 /* if bit then unpack */
9140 if (IS_BITVAR (retype))
9141 genUnpackBits (result, "dptr", CPOINTER);
9144 size = AOP_SIZE (result);
9147 _startLazyDPSEvaluation ();
9153 emitcode ("clr", "a");
9154 emitcode ("movc", "a,@a+dptr");
9155 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9156 emitcode ("inc", "dptr");
9157 aopPut (AOP (result), "a", offset++);
9159 _endLazyDPSEvaluation ();
9161 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9162 aopPut ( AOP (left), "dpl", 0);
9163 aopPut ( AOP (left), "dph", 1);
9164 if (options.model == MODEL_FLAT24)
9165 aopPut ( AOP (left), "dpx", 2);
9167 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9168 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9170 size = AOP_SIZE (result) - 1;
9171 while (size--) emitcode ("lcall","__decdptr");
9174 freeAsmop (left, NULL, ic, TRUE);
9175 freeAsmop (result, NULL, ic, TRUE);
9178 /*-----------------------------------------------------------------*/
9179 /* genGenPointerGet - gget value from generic pointer space */
9180 /*-----------------------------------------------------------------*/
9182 genGenPointerGet (operand * left,
9183 operand * result, iCode * ic, iCode * pi)
9186 sym_link *retype = getSpec (operandType (result));
9187 sym_link *letype = getSpec (operandType (left));
9189 D (emitcode (";", "genGenPointerGet "); );
9191 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9193 /* if the operand is already in dptr
9194 then we do nothing else we move the value to dptr */
9195 if (AOP_TYPE (left) != AOP_STR)
9197 /* if this is remateriazable */
9198 if (AOP_TYPE (left) == AOP_IMMD)
9200 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9201 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9202 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9204 emitcode ("mov", "b,#%d", pointerCode (retype));
9207 { /* we need to get it byte by byte */
9208 _startLazyDPSEvaluation ();
9209 if (AOP(left)->type==AOP_DPTR2) {
9211 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9214 emitcode ("mov", "dpl,%s", l);
9215 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9218 emitcode ("mov", "dph,%s", l);
9219 if (options.model == MODEL_FLAT24) {
9220 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9223 emitcode ("mov", "dpx,%s", l);
9224 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9226 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9229 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9230 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9231 if (options.model == MODEL_FLAT24) {
9232 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9233 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9235 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9238 _endLazyDPSEvaluation ();
9241 /* so dptr know contains the address */
9242 aopOp (result, ic, FALSE, TRUE);
9244 /* if bit then unpack */
9245 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9246 genUnpackBits (result, "dptr", GPOINTER);
9249 size = AOP_SIZE (result);
9254 emitcode ("lcall", "__gptrget");
9255 aopPut (AOP (result), "a", offset++);
9256 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9257 emitcode ("inc", "dptr");
9261 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9262 aopPut ( AOP (left), "dpl", 0);
9263 aopPut ( AOP (left), "dph", 1);
9264 if (options.model == MODEL_FLAT24) {
9265 aopPut ( AOP (left), "dpx", 2);
9266 aopPut ( AOP (left), "b", 3);
9267 } else aopPut ( AOP (left), "b", 2);
9269 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9270 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9272 size = AOP_SIZE (result) - 1;
9273 while (size--) emitcode ("lcall","__decdptr");
9276 freeAsmop (left, NULL, ic, TRUE);
9277 freeAsmop (result, NULL, ic, TRUE);
9280 /*-----------------------------------------------------------------*/
9281 /* genPointerGet - generate code for pointer get */
9282 /*-----------------------------------------------------------------*/
9284 genPointerGet (iCode * ic, iCode *pi)
9286 operand *left, *result;
9287 sym_link *type, *etype;
9290 D (emitcode (";", "genPointerGet ");
9293 left = IC_LEFT (ic);
9294 result = IC_RESULT (ic);
9296 /* depending on the type of pointer we need to
9297 move it to the correct pointer register */
9298 type = operandType (left);
9299 etype = getSpec (type);
9300 /* if left is of type of pointer then it is simple */
9301 if (IS_PTR (type) && !IS_FUNC (type->next))
9302 p_type = DCL_TYPE (type);
9305 /* we have to go by the storage class */
9306 p_type = PTR_TYPE (SPEC_OCLS (etype));
9308 /* special case when cast remat */
9309 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9310 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9311 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9312 type = type = operandType (left);
9313 p_type = DCL_TYPE (type);
9315 /* now that we have the pointer type we assign
9316 the pointer values */
9322 genNearPointerGet (left, result, ic, pi);
9326 genPagedPointerGet (left, result, ic, pi);
9330 genFarPointerGet (left, result, ic, pi);
9334 emitcodePointerGet (left, result, ic, pi);
9338 genGenPointerGet (left, result, ic, pi);
9344 /*-----------------------------------------------------------------*/
9345 /* genPackBits - generates code for packed bit storage */
9346 /*-----------------------------------------------------------------*/
9348 genPackBits (sym_link * etype,
9350 char *rname, int p_type)
9358 blen = SPEC_BLEN (etype);
9359 bstr = SPEC_BSTR (etype);
9361 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9364 /* if the bit lenth is less than or */
9365 /* it exactly fits a byte then */
9366 if (SPEC_BLEN (etype) <= 8)
9368 shCount = SPEC_BSTR (etype);
9370 /* shift left acc */
9373 if (SPEC_BLEN (etype) < 8)
9374 { /* if smaller than a byte */
9380 emitcode ("mov", "b,a");
9381 emitcode ("mov", "a,@%s", rname);
9385 emitcode ("mov", "b,a");
9386 emitcode ("movx", "a,@dptr");
9390 emitcode ("push", "b");
9391 emitcode ("push", "acc");
9392 emitcode ("lcall", "__gptrget");
9393 emitcode ("pop", "b");
9397 emitcode ("anl", "a,#!constbyte", (unsigned char)
9398 ((unsigned char) (0xFF << (blen + bstr)) |
9399 (unsigned char) (0xFF >> (8 - bstr))));
9400 emitcode ("orl", "a,b");
9401 if (p_type == GPOINTER)
9402 emitcode ("pop", "b");
9409 emitcode ("mov", "@%s,a", rname);
9413 emitcode ("movx", "@dptr,a");
9417 emitcode ("lcall", "__gptrput");
9422 if (SPEC_BLEN (etype) <= 8)
9425 emitcode ("inc", "%s", rname);
9426 rLen = SPEC_BLEN (etype);
9428 /* now generate for lengths greater than one byte */
9432 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9444 emitcode ("mov", "@%s,a", rname);
9447 emitcode ("mov", "@%s,%s", rname, l);
9452 emitcode ("movx", "@dptr,a");
9457 emitcode ("lcall", "__gptrput");
9460 emitcode ("inc", "%s", rname);
9465 /* last last was not complete */
9468 /* save the byte & read byte */
9472 emitcode ("mov", "b,a");
9473 emitcode ("mov", "a,@%s", rname);
9477 emitcode ("mov", "b,a");
9478 emitcode ("movx", "a,@dptr");
9482 emitcode ("push", "b");
9483 emitcode ("push", "acc");
9484 emitcode ("lcall", "__gptrget");
9485 emitcode ("pop", "b");
9489 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9490 emitcode ("orl", "a,b");
9493 if (p_type == GPOINTER)
9494 emitcode ("pop", "b");
9500 emitcode ("mov", "@%s,a", rname);
9504 emitcode ("movx", "@dptr,a");
9508 emitcode ("lcall", "__gptrput");
9512 /*-----------------------------------------------------------------*/
9513 /* genDataPointerSet - remat pointer to data space */
9514 /*-----------------------------------------------------------------*/
9516 genDataPointerSet (operand * right,
9520 int size, offset = 0;
9521 char *l, buffer[256];
9523 aopOp (right, ic, FALSE, FALSE);
9525 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9526 size = AOP_SIZE (right);
9530 sprintf (buffer, "(%s + %d)", l + 1, offset);
9532 sprintf (buffer, "%s", l + 1);
9533 emitcode ("mov", "%s,%s", buffer,
9534 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9537 freeAsmop (right, NULL, ic, TRUE);
9538 freeAsmop (result, NULL, ic, TRUE);
9541 /*-----------------------------------------------------------------*/
9542 /* genNearPointerSet - emitcode for near pointer put */
9543 /*-----------------------------------------------------------------*/
9545 genNearPointerSet (operand * right,
9553 sym_link *retype, *letype;
9554 sym_link *ptype = operandType (result);
9556 retype = getSpec (operandType (right));
9557 letype = getSpec (ptype);
9559 aopOp (result, ic, FALSE, FALSE);
9561 /* if the result is rematerializable &
9562 in data space & not a bit variable */
9563 if (AOP_TYPE (result) == AOP_IMMD &&
9564 DCL_TYPE (ptype) == POINTER &&
9565 !IS_BITVAR (retype) &&
9566 !IS_BITVAR (letype))
9568 genDataPointerSet (right, result, ic);
9572 /* if the value is already in a pointer register
9573 then don't need anything more */
9574 if (!AOP_INPREG (AOP (result)))
9576 /* otherwise get a free pointer register */
9578 preg = getFreePtr (ic, &aop, FALSE);
9579 emitcode ("mov", "%s,%s",
9581 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9585 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9587 aopOp (right, ic, FALSE, FALSE);
9589 /* if bitfield then unpack the bits */
9590 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9591 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9594 /* we have can just get the values */
9595 int size = AOP_SIZE (right);
9600 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9604 emitcode ("mov", "@%s,a", rname);
9607 emitcode ("mov", "@%s,%s", rname, l);
9609 emitcode ("inc", "%s", rname);
9614 /* now some housekeeping stuff */
9617 /* we had to allocate for this iCode */
9618 if (pi) aopPut (AOP (result),rname,0);
9619 freeAsmop (NULL, aop, ic, TRUE);
9623 /* we did not allocate which means left
9624 already in a pointer register, then
9625 if size > 0 && this could be used again
9626 we have to point it back to where it
9628 if (AOP_SIZE (right) > 1 &&
9629 !OP_SYMBOL (result)->remat &&
9630 (OP_SYMBOL (result)->liveTo > ic->seq ||
9634 int size = AOP_SIZE (right) - 1;
9636 emitcode ("dec", "%s", rname);
9641 if (pi) pi->generated = 1;
9642 freeAsmop (result, NULL, ic, TRUE);
9643 freeAsmop (right, NULL, ic, TRUE);
9648 /*-----------------------------------------------------------------*/
9649 /* genPagedPointerSet - emitcode for Paged pointer put */
9650 /*-----------------------------------------------------------------*/
9652 genPagedPointerSet (operand * right,
9660 sym_link *retype, *letype;
9662 retype = getSpec (operandType (right));
9663 letype = getSpec (operandType (result));
9665 aopOp (result, ic, FALSE, FALSE);
9667 /* if the value is already in a pointer register
9668 then don't need anything more */
9669 if (!AOP_INPREG (AOP (result)))
9671 /* otherwise get a free pointer register */
9673 preg = getFreePtr (ic, &aop, FALSE);
9674 emitcode ("mov", "%s,%s",
9676 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9680 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9682 aopOp (right, ic, FALSE, FALSE);
9684 /* if bitfield then unpack the bits */
9685 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9686 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9689 /* we have can just get the values */
9690 int size = AOP_SIZE (right);
9695 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9698 emitcode ("movx", "@%s,a", rname);
9701 emitcode ("inc", "%s", rname);
9707 /* now some housekeeping stuff */
9710 if (pi) aopPut (AOP (result),rname,0);
9711 /* we had to allocate for this iCode */
9712 freeAsmop (NULL, aop, ic, TRUE);
9716 /* we did not allocate which means left
9717 already in a pointer register, then
9718 if size > 0 && this could be used again
9719 we have to point it back to where it
9721 if (AOP_SIZE (right) > 1 &&
9722 !OP_SYMBOL (result)->remat &&
9723 (OP_SYMBOL (result)->liveTo > ic->seq ||
9727 int size = AOP_SIZE (right) - 1;
9729 emitcode ("dec", "%s", rname);
9734 if (pi) pi->generated = 1;
9735 freeAsmop (result, NULL, ic, TRUE);
9736 freeAsmop (right, NULL, ic, TRUE);
9741 /*-----------------------------------------------------------------*/
9742 /* genFarPointerSet - set value from far space */
9743 /*-----------------------------------------------------------------*/
9745 genFarPointerSet (operand * right,
9746 operand * result, iCode * ic, iCode *pi)
9748 int size, offset, dopi=1;
9749 sym_link *retype = getSpec (operandType (right));
9750 sym_link *letype = getSpec (operandType (result));
9752 aopOp (result, ic, FALSE, FALSE);
9754 /* if the operand is already in dptr
9755 then we do nothing else we move the value to dptr */
9756 if (AOP_TYPE (result) != AOP_STR)
9758 /* if this is remateriazable */
9759 if (AOP_TYPE (result) == AOP_IMMD)
9760 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9763 /* we need to get it byte by byte */
9764 _startLazyDPSEvaluation ();
9765 if (AOP_TYPE (result) != AOP_DPTR)
9767 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9768 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9769 if (options.model == MODEL_FLAT24)
9770 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9774 /* We need to generate a load to DPTR indirect through DPTR. */
9775 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9777 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9778 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9779 if (options.model == MODEL_FLAT24)
9780 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9781 emitcode ("pop", "dph");
9782 emitcode ("pop", "dpl");
9785 _endLazyDPSEvaluation ();
9788 /* so dptr know contains the address */
9789 aopOp (right, ic, FALSE, TRUE);
9791 /* if bit then unpack */
9792 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9793 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9796 size = AOP_SIZE (right);
9799 _startLazyDPSEvaluation ();
9802 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9808 emitcode ("movx", "@dptr,a");
9809 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9810 emitcode ("inc", "dptr");
9812 _endLazyDPSEvaluation ();
9815 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9816 aopPut (AOP(result),"dpl",0);
9817 aopPut (AOP(result),"dph",1);
9818 if (options.model == MODEL_FLAT24)
9819 aopPut (AOP(result),"dpx",2);
9821 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9822 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9824 size = AOP_SIZE (right) - 1;
9825 while (size--) emitcode ("lcall","__decdptr");
9827 freeAsmop (result, NULL, ic, TRUE);
9828 freeAsmop (right, NULL, ic, TRUE);
9831 /*-----------------------------------------------------------------*/
9832 /* genGenPointerSet - set value from generic pointer space */
9833 /*-----------------------------------------------------------------*/
9835 genGenPointerSet (operand * right,
9836 operand * result, iCode * ic, iCode *pi)
9839 sym_link *retype = getSpec (operandType (right));
9840 sym_link *letype = getSpec (operandType (result));
9842 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9844 /* if the operand is already in dptr
9845 then we do nothing else we move the value to dptr */
9846 if (AOP_TYPE (result) != AOP_STR)
9848 _startLazyDPSEvaluation ();
9849 /* if this is remateriazable */
9850 if (AOP_TYPE (result) == AOP_IMMD)
9852 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9853 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9854 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9856 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9859 { /* we need to get it byte by byte */
9860 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9861 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9862 if (options.model == MODEL_FLAT24) {
9863 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9864 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9866 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9869 _endLazyDPSEvaluation ();
9871 /* so dptr know contains the address */
9872 aopOp (right, ic, FALSE, TRUE);
9874 /* if bit then unpack */
9875 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9876 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9879 size = AOP_SIZE (right);
9882 _startLazyDPSEvaluation ();
9885 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9891 emitcode ("lcall", "__gptrput");
9892 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9893 emitcode ("inc", "dptr");
9895 _endLazyDPSEvaluation ();
9898 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9899 aopPut (AOP(result),"dpl",0);
9900 aopPut (AOP(result),"dph",1);
9901 if (options.model == MODEL_FLAT24) {
9902 aopPut (AOP(result),"dpx",2);
9903 aopPut (AOP(result),"b",3);
9905 aopPut (AOP(result),"b",2);
9908 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9909 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9911 size = AOP_SIZE (right) - 1;
9912 while (size--) emitcode ("lcall","__decdptr");
9914 freeAsmop (result, NULL, ic, TRUE);
9915 freeAsmop (right, NULL, ic, TRUE);
9918 /*-----------------------------------------------------------------*/
9919 /* genPointerSet - stores the value into a pointer location */
9920 /*-----------------------------------------------------------------*/
9922 genPointerSet (iCode * ic, iCode *pi)
9924 operand *right, *result;
9925 sym_link *type, *etype;
9928 D (emitcode (";", "genPointerSet ");
9931 right = IC_RIGHT (ic);
9932 result = IC_RESULT (ic);
9934 /* depending on the type of pointer we need to
9935 move it to the correct pointer register */
9936 type = operandType (result);
9937 etype = getSpec (type);
9938 /* if left is of type of pointer then it is simple */
9939 if (IS_PTR (type) && !IS_FUNC (type->next))
9941 p_type = DCL_TYPE (type);
9945 /* we have to go by the storage class */
9946 p_type = PTR_TYPE (SPEC_OCLS (etype));
9948 /* special case when cast remat */
9949 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9950 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9951 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9952 type = type = operandType (result);
9953 p_type = DCL_TYPE (type);
9956 /* now that we have the pointer type we assign
9957 the pointer values */
9963 genNearPointerSet (right, result, ic, pi);
9967 genPagedPointerSet (right, result, ic, pi);
9971 genFarPointerSet (right, result, ic, pi);
9975 genGenPointerSet (right, result, ic, pi);
9981 /*-----------------------------------------------------------------*/
9982 /* genIfx - generate code for Ifx statement */
9983 /*-----------------------------------------------------------------*/
9985 genIfx (iCode * ic, iCode * popIc)
9987 operand *cond = IC_COND (ic);
9990 D (emitcode (";", "genIfx "););
9992 aopOp (cond, ic, FALSE, FALSE);
9994 /* get the value into acc */
9995 if (AOP_TYPE (cond) != AOP_CRY)
9999 /* the result is now in the accumulator */
10000 freeAsmop (cond, NULL, ic, TRUE);
10002 /* if there was something to be popped then do it */
10006 /* if the condition is a bit variable */
10007 if (isbit && IS_ITEMP (cond) &&
10009 genIfxJump (ic, SPIL_LOC (cond)->rname);
10010 else if (isbit && !IS_ITEMP (cond))
10011 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10013 genIfxJump (ic, "a");
10018 /*-----------------------------------------------------------------*/
10019 /* genAddrOf - generates code for address of */
10020 /*-----------------------------------------------------------------*/
10022 genAddrOf (iCode * ic)
10024 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10027 D (emitcode (";", "genAddrOf ");
10030 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10032 /* if the operand is on the stack then we
10033 need to get the stack offset of this
10035 if (sym->onStack) {
10037 /* if 10 bit stack */
10038 if (options.stack10bit) {
10040 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10041 /* if it has an offset then we need to compute it */
10042 emitcode ("subb", "a,#!constbyte",
10043 -((sym->stack < 0) ?
10044 ((short) (sym->stack - _G.nRegsSaved)) :
10045 ((short) sym->stack)) & 0xff);
10046 emitcode ("mov","b,a");
10047 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10048 ((short) (sym->stack - _G.nRegsSaved)) :
10049 ((short) sym->stack)) >> 8) & 0xff);
10051 emitcode ("mov", "a,_bpx");
10052 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10053 ((char) (sym->stack - _G.nRegsSaved)) :
10054 ((char) sym->stack )) & 0xff);
10055 emitcode ("mov", "b,a");
10056 emitcode ("mov", "a,_bpx+1");
10057 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10058 ((short) (sym->stack - _G.nRegsSaved)) :
10059 ((short) sym->stack )) >> 8) & 0xff);
10060 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10061 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10062 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10064 /* we can just move _bp */
10065 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10066 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10067 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10070 /* if it has an offset then we need to compute it */
10072 emitcode ("mov", "a,_bp");
10073 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10074 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10076 /* we can just move _bp */
10077 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10079 /* fill the result with zero */
10080 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10083 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10085 "*** warning: pointer to stack var truncated.\n");
10090 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10096 /* object not on stack then we need the name */
10097 size = AOP_SIZE (IC_RESULT (ic));
10102 char s[SDCC_NAME_MAX];
10106 tsprintf(s,"!his",sym->rname);
10109 tsprintf(s,"!hihis",sym->rname);
10112 tsprintf(s,"!hihihis",sym->rname);
10114 default: /* should not need this (just in case) */
10115 sprintf (s, "#(%s >> %d)",
10120 sprintf (s, "#%s", sym->rname);
10121 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10125 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10129 /*-----------------------------------------------------------------*/
10130 /* genArrayInit - generates code for address of */
10131 /*-----------------------------------------------------------------*/
10133 genArrayInit (iCode * ic)
10135 literalList *iLoop;
10137 int elementSize = 0, eIndex;
10138 unsigned val, lastVal;
10140 operand *left=IC_LEFT(ic);
10142 D (emitcode (";", "genArrayInit "););
10144 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10146 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10148 // Load immediate value into DPTR.
10149 emitcode("mov", "dptr, %s",
10150 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10152 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10155 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10156 "Unexpected operand to genArrayInit.\n");
10159 // a regression because of SDCCcse.c:1.52
10160 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10161 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10162 if (options.model == MODEL_FLAT24)
10163 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10167 type = operandType(IC_LEFT(ic));
10169 if (type && type->next)
10171 elementSize = getSize(type->next);
10175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10176 "can't determine element size in genArrayInit.\n");
10180 iLoop = IC_ARRAYILIST(ic);
10185 bool firstpass = TRUE;
10187 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10188 iLoop->count, (int)iLoop->literalValue, elementSize);
10194 symbol *tlbl = NULL;
10196 count = ix > 256 ? 256 : ix;
10200 tlbl = newiTempLabel (NULL);
10201 if (firstpass || (count & 0xff))
10203 emitcode("mov", "b, #!constbyte", count & 0xff);
10206 emitcode ("", "!tlabeldef", tlbl->key + 100);
10211 for (eIndex = 0; eIndex < elementSize; eIndex++)
10213 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10214 if (val != lastVal)
10216 emitcode("mov", "a, #!constbyte", val);
10220 emitcode("movx", "@dptr, a");
10221 emitcode("inc", "dptr");
10226 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10232 iLoop = iLoop->next;
10235 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10238 /*-----------------------------------------------------------------*/
10239 /* genFarFarAssign - assignment when both are in far space */
10240 /*-----------------------------------------------------------------*/
10242 genFarFarAssign (operand * result, operand * right, iCode * ic)
10244 int size = AOP_SIZE (right);
10246 symbol *rSym = NULL;
10250 /* quick & easy case. */
10251 D(emitcode(";","genFarFarAssign (1 byte case)"););
10252 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10253 freeAsmop (right, NULL, ic, FALSE);
10254 /* now assign DPTR to result */
10256 aopOp(result, ic, FALSE, FALSE);
10258 aopPut(AOP(result), "a", 0);
10259 freeAsmop(result, NULL, ic, FALSE);
10263 /* See if we've got an underlying symbol to abuse. */
10264 if (IS_SYMOP(result) && OP_SYMBOL(result))
10266 if (IS_TRUE_SYMOP(result))
10268 rSym = OP_SYMBOL(result);
10270 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10272 rSym = OP_SYMBOL(result)->usl.spillLoc;
10276 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10278 /* We can use the '390 auto-toggle feature to good effect here. */
10280 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10281 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10282 emitcode ("mov", "dptr,#%s", rSym->rname);
10283 /* DP2 = result, DP1 = right, DP1 is current. */
10286 emitcode("movx", "a,@dptr");
10287 emitcode("movx", "@dptr,a");
10290 emitcode("inc", "dptr");
10291 emitcode("inc", "dptr");
10294 emitcode("mov", "dps,#0");
10295 freeAsmop (right, NULL, ic, FALSE);
10297 some alternative code for processors without auto-toggle
10298 no time to test now, so later well put in...kpb
10299 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10300 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10301 emitcode ("mov", "dptr,#%s", rSym->rname);
10302 /* DP2 = result, DP1 = right, DP1 is current. */
10306 emitcode("movx", "a,@dptr");
10308 emitcode("inc", "dptr");
10309 emitcode("inc", "dps");
10310 emitcode("movx", "@dptr,a");
10312 emitcode("inc", "dptr");
10313 emitcode("inc", "dps");
10315 emitcode("mov", "dps,#0");
10316 freeAsmop (right, NULL, ic, FALSE);
10321 D (emitcode (";", "genFarFarAssign"););
10322 aopOp (result, ic, TRUE, TRUE);
10324 _startLazyDPSEvaluation ();
10328 aopPut (AOP (result),
10329 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10332 _endLazyDPSEvaluation ();
10333 freeAsmop (result, NULL, ic, FALSE);
10334 freeAsmop (right, NULL, ic, FALSE);
10338 /*-----------------------------------------------------------------*/
10339 /* genAssign - generate code for assignment */
10340 /*-----------------------------------------------------------------*/
10342 genAssign (iCode * ic)
10344 operand *result, *right;
10346 unsigned long lit = 0L;
10348 D (emitcode (";", "genAssign ");
10351 result = IC_RESULT (ic);
10352 right = IC_RIGHT (ic);
10354 /* if they are the same */
10355 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10358 aopOp (right, ic, FALSE, FALSE);
10360 emitcode (";", "genAssign: resultIsFar = %s",
10361 isOperandInFarSpace (result) ?
10364 /* special case both in far space */
10365 if ((AOP_TYPE (right) == AOP_DPTR ||
10366 AOP_TYPE (right) == AOP_DPTR2) &&
10367 /* IS_TRUE_SYMOP(result) && */
10368 isOperandInFarSpace (result))
10370 genFarFarAssign (result, right, ic);
10374 aopOp (result, ic, TRUE, FALSE);
10376 /* if they are the same registers */
10377 if (sameRegs (AOP (right), AOP (result)))
10380 /* if the result is a bit */
10381 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10383 /* if the right size is a literal then
10384 we know what the value is */
10385 if (AOP_TYPE (right) == AOP_LIT)
10387 if (((int) operandLitValue (right)))
10388 aopPut (AOP (result), one, 0);
10390 aopPut (AOP (result), zero, 0);
10394 /* the right is also a bit variable */
10395 if (AOP_TYPE (right) == AOP_CRY)
10397 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10398 aopPut (AOP (result), "c", 0);
10402 /* we need to or */
10404 aopPut (AOP (result), "a", 0);
10408 /* bit variables done */
10410 size = AOP_SIZE (result);
10412 if (AOP_TYPE (right) == AOP_LIT)
10413 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10416 (AOP_TYPE (result) != AOP_REG) &&
10417 (AOP_TYPE (right) == AOP_LIT) &&
10418 !IS_FLOAT (operandType (right)))
10420 _startLazyDPSEvaluation ();
10421 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10423 aopPut (AOP (result),
10424 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10429 /* And now fill the rest with zeros. */
10432 emitcode ("clr", "a");
10436 aopPut (AOP (result), "a", offset++);
10438 _endLazyDPSEvaluation ();
10442 _startLazyDPSEvaluation ();
10445 aopPut (AOP (result),
10446 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10450 _endLazyDPSEvaluation ();
10454 freeAsmop (right, NULL, ic, FALSE);
10455 freeAsmop (result, NULL, ic, TRUE);
10458 /*-----------------------------------------------------------------*/
10459 /* genJumpTab - generates code for jump table */
10460 /*-----------------------------------------------------------------*/
10462 genJumpTab (iCode * ic)
10467 D (emitcode (";", "genJumpTab ");
10470 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10471 /* get the condition into accumulator */
10472 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10474 /* multiply by four! */
10475 emitcode ("add", "a,acc");
10476 emitcode ("add", "a,acc");
10477 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10479 jtab = newiTempLabel (NULL);
10480 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10481 emitcode ("jmp", "@a+dptr");
10482 emitcode ("", "!tlabeldef", jtab->key + 100);
10483 /* now generate the jump labels */
10484 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10485 jtab = setNextItem (IC_JTLABELS (ic)))
10486 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10490 /*-----------------------------------------------------------------*/
10491 /* genCast - gen code for casting */
10492 /*-----------------------------------------------------------------*/
10494 genCast (iCode * ic)
10496 operand *result = IC_RESULT (ic);
10497 sym_link *ctype = operandType (IC_LEFT (ic));
10498 sym_link *rtype = operandType (IC_RIGHT (ic));
10499 operand *right = IC_RIGHT (ic);
10502 D (emitcode (";", "genCast ");
10505 /* if they are equivalent then do nothing */
10506 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10509 aopOp (right, ic, FALSE, FALSE);
10510 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10512 /* if the result is a bit */
10513 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10514 if (IS_BITVAR(OP_SYMBOL(result)->type))
10516 /* if the right size is a literal then
10517 we know what the value is */
10518 if (AOP_TYPE (right) == AOP_LIT)
10520 if (((int) operandLitValue (right)))
10521 aopPut (AOP (result), one, 0);
10523 aopPut (AOP (result), zero, 0);
10528 /* the right is also a bit variable */
10529 if (AOP_TYPE (right) == AOP_CRY)
10531 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10532 aopPut (AOP (result), "c", 0);
10536 /* we need to or */
10538 aopPut (AOP (result), "a", 0);
10542 /* if they are the same size : or less */
10543 if (AOP_SIZE (result) <= AOP_SIZE (right))
10546 /* if they are in the same place */
10547 if (sameRegs (AOP (right), AOP (result)))
10550 /* if they in different places then copy */
10551 size = AOP_SIZE (result);
10553 _startLazyDPSEvaluation ();
10556 aopPut (AOP (result),
10557 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10561 _endLazyDPSEvaluation ();
10566 /* if the result is of type pointer */
10567 if (IS_PTR (ctype))
10571 sym_link *type = operandType (right);
10573 /* pointer to generic pointer */
10574 if (IS_GENPTR (ctype))
10580 p_type = DCL_TYPE (type);
10584 #if OLD_CAST_BEHAVIOR
10585 /* KV: we are converting a non-pointer type to
10586 * a generic pointer. This (ifdef'd out) code
10587 * says that the resulting generic pointer
10588 * should have the same class as the storage
10589 * location of the non-pointer variable.
10591 * For example, converting an int (which happens
10592 * to be stored in DATA space) to a pointer results
10593 * in a DATA generic pointer; if the original int
10594 * in XDATA space, so will be the resulting pointer.
10596 * I don't like that behavior, and thus this change:
10597 * all such conversions will be forced to XDATA and
10598 * throw a warning. If you want some non-XDATA
10599 * type, or you want to suppress the warning, you
10600 * must go through an intermediate cast, like so:
10602 * char _generic *gp = (char _xdata *)(intVar);
10604 sym_link *etype = getSpec (type);
10606 /* we have to go by the storage class */
10607 if (SPEC_OCLS (etype) != generic)
10609 p_type = PTR_TYPE (SPEC_OCLS (etype));
10614 /* Converting unknown class (i.e. register variable)
10615 * to generic pointer. This is not good, but
10616 * we'll make a guess (and throw a warning).
10619 werror (W_INT_TO_GEN_PTR_CAST);
10623 /* the first two bytes are known */
10624 size = GPTRSIZE - 1;
10626 _startLazyDPSEvaluation ();
10629 aopPut (AOP (result),
10630 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10634 _endLazyDPSEvaluation ();
10636 /* the last byte depending on type */
10654 /* this should never happen */
10655 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10656 "got unknown pointer type");
10659 aopPut (AOP (result), l, GPTRSIZE - 1);
10663 /* just copy the pointers */
10664 size = AOP_SIZE (result);
10666 _startLazyDPSEvaluation ();
10669 aopPut (AOP (result),
10670 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10674 _endLazyDPSEvaluation ();
10678 /* so we now know that the size of destination is greater
10679 than the size of the source */
10680 /* we move to result for the size of source */
10681 size = AOP_SIZE (right);
10683 _startLazyDPSEvaluation ();
10686 aopPut (AOP (result),
10687 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10691 _endLazyDPSEvaluation ();
10693 /* now depending on the sign of the source && destination */
10694 size = AOP_SIZE (result) - AOP_SIZE (right);
10695 /* if unsigned or not an integral type */
10696 /* also, if the source is a bit, we don't need to sign extend, because
10697 * it can't possibly have set the sign bit.
10699 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10703 aopPut (AOP (result), zero, offset++);
10708 /* we need to extend the sign :{ */
10709 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10710 FALSE, FALSE, TRUE);
10712 emitcode ("rlc", "a");
10713 emitcode ("subb", "a,acc");
10715 aopPut (AOP (result), "a", offset++);
10718 /* we are done hurray !!!! */
10721 freeAsmop (right, NULL, ic, TRUE);
10722 freeAsmop (result, NULL, ic, TRUE);
10726 /*-----------------------------------------------------------------*/
10727 /* genDjnz - generate decrement & jump if not zero instrucion */
10728 /*-----------------------------------------------------------------*/
10730 genDjnz (iCode * ic, iCode * ifx)
10732 symbol *lbl, *lbl1;
10736 /* if the if condition has a false label
10737 then we cannot save */
10738 if (IC_FALSE (ifx))
10741 /* if the minus is not of the form
10743 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10744 !IS_OP_LITERAL (IC_RIGHT (ic)))
10747 if (operandLitValue (IC_RIGHT (ic)) != 1)
10750 /* if the size of this greater than one then no
10752 if (getSize (operandType (IC_RESULT (ic))) > 1)
10755 /* otherwise we can save BIG */
10756 D(emitcode(";", "genDjnz"););
10758 lbl = newiTempLabel (NULL);
10759 lbl1 = newiTempLabel (NULL);
10761 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10763 if (AOP_NEEDSACC(IC_RESULT(ic)))
10765 /* If the result is accessed indirectly via
10766 * the accumulator, we must explicitly write
10767 * it back after the decrement.
10769 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10771 if (strcmp(rByte, "a"))
10773 /* Something is hopelessly wrong */
10774 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10775 __FILE__, __LINE__);
10776 /* We can just give up; the generated code will be inefficient,
10777 * but what the hey.
10779 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10782 emitcode ("dec", "%s", rByte);
10783 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10784 emitcode ("jnz", "!tlabel", lbl->key + 100);
10786 else if (IS_AOP_PREG (IC_RESULT (ic)))
10788 emitcode ("dec", "%s",
10789 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10790 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10791 emitcode ("jnz", "!tlabel", lbl->key + 100);
10795 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10798 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10799 emitcode ("", "!tlabeldef", lbl->key + 100);
10800 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10801 emitcode ("", "!tlabeldef", lbl1->key + 100);
10803 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10804 ifx->generated = 1;
10808 /*-----------------------------------------------------------------*/
10809 /* genReceive - generate code for a receive iCode */
10810 /*-----------------------------------------------------------------*/
10812 genReceive (iCode * ic)
10815 D (emitcode (";", "genReceive ");
10818 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10819 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10820 IS_TRUE_SYMOP (IC_RESULT (ic))))
10822 int size = getSize (operandType (IC_RESULT (ic)));
10823 int offset = fReturnSizeDS390 - size;
10826 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10827 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10830 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10831 size = AOP_SIZE (IC_RESULT (ic));
10835 emitcode ("pop", "acc");
10836 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10843 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10845 assignResultValue (IC_RESULT (ic));
10848 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10851 /*-----------------------------------------------------------------*/
10852 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10853 /*-----------------------------------------------------------------*/
10854 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10856 operand *from , *to , *count;
10861 /* we know it has to be 3 parameters */
10862 assert (nparms == 3);
10864 rsave = newBitVect(16);
10865 /* save DPTR if it needs to be saved */
10866 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10867 if (bitVectBitValue(ic->rMask,i))
10868 rsave = bitVectSetBit(rsave,i);
10870 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10871 ds390_rUmaskForOp (IC_RESULT(ic))));
10878 aopOp (from, ic->next, FALSE, FALSE);
10880 /* get from into DPTR1 */
10881 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10882 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10883 if (options.model == MODEL_FLAT24) {
10884 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10887 freeAsmop (from, NULL, ic, FALSE);
10888 aopOp (to, ic, FALSE, FALSE);
10889 /* get "to" into DPTR */
10890 /* if the operand is already in dptr
10891 then we do nothing else we move the value to dptr */
10892 if (AOP_TYPE (to) != AOP_STR) {
10893 /* if already in DPTR then we need to push */
10894 if (AOP_TYPE(to) == AOP_DPTR) {
10895 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10896 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10897 if (options.model == MODEL_FLAT24)
10898 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10899 emitcode ("pop", "dph");
10900 emitcode ("pop", "dpl");
10902 _startLazyDPSEvaluation ();
10903 /* if this is remateriazable */
10904 if (AOP_TYPE (to) == AOP_IMMD) {
10905 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10906 } else { /* we need to get it byte by byte */
10907 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10908 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10909 if (options.model == MODEL_FLAT24) {
10910 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10913 _endLazyDPSEvaluation ();
10916 freeAsmop (to, NULL, ic, FALSE);
10918 aopOp (count, ic->next->next, FALSE,FALSE);
10919 lbl =newiTempLabel(NULL);
10921 /* now for the actual copy */
10922 if (AOP_TYPE(count) == AOP_LIT &&
10923 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10924 emitcode (";","OH JOY auto increment with djnz (very fast)");
10925 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10926 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10927 emitcode ("","!tlabeldef",lbl->key+100);
10929 emitcode ("clr","a");
10930 emitcode ("movc", "a,@a+dptr");
10932 emitcode ("movx", "a,@dptr");
10933 emitcode ("movx", "@dptr,a");
10934 emitcode ("inc", "dptr");
10935 emitcode ("inc", "dptr");
10936 emitcode ("djnz","b,!tlabel",lbl->key+100);
10938 symbol *lbl1 = newiTempLabel(NULL);
10940 emitcode (";"," Auto increment but no djnz");
10941 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10942 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10943 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10944 emitcode ("","!tlabeldef",lbl->key+100);
10946 emitcode ("clr","a");
10947 emitcode ("movc", "a,@a+dptr");
10949 emitcode ("movx", "a,@dptr");
10950 emitcode ("movx", "@dptr,a");
10951 emitcode ("inc", "dptr");
10952 emitcode ("inc", "dptr");
10953 emitcode ("mov","a,b");
10954 emitcode ("orl","a,_ap");
10955 emitcode ("jz","!tlabel",lbl1->key+100);
10956 emitcode ("mov","a,_ap");
10957 emitcode ("add","a,#!constbyte",0xFF);
10958 emitcode ("mov","_ap,a");
10959 emitcode ("mov","a,b");
10960 emitcode ("addc","a,#!constbyte",0xFF);
10961 emitcode ("mov","b,a");
10962 emitcode ("sjmp","!tlabel",lbl->key+100);
10963 emitcode ("","!tlabeldef",lbl1->key+100);
10965 emitcode ("mov", "dps,#0");
10966 freeAsmop (count, NULL, ic, FALSE);
10967 unsavermask(rsave);
10971 /*-----------------------------------------------------------------*/
10972 /* genMemsetX - gencode for memSetX data */
10973 /*-----------------------------------------------------------------*/
10974 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10976 operand *to , *val , *count;
10980 bitVect *rsave = NULL;
10982 /* we know it has to be 3 parameters */
10983 assert (nparms == 3);
10989 /* save DPTR if it needs to be saved */
10990 rsave = newBitVect(16);
10991 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10992 if (bitVectBitValue(ic->rMask,i))
10993 rsave = bitVectSetBit(rsave,i);
10995 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10996 ds390_rUmaskForOp (IC_RESULT(ic))));
10999 aopOp (to, ic, FALSE, FALSE);
11000 /* get "to" into DPTR */
11001 /* if the operand is already in dptr
11002 then we do nothing else we move the value to dptr */
11003 if (AOP_TYPE (to) != AOP_STR) {
11004 /* if already in DPTR then we need to push */
11005 if (AOP_TYPE(to) == AOP_DPTR) {
11006 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11007 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11008 if (options.model == MODEL_FLAT24)
11009 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11010 emitcode ("pop", "dph");
11011 emitcode ("pop", "dpl");
11013 _startLazyDPSEvaluation ();
11014 /* if this is remateriazable */
11015 if (AOP_TYPE (to) == AOP_IMMD) {
11016 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11017 } else { /* we need to get it byte by byte */
11018 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11019 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11020 if (options.model == MODEL_FLAT24) {
11021 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11024 _endLazyDPSEvaluation ();
11027 freeAsmop (to, NULL, ic, FALSE);
11029 aopOp (val, ic->next->next, FALSE,FALSE);
11030 aopOp (count, ic->next->next, FALSE,FALSE);
11031 lbl =newiTempLabel(NULL);
11032 /* now for the actual copy */
11033 if (AOP_TYPE(count) == AOP_LIT &&
11034 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11035 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11036 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11038 emitcode ("","!tlabeldef",lbl->key+100);
11039 emitcode ("movx", "@dptr,a");
11040 emitcode ("inc", "dptr");
11041 emitcode ("djnz","b,!tlabel",lbl->key+100);
11043 symbol *lbl1 = newiTempLabel(NULL);
11045 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11046 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11047 emitcode ("","!tlabeldef",lbl->key+100);
11048 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11050 emitcode ("movx", "a,@dptr");
11051 emitcode ("inc", "dptr");
11052 emitcode ("mov","a,b");
11053 emitcode ("orl","a,_ap");
11054 emitcode ("jz","!tlabel",lbl1->key+100);
11055 emitcode ("mov","a,_ap");
11056 emitcode ("add","a,#!constbyte",0xFF);
11057 emitcode ("mov","_ap,a");
11058 emitcode ("mov","a,b");
11059 emitcode ("addc","a,#!constbyte",0xFF);
11060 emitcode ("mov","b,a");
11061 emitcode ("sjmp","!tlabel",lbl->key+100);
11062 emitcode ("","!tlabeldef",lbl1->key+100);
11064 freeAsmop (count, NULL, ic, FALSE);
11065 unsavermask(rsave);
11068 /*-----------------------------------------------------------------*/
11069 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11070 /*-----------------------------------------------------------------*/
11071 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11074 operand *pnum, *result;
11077 assert (nparms==1);
11078 /* save registers that need to be saved */
11079 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11080 ds390_rUmaskForOp (IC_RESULT(ic))));
11083 aopOp (pnum, ic, FALSE, FALSE);
11084 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11085 freeAsmop (pnum, NULL, ic, FALSE);
11086 emitcode ("lcall","NatLib_LoadPrimitive");
11087 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11088 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11089 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11090 for (i = (size-1) ; i >= 0 ; i-- ) {
11091 emitcode ("push","a%s",javaRet[i]);
11093 for (i=0; i < size ; i++ ) {
11094 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11097 for (i = 0 ; i < size ; i++ ) {
11098 aopPut(AOP(result),javaRet[i],i);
11101 freeAsmop (result, NULL, ic, FALSE);
11102 unsavermask(rsave);
11105 /*-----------------------------------------------------------------*/
11106 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11107 /*-----------------------------------------------------------------*/
11108 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11111 operand *pnum, *result;
11115 assert (nparms==1);
11116 /* save registers that need to be saved */
11117 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11118 ds390_rUmaskForOp (IC_RESULT(ic))));
11121 aopOp (pnum, ic, FALSE, FALSE);
11122 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11123 freeAsmop (pnum, NULL, ic, FALSE);
11124 emitcode ("lcall","NatLib_LoadPointer");
11125 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11126 if (AOP_TYPE(result)!=AOP_STR) {
11127 for (i = 0 ; i < size ; i++ ) {
11128 aopPut(AOP(result),fReturn[i],i);
11131 freeAsmop (result, NULL, ic, FALSE);
11132 unsavermask(rsave);
11135 /*-----------------------------------------------------------------*/
11136 /* genNatLibInstallStateBlock - */
11137 /*-----------------------------------------------------------------*/
11138 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11139 operand **parms, const char *name)
11142 operand *psb, *handle;
11143 assert (nparms==2);
11145 /* save registers that need to be saved */
11146 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11147 ds390_rUmaskForOp (IC_RESULT(ic))));
11151 /* put pointer to state block into DPTR1 */
11152 aopOp (psb, ic, FALSE, FALSE);
11153 if (AOP_TYPE (psb) == AOP_IMMD) {
11154 emitcode ("mov","dps,#1");
11155 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11156 emitcode ("mov","dps,#0");
11158 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11159 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11160 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11162 freeAsmop (psb, NULL, ic, FALSE);
11164 /* put libraryID into DPTR */
11165 emitcode ("mov","dptr,#LibraryID");
11167 /* put handle into r3:r2 */
11168 aopOp (handle, ic, FALSE, FALSE);
11169 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11170 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11171 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11172 emitcode ("pop","ar3");
11173 emitcode ("pop","ar2");
11175 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11176 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11178 freeAsmop (psb, NULL, ic, FALSE);
11180 /* make the call */
11181 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11183 /* put return value into place*/
11185 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11187 aopPut(AOP(IC_RESULT(ic)),"a",0);
11188 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11189 unsavermask(rsave);
11192 /*-----------------------------------------------------------------*/
11193 /* genNatLibRemoveStateBlock - */
11194 /*-----------------------------------------------------------------*/
11195 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11201 /* save registers that need to be saved */
11202 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11203 ds390_rUmaskForOp (IC_RESULT(ic))));
11205 /* put libraryID into DPTR */
11206 emitcode ("mov","dptr,#LibraryID");
11207 /* make the call */
11208 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11209 unsavermask(rsave);
11212 /*-----------------------------------------------------------------*/
11213 /* genNatLibGetStateBlock - */
11214 /*-----------------------------------------------------------------*/
11215 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11216 operand **parms,const char *name)
11219 symbol *lbl = newiTempLabel(NULL);
11222 /* save registers that need to be saved */
11223 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11224 ds390_rUmaskForOp (IC_RESULT(ic))));
11226 /* put libraryID into DPTR */
11227 emitcode ("mov","dptr,#LibraryID");
11228 /* make the call */
11229 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11230 emitcode ("jnz","!tlabel",lbl->key+100);
11232 /* put return value into place */
11233 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11234 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11235 emitcode ("push","ar3");
11236 emitcode ("push","ar2");
11237 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11238 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11240 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11241 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11243 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11244 emitcode ("","!tlabeldef",lbl->key+100);
11245 unsavermask(rsave);
11248 /*-----------------------------------------------------------------*/
11249 /* genMMMalloc - */
11250 /*-----------------------------------------------------------------*/
11251 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11252 int size, const char *name)
11257 symbol *lbl = newiTempLabel(NULL);
11259 assert (nparms == 1);
11260 /* save registers that need to be saved */
11261 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11262 ds390_rUmaskForOp (IC_RESULT(ic))));
11265 aopOp (bsize,ic,FALSE,FALSE);
11267 /* put the size in R4-R2 */
11268 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11269 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11270 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11272 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11273 emitcode("pop","ar4");
11275 emitcode("pop","ar3");
11276 emitcode("pop","ar2");
11278 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11279 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11281 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11284 freeAsmop (bsize, NULL, ic, FALSE);
11286 /* make the call */
11287 emitcode ("lcall","MM_%s",name);
11288 emitcode ("jz","!tlabel",lbl->key+100);
11289 emitcode ("mov","r2,#!constbyte",0xff);
11290 emitcode ("mov","r3,#!constbyte",0xff);
11291 emitcode ("","!tlabeldef",lbl->key+100);
11292 /* we don't care about the pointer : we just save the handle */
11293 rsym = OP_SYMBOL(IC_RESULT(ic));
11294 if (rsym->liveFrom != rsym->liveTo) {
11295 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11296 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11297 emitcode ("push","ar3");
11298 emitcode ("push","ar2");
11299 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11300 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11302 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11303 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11305 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11307 unsavermask(rsave);
11310 /*-----------------------------------------------------------------*/
11312 /*-----------------------------------------------------------------*/
11313 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11318 assert (nparms == 1);
11319 /* save registers that need to be saved */
11320 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11321 ds390_rUmaskForOp (IC_RESULT(ic))));
11324 aopOp (handle,ic,FALSE,FALSE);
11326 /* put the size in R4-R2 */
11327 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11328 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11329 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11330 emitcode("pop","ar3");
11331 emitcode("pop","ar2");
11333 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11334 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11336 freeAsmop (handle, NULL, ic, FALSE);
11338 /* make the call */
11339 emitcode ("lcall","MM_Deref");
11342 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11343 if (rsym->liveFrom != rsym->liveTo) {
11344 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11345 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11346 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11347 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11348 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11352 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11353 unsavermask(rsave);
11356 /*-----------------------------------------------------------------*/
11357 /* genMMUnrestrictedPersist - */
11358 /*-----------------------------------------------------------------*/
11359 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11364 assert (nparms == 1);
11365 /* save registers that need to be saved */
11366 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11367 ds390_rUmaskForOp (IC_RESULT(ic))));
11370 aopOp (handle,ic,FALSE,FALSE);
11372 /* put the size in R3-R2 */
11373 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11374 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11375 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11376 emitcode("pop","ar3");
11377 emitcode("pop","ar2");
11379 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11380 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11382 freeAsmop (handle, NULL, ic, FALSE);
11384 /* make the call */
11385 emitcode ("lcall","MM_UnrestrictedPersist");
11388 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11389 if (rsym->liveFrom != rsym->liveTo) {
11390 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11391 aopPut(AOP(IC_RESULT(ic)),"a",0);
11392 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11395 unsavermask(rsave);
11398 /*-----------------------------------------------------------------*/
11399 /* genSystemExecJavaProcess - */
11400 /*-----------------------------------------------------------------*/
11401 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11404 operand *handle, *pp;
11406 assert (nparms==2);
11407 /* save registers that need to be saved */
11408 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11409 ds390_rUmaskForOp (IC_RESULT(ic))));
11414 /* put the handle in R3-R2 */
11415 aopOp (handle,ic,FALSE,FALSE);
11416 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11417 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11418 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11419 emitcode("pop","ar3");
11420 emitcode("pop","ar2");
11422 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11423 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11425 freeAsmop (handle, NULL, ic, FALSE);
11427 /* put pointer in DPTR */
11428 aopOp (pp,ic,FALSE,FALSE);
11429 if (AOP_TYPE(pp) == AOP_IMMD) {
11430 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11431 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11432 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11433 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11434 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11436 freeAsmop (handle, NULL, ic, FALSE);
11438 /* make the call */
11439 emitcode ("lcall","System_ExecJavaProcess");
11441 /* put result in place */
11443 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11444 if (rsym->liveFrom != rsym->liveTo) {
11445 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11446 aopPut(AOP(IC_RESULT(ic)),"a",0);
11447 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11451 unsavermask(rsave);
11454 /*-----------------------------------------------------------------*/
11455 /* genSystemRTCRegisters - */
11456 /*-----------------------------------------------------------------*/
11457 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11463 assert (nparms==1);
11464 /* save registers that need to be saved */
11465 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11466 ds390_rUmaskForOp (IC_RESULT(ic))));
11469 /* put pointer in DPTR */
11470 aopOp (pp,ic,FALSE,FALSE);
11471 if (AOP_TYPE (pp) == AOP_IMMD) {
11472 emitcode ("mov","dps,#1");
11473 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11474 emitcode ("mov","dps,#0");
11476 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11477 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11478 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11480 freeAsmop (pp, NULL, ic, FALSE);
11482 /* make the call */
11483 emitcode ("lcall","System_%sRTCRegisters",name);
11485 unsavermask(rsave);
11488 /*-----------------------------------------------------------------*/
11489 /* genSystemThreadSleep - */
11490 /*-----------------------------------------------------------------*/
11491 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11496 assert (nparms==1);
11497 /* save registers that need to be saved */
11498 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11499 ds390_rUmaskForOp (IC_RESULT(ic))));
11502 aopOp(to,ic,FALSE,FALSE);
11503 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11504 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11505 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11506 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11507 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11508 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11509 emitcode ("pop","ar3");
11510 emitcode ("pop","ar2");
11511 emitcode ("pop","ar1");
11512 emitcode ("pop","ar0");
11514 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11515 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11516 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11517 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11519 freeAsmop (to, NULL, ic, FALSE);
11521 /* suspend in acc */
11523 aopOp(s,ic,FALSE,FALSE);
11524 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11525 freeAsmop (s, NULL, ic, FALSE);
11527 /* make the call */
11528 emitcode ("lcall","System_%s",name);
11530 unsavermask(rsave);
11533 /*-----------------------------------------------------------------*/
11534 /* genSystemThreadResume - */
11535 /*-----------------------------------------------------------------*/
11536 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11541 assert (nparms==2);
11542 /* save registers that need to be saved */
11543 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11544 ds390_rUmaskForOp (IC_RESULT(ic))));
11550 aopOp(pid,ic,FALSE,FALSE);
11551 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11552 freeAsmop (pid, NULL, ic, FALSE);
11555 aopOp(tid,ic,FALSE,FALSE);
11556 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11557 freeAsmop (tid, NULL, ic, FALSE);
11559 emitcode ("lcall","System_ThreadResume");
11561 /* put result into place */
11563 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11564 if (rsym->liveFrom != rsym->liveTo) {
11565 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11566 aopPut(AOP(IC_RESULT(ic)),"a",0);
11567 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11570 unsavermask(rsave);
11573 /*-----------------------------------------------------------------*/
11574 /* genSystemProcessResume - */
11575 /*-----------------------------------------------------------------*/
11576 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11581 assert (nparms==1);
11582 /* save registers that need to be saved */
11583 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11584 ds390_rUmaskForOp (IC_RESULT(ic))));
11589 aopOp(pid,ic,FALSE,FALSE);
11590 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11591 freeAsmop (pid, NULL, ic, FALSE);
11593 emitcode ("lcall","System_ProcessResume");
11595 unsavermask(rsave);
11598 /*-----------------------------------------------------------------*/
11600 /*-----------------------------------------------------------------*/
11601 static void genSystem (iCode *ic,int nparms,char *name)
11603 assert(nparms == 0);
11605 emitcode ("lcall","System_%s",name);
11608 /*-----------------------------------------------------------------*/
11609 /* genSystemPoll - */
11610 /*-----------------------------------------------------------------*/
11611 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11616 assert (nparms==1);
11617 /* save registers that need to be saved */
11618 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11619 ds390_rUmaskForOp (IC_RESULT(ic))));
11622 aopOp (fp,ic,FALSE,FALSE);
11623 if (AOP_TYPE (fp) == AOP_IMMD) {
11624 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11625 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11626 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11627 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11628 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11630 freeAsmop (fp, NULL, ic, FALSE);
11632 emitcode ("lcall","System_%sPoll",name);
11634 /* put result into place */
11636 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11637 if (rsym->liveFrom != rsym->liveTo) {
11638 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11639 aopPut(AOP(IC_RESULT(ic)),"a",0);
11640 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11643 unsavermask(rsave);
11646 /*-----------------------------------------------------------------*/
11647 /* genSystemGetCurrentID - */
11648 /*-----------------------------------------------------------------*/
11649 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11651 assert (nparms==0);
11653 emitcode ("lcall","System_GetCurrent%sId",name);
11654 /* put result into place */
11656 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11657 if (rsym->liveFrom != rsym->liveTo) {
11658 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11659 aopPut(AOP(IC_RESULT(ic)),"a",0);
11660 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11665 /*-----------------------------------------------------------------*/
11666 /* genBuiltIn - calls the appropriate function to generating code */
11667 /* for a built in function */
11668 /*-----------------------------------------------------------------*/
11669 static void genBuiltIn (iCode *ic)
11671 operand *bi_parms[MAX_BUILTIN_ARGS];
11676 /* get all the arguments for a built in function */
11677 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11679 /* which function is it */
11680 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11681 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11682 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11683 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11684 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11685 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11686 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11687 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11688 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11689 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11690 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11691 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11692 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11693 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11694 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11695 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11696 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11697 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11698 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11699 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11700 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11701 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11702 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11703 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11704 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11705 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11706 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11707 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11708 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11709 } else if (strcmp(bif->name,"MM_Malloc")==0) {
11710 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11711 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11712 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11713 } else if (strcmp(bif->name,"MM_Free")==0) {
11714 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11715 } else if (strcmp(bif->name,"MM_Deref")==0) {
11716 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11717 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11718 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11719 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11720 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11721 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11722 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11723 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11724 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11725 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11726 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11727 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11728 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11729 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11730 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11731 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11732 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11733 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11734 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11735 } else if (strcmp(bif->name,"System_SaveThread")==0) {
11736 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11737 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11738 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11739 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11740 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11741 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11742 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11743 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11744 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11745 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11746 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11747 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11748 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11749 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11750 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11751 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11752 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11753 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11754 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11755 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11756 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11758 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11764 /*-----------------------------------------------------------------*/
11765 /* gen390Code - generate code for Dallas 390 based controllers */
11766 /*-----------------------------------------------------------------*/
11768 gen390Code (iCode * lic)
11773 lineHead = lineCurr = NULL;
11775 if (options.model == MODEL_FLAT24) {
11776 fReturnSizeDS390 = 5;
11777 fReturn = fReturn24;
11779 fReturnSizeDS390 = 4;
11780 fReturn = fReturn16;
11781 options.stack10bit=0;
11785 /* print the allocation information */
11787 printAllocInfo (currFunc, codeOutFile);
11789 /* if debug information required */
11790 if (options.debug && currFunc)
11792 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11794 if (IS_STATIC (currFunc->etype))
11795 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11797 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11800 /* stack pointer name */
11801 if (options.useXstack)
11807 for (ic = lic; ic; ic = ic->next)
11810 if (cln != ic->lineno)
11815 emitcode ("", "C$%s$%d$%d$%d ==.",
11816 FileBaseName (ic->filename), ic->lineno,
11817 ic->level, ic->block);
11820 emitcode (";", "%s %d", ic->filename, ic->lineno);
11823 /* if the result is marked as
11824 spilt and rematerializable or code for
11825 this has already been generated then
11827 if (resultRemat (ic) || ic->generated)
11830 /* depending on the operation */
11850 /* IPOP happens only when trying to restore a
11851 spilt live range, if there is an ifx statement
11852 following this pop then the if statement might
11853 be using some of the registers being popped which
11854 would destory the contents of the register so
11855 we need to check for this condition and handle it */
11857 ic->next->op == IFX &&
11858 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11859 genIfx (ic->next, ic);
11877 genEndFunction (ic);
11897 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11914 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11918 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11925 /* note these two are xlated by algebraic equivalence
11926 during parsing SDCC.y */
11927 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11928 "got '>=' or '<=' shouldn't have come here");
11932 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11944 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11948 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11952 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11976 genRightShift (ic);
11979 case GET_VALUE_AT_ADDRESS:
11980 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11984 if (POINTER_SET (ic))
11985 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12011 if (ic->builtinSEND) genBuiltIn(ic);
12012 else addSet (&_G.sendSet, ic);
12025 /* now we are ready to call the
12026 peep hole optimizer */
12027 if (!options.nopeep)
12028 peepHole (&lineHead);
12030 /* now do the actual printing */
12031 printLine (lineHead, codeOutFile);