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 /*-----------------------------------------------------------------*/
1696 D (emitcode (";", "genCpl ");
1700 /* assign asmOps to operand & result */
1701 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1702 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1704 /* if both are in bit space then
1706 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1707 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1710 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1711 emitcode ("cpl", "c");
1712 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1716 size = AOP_SIZE (IC_RESULT (ic));
1717 _startLazyDPSEvaluation ();
1720 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1722 emitcode ("cpl", "a");
1723 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1725 _endLazyDPSEvaluation ();
1729 /* release the aops */
1730 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1734 /*-----------------------------------------------------------------*/
1735 /* genUminusFloat - unary minus for floating points */
1736 /*-----------------------------------------------------------------*/
1738 genUminusFloat (operand * op, operand * result)
1740 int size, offset = 0;
1742 /* for this we just need to flip the
1743 first it then copy the rest in place */
1744 D (emitcode (";", "genUminusFloat");
1747 _startLazyDPSEvaluation ();
1748 size = AOP_SIZE (op) - 1;
1749 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1752 emitcode ("cpl", "acc.7");
1753 aopPut (AOP (result), "a", 3);
1757 aopPut (AOP (result),
1758 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1762 _endLazyDPSEvaluation ();
1765 /*-----------------------------------------------------------------*/
1766 /* genUminus - unary minus code generation */
1767 /*-----------------------------------------------------------------*/
1769 genUminus (iCode * ic)
1772 sym_link *optype, *rtype;
1774 D (emitcode (";", "genUminus ");
1779 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1780 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1782 /* if both in bit space then special
1784 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1785 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1788 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1789 emitcode ("cpl", "c");
1790 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1794 optype = operandType (IC_LEFT (ic));
1795 rtype = operandType (IC_RESULT (ic));
1797 /* if float then do float stuff */
1798 if (IS_FLOAT (optype))
1800 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1804 /* otherwise subtract from zero */
1805 size = AOP_SIZE (IC_LEFT (ic));
1807 _startLazyDPSEvaluation ();
1810 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1811 if (!strcmp (l, "a"))
1815 emitcode ("cpl", "a");
1816 emitcode ("addc", "a,#0");
1822 emitcode ("clr", "a");
1823 emitcode ("subb", "a,%s", l);
1825 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1827 _endLazyDPSEvaluation ();
1829 /* if any remaining bytes in the result */
1830 /* we just need to propagate the sign */
1831 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1833 emitcode ("rlc", "a");
1834 emitcode ("subb", "a,acc");
1836 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1840 /* release the aops */
1841 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1845 /*-----------------------------------------------------------------*/
1846 /* savermask - saves registers in the mask */
1847 /*-----------------------------------------------------------------*/
1848 static void savermask(bitVect *rs_mask)
1851 if (options.useXstack) {
1852 if (bitVectBitValue (rs_mask, R0_IDX))
1853 emitcode ("mov", "b,r0");
1854 emitcode ("mov", "r0,%s", spname);
1855 for (i = 0; i < ds390_nRegs; i++) {
1856 if (bitVectBitValue (rs_mask, i)) {
1858 emitcode ("mov", "a,b");
1860 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1861 emitcode ("movx", "@r0,a");
1862 emitcode ("inc", "r0");
1865 emitcode ("mov", "%s,r0", spname);
1866 if (bitVectBitValue (rs_mask, R0_IDX))
1867 emitcode ("mov", "r0,b");
1869 for (i = 0; i < ds390_nRegs; i++) {
1870 if (bitVectBitValue (rs_mask, i))
1871 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1876 /*-----------------------------------------------------------------*/
1877 /* saveRegisters - will look for a call and save the registers */
1878 /*-----------------------------------------------------------------*/
1880 saveRegisters (iCode * lic)
1886 for (ic = lic; ic; ic = ic->next)
1887 if (ic->op == CALL || ic->op == PCALL)
1892 fprintf (stderr, "found parameter push with no function call\n");
1896 /* if the registers have been saved already then
1898 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1900 /* special case if DPTR alive across a function call then must save it
1901 even though callee saves */
1902 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1904 rsave = newBitVect(ic->rMask->size);
1905 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1906 if (bitVectBitValue(ic->rMask,i))
1907 rsave = bitVectSetBit(rsave,i);
1909 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1911 /* safe the registers in use at this time but skip the
1912 ones for the result */
1913 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1914 ds390_rUmaskForOp (IC_RESULT(ic)));
1920 /*-----------------------------------------------------------------*/
1921 /* usavermask - restore registers with mask */
1922 /*-----------------------------------------------------------------*/
1923 static void unsavermask(bitVect *rs_mask)
1926 if (options.useXstack) {
1927 emitcode ("mov", "r0,%s", spname);
1928 for (i = ds390_nRegs; i >= 0; i--) {
1929 if (bitVectBitValue (rs_mask, i)) {
1930 emitcode ("dec", "r0");
1931 emitcode ("movx", "a,@r0");
1933 emitcode ("mov", "b,a");
1935 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1938 emitcode ("mov", "%s,r0", spname);
1939 if (bitVectBitValue (rs_mask, R0_IDX))
1940 emitcode ("mov", "r0,b");
1942 for (i = ds390_nRegs; i >= 0; i--) {
1943 if (bitVectBitValue (rs_mask, i))
1944 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1949 /*-----------------------------------------------------------------*/
1950 /* unsaveRegisters - pop the pushed registers */
1951 /*-----------------------------------------------------------------*/
1953 unsaveRegisters (iCode * ic)
1957 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1959 rsave = newBitVect(ic->rMask->size);
1960 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1961 if (bitVectBitValue(ic->rMask,i))
1962 rsave = bitVectSetBit(rsave,i);
1964 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1966 /* restore the registers in use at this time but skip the
1967 ones for the result */
1968 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1969 ds390_rUmaskForOp (IC_RESULT(ic)));
1975 /*-----------------------------------------------------------------*/
1977 /*-----------------------------------------------------------------*/
1979 pushSide (operand * oper, int size)
1982 _startLazyDPSEvaluation ();
1985 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1986 if (AOP_TYPE (oper) != AOP_REG &&
1987 AOP_TYPE (oper) != AOP_DIR &&
1990 emitcode ("mov", "a,%s", l);
1991 emitcode ("push", "acc");
1994 emitcode ("push", "%s", l);
1996 _endLazyDPSEvaluation ();
1999 /*-----------------------------------------------------------------*/
2000 /* assignResultValue - */
2001 /*-----------------------------------------------------------------*/
2003 assignResultValue (operand * oper)
2006 int size = AOP_SIZE (oper);
2008 _startLazyDPSEvaluation ();
2011 aopPut (AOP (oper), fReturn[offset], offset);
2014 _endLazyDPSEvaluation ();
2018 /*-----------------------------------------------------------------*/
2019 /* genXpush - pushes onto the external stack */
2020 /*-----------------------------------------------------------------*/
2022 genXpush (iCode * ic)
2024 asmop *aop = newAsmop (0);
2026 int size, offset = 0;
2028 D (emitcode (";", "genXpush ");
2031 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2032 r = getFreePtr (ic, &aop, FALSE);
2035 emitcode ("mov", "%s,_spx", r->name);
2037 size = AOP_SIZE (IC_LEFT (ic));
2038 _startLazyDPSEvaluation ();
2042 char *l = aopGet (AOP (IC_LEFT (ic)),
2043 offset++, FALSE, FALSE, TRUE);
2045 emitcode ("movx", "@%s,a", r->name);
2046 emitcode ("inc", "%s", r->name);
2049 _endLazyDPSEvaluation ();
2052 emitcode ("mov", "_spx,%s", r->name);
2054 freeAsmop (NULL, aop, ic, TRUE);
2055 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2058 /*-----------------------------------------------------------------*/
2059 /* genIpush - genrate code for pushing this gets a little complex */
2060 /*-----------------------------------------------------------------*/
2062 genIpush (iCode * ic)
2064 int size, offset = 0;
2067 D (emitcode (";", "genIpush ");
2070 /* if this is not a parm push : ie. it is spill push
2071 and spill push is always done on the local stack */
2075 /* and the item is spilt then do nothing */
2076 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2079 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2080 size = AOP_SIZE (IC_LEFT (ic));
2081 /* push it on the stack */
2082 _startLazyDPSEvaluation ();
2085 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2091 emitcode ("push", "%s", l);
2093 _endLazyDPSEvaluation ();
2097 /* this is a paramter push: in this case we call
2098 the routine to find the call and save those
2099 registers that need to be saved */
2102 /* if use external stack then call the external
2103 stack pushing routine */
2104 if (options.useXstack)
2110 /* then do the push */
2111 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2113 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2114 size = AOP_SIZE (IC_LEFT (ic));
2116 _startLazyDPSEvaluation ();
2119 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2120 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2121 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2124 emitcode ("mov", "a,%s", l);
2125 emitcode ("push", "acc");
2128 emitcode ("push", "%s", l);
2130 _endLazyDPSEvaluation ();
2132 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2135 /*-----------------------------------------------------------------*/
2136 /* genIpop - recover the registers: can happen only for spilling */
2137 /*-----------------------------------------------------------------*/
2139 genIpop (iCode * ic)
2143 D (emitcode (";", "genIpop ");
2147 /* if the temp was not pushed then */
2148 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2151 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2152 size = AOP_SIZE (IC_LEFT (ic));
2153 offset = (size - 1);
2154 _startLazyDPSEvaluation ();
2157 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2158 FALSE, TRUE, TRUE));
2160 _endLazyDPSEvaluation ();
2162 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2165 /*-----------------------------------------------------------------*/
2166 /* unsaveRBank - restores the resgister bank from stack */
2167 /*-----------------------------------------------------------------*/
2169 unsaveRBank (int bank, iCode * ic, bool popPsw)
2175 if (options.useXstack)
2179 /* Assume r0 is available for use. */
2180 r = ds390_regWithIdx (R0_IDX);;
2185 r = getFreePtr (ic, &aop, FALSE);
2187 emitcode ("mov", "%s,_spx", r->name);
2192 if (options.useXstack)
2194 emitcode ("movx", "a,@%s", r->name);
2195 emitcode ("mov", "psw,a");
2196 emitcode ("dec", "%s", r->name);
2200 emitcode ("pop", "psw");
2204 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2206 if (options.useXstack)
2208 emitcode ("movx", "a,@%s", r->name);
2209 emitcode ("mov", "(%s+%d),a",
2210 regs390[i].base, 8 * bank + regs390[i].offset);
2211 emitcode ("dec", "%s", r->name);
2215 emitcode ("pop", "(%s+%d)",
2216 regs390[i].base, 8 * bank + regs390[i].offset);
2219 if (options.useXstack)
2221 emitcode ("mov", "_spx,%s", r->name);
2226 freeAsmop (NULL, aop, ic, TRUE);
2230 /*-----------------------------------------------------------------*/
2231 /* saveRBank - saves an entire register bank on the stack */
2232 /*-----------------------------------------------------------------*/
2234 saveRBank (int bank, iCode * ic, bool pushPsw)
2240 if (options.useXstack)
2244 /* Assume r0 is available for use. */
2245 r = ds390_regWithIdx (R0_IDX);;
2250 r = getFreePtr (ic, &aop, FALSE);
2252 emitcode ("mov", "%s,_spx", r->name);
2255 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2257 if (options.useXstack)
2259 emitcode ("inc", "%s", r->name);
2260 emitcode ("mov", "a,(%s+%d)",
2261 regs390[i].base, 8 * bank + regs390[i].offset);
2262 emitcode ("movx", "@%s,a", r->name);
2265 emitcode ("push", "(%s+%d)",
2266 regs390[i].base, 8 * bank + regs390[i].offset);
2271 if (options.useXstack)
2273 emitcode ("mov", "a,psw");
2274 emitcode ("movx", "@%s,a", r->name);
2275 emitcode ("inc", "%s", r->name);
2276 emitcode ("mov", "_spx,%s", r->name);
2280 emitcode ("push", "psw");
2283 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2288 freeAsmop (NULL, aop, ic, TRUE);
2297 /*-----------------------------------------------------------------*/
2298 /* genCall - generates a call statement */
2299 /*-----------------------------------------------------------------*/
2301 genCall (iCode * ic)
2304 bool restoreBank = FALSE;
2305 bool swapBanks = FALSE;
2307 D (emitcode (";", "genCall "););
2309 /* if we are calling a not _naked function that is not using
2310 the same register bank then we need to save the
2311 destination registers on the stack */
2312 dtype = operandType (IC_LEFT (ic));
2313 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2314 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2315 IFFUNC_ISISR (currFunc->type))
2319 /* This is unexpected; the bank should have been saved in
2322 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2328 /* if caller saves & we have not saved then */
2332 /* if send set is not empty the assign */
2333 /* We've saved all the registers we care about;
2334 * therefore, we may clobber any register not used
2335 * in the calling convention (i.e. anything not in
2342 for (sic = setFirstItem (_G.sendSet); sic;
2343 sic = setNextItem (_G.sendSet))
2345 int size, offset = 0;
2347 // we know that dpl(hxb) is the result, so
2348 _startLazyDPSEvaluation ();
2349 size=getSize(operandType(IC_LEFT(sic)));
2351 aopOp (IC_LEFT (sic), sic, FALSE,
2352 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2354 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2358 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2359 FALSE, FALSE, TRUE);
2360 if (strcmp (l, fReturn[offset]))
2362 emitcode ("mov", "%s,%s",
2368 _endLazyDPSEvaluation ();
2369 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2376 emitcode ("mov", "psw,#!constbyte",
2377 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2381 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2382 OP_SYMBOL (IC_LEFT (ic))->rname :
2383 OP_SYMBOL (IC_LEFT (ic))->name));
2387 emitcode ("mov", "psw,#!constbyte",
2388 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2391 /* if we need assign a result value */
2392 if ((IS_ITEMP (IC_RESULT (ic)) &&
2393 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2394 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2395 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2396 IS_TRUE_SYMOP (IC_RESULT (ic)))
2398 if (isOperandInFarSpace (IC_RESULT (ic))
2399 && getSize (operandType (IC_RESULT (ic))) <= 2)
2401 int size = getSize (operandType (IC_RESULT (ic)));
2403 /* Special case for 1 or 2 byte return in far space. */
2407 emitcode ("mov", "b,%s", fReturn[1]);
2410 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2411 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2415 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2417 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2422 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2425 assignResultValue (IC_RESULT (ic));
2427 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2431 /* adjust the stack for parameters if
2433 if (ic->parmBytes) {
2435 if (options.stack10bit) {
2436 if (ic->parmBytes <= 4) {
2437 emitcode(";","stack adjustment for parms");
2438 for (i=0; i < ic->parmBytes ; i++) {
2439 emitcode("pop","acc");
2442 emitcode ("clr","c");
2443 emitcode ("mov","a,sp");
2444 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2445 emitcode ("mov","sp,a");
2446 emitcode ("mov","a,esp");
2447 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2448 emitcode ("mov","esp,a");
2451 if (ic->parmBytes > 3) {
2452 emitcode ("mov", "a,%s", spname);
2453 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2454 emitcode ("mov", "%s,a", spname);
2456 for (i = 0; i < ic->parmBytes; i++)
2457 emitcode ("dec", "%s", spname);
2461 /* if we hade saved some registers then unsave them */
2463 unsaveRegisters (ic);
2465 /* if register bank was saved then pop them */
2467 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2470 /*-----------------------------------------------------------------*/
2471 /* genPcall - generates a call by pointer statement */
2472 /*-----------------------------------------------------------------*/
2474 genPcall (iCode * ic)
2477 symbol *rlbl = newiTempLabel (NULL);
2478 bool restoreBank=FALSE;
2480 D (emitcode (";", "genPcall ");
2484 /* if caller saves & we have not saved then */
2488 /* if we are calling a function that is not using
2489 the same register bank then we need to save the
2490 destination registers on the stack */
2491 dtype = operandType (IC_LEFT (ic));
2492 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2493 IFFUNC_ISISR (currFunc->type) &&
2494 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2495 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2499 /* push the return address on to the stack */
2500 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2501 emitcode ("push", "acc");
2502 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2503 emitcode ("push", "acc");
2505 if (options.model == MODEL_FLAT24)
2507 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2508 emitcode ("push", "acc");
2511 /* now push the calling address */
2512 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2514 pushSide (IC_LEFT (ic), FPTRSIZE);
2516 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2518 /* if send set is not empty the assign */
2523 for (sic = setFirstItem (_G.sendSet); sic;
2524 sic = setNextItem (_G.sendSet))
2526 int size, offset = 0;
2528 // we know that dpl(hxb) is the result, so
2529 _startLazyDPSEvaluation ();
2530 size=getSize(operandType(IC_LEFT(sic)));
2532 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2534 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2538 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2539 FALSE, FALSE, TRUE);
2540 if (strcmp (l, fReturn[offset]))
2542 emitcode ("mov", "%s,%s",
2548 _endLazyDPSEvaluation ();
2549 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2554 emitcode ("ret", "");
2555 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2558 /* if we need assign a result value */
2559 if ((IS_ITEMP (IC_RESULT (ic)) &&
2560 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2561 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2562 IS_TRUE_SYMOP (IC_RESULT (ic)))
2566 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2569 assignResultValue (IC_RESULT (ic));
2571 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2574 /* adjust the stack for parameters if
2579 if (ic->parmBytes > 3)
2581 emitcode ("mov", "a,%s", spname);
2582 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2583 emitcode ("mov", "%s,a", spname);
2586 for (i = 0; i < ic->parmBytes; i++)
2587 emitcode ("dec", "%s", spname);
2591 /* if register bank was saved then unsave them */
2593 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2595 /* if we hade saved some registers then
2598 unsaveRegisters (ic);
2602 /*-----------------------------------------------------------------*/
2603 /* resultRemat - result is rematerializable */
2604 /*-----------------------------------------------------------------*/
2606 resultRemat (iCode * ic)
2608 if (SKIP_IC (ic) || ic->op == IFX)
2611 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2613 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2614 if (sym->remat && !POINTER_SET (ic))
2621 #if defined(__BORLANDC__) || defined(_MSC_VER)
2622 #define STRCASECMP stricmp
2624 #define STRCASECMP strcasecmp
2627 /*-----------------------------------------------------------------*/
2628 /* inExcludeList - return 1 if the string is in exclude Reg list */
2629 /*-----------------------------------------------------------------*/
2631 inExcludeList (char *s)
2635 if (options.excludeRegs[i] &&
2636 STRCASECMP (options.excludeRegs[i], "none") == 0)
2639 for (i = 0; options.excludeRegs[i]; i++)
2641 if (options.excludeRegs[i] &&
2642 STRCASECMP (s, options.excludeRegs[i]) == 0)
2648 /*-----------------------------------------------------------------*/
2649 /* genFunction - generated code for function entry */
2650 /*-----------------------------------------------------------------*/
2652 genFunction (iCode * ic)
2656 bool switchedPSW = FALSE;
2658 D (emitcode (";", "genFunction "););
2661 /* create the function header */
2662 emitcode (";", "-----------------------------------------");
2663 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2664 emitcode (";", "-----------------------------------------");
2666 emitcode ("", "%s:", sym->rname);
2667 ftype = operandType (IC_LEFT (ic));
2669 if (IFFUNC_ISNAKED(ftype))
2671 emitcode(";", "naked function: no prologue.");
2675 if (options.stack_probe)
2676 emitcode ("lcall","__stack_probe");
2677 /* if critical function then turn interrupts off */
2678 if (IFFUNC_ISCRITICAL (ftype))
2679 emitcode ("clr", "ea");
2681 /* here we need to generate the equates for the
2682 register bank if required */
2683 if (FUNC_REGBANK (ftype) != rbank)
2687 rbank = FUNC_REGBANK (ftype);
2688 for (i = 0; i < ds390_nRegs; i++)
2690 if (regs390[i].print) {
2691 if (strcmp (regs390[i].base, "0") == 0)
2692 emitcode ("", "%s !equ !constbyte",
2694 8 * rbank + regs390[i].offset);
2696 emitcode ("", "%s !equ %s + !constbyte",
2699 8 * rbank + regs390[i].offset);
2704 /* if this is an interrupt service routine then
2705 save acc, b, dpl, dph */
2706 if (IFFUNC_ISISR (sym->type))
2709 if (!inExcludeList ("acc"))
2710 emitcode ("push", "acc");
2711 if (!inExcludeList ("b"))
2712 emitcode ("push", "b");
2713 if (!inExcludeList ("dpl"))
2714 emitcode ("push", "dpl");
2715 if (!inExcludeList ("dph"))
2716 emitcode ("push", "dph");
2717 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2719 emitcode ("push", "dpx");
2720 /* Make sure we're using standard DPTR */
2721 emitcode ("push", "dps");
2722 emitcode ("mov", "dps,#0");
2723 if (options.stack10bit)
2725 /* This ISR could conceivably use DPTR2. Better save it. */
2726 emitcode ("push", "dpl1");
2727 emitcode ("push", "dph1");
2728 emitcode ("push", "dpx1");
2729 emitcode ("push", DP2_RESULT_REG);
2732 /* if this isr has no bank i.e. is going to
2733 run with bank 0 , then we need to save more
2735 if (!FUNC_REGBANK (sym->type))
2738 /* if this function does not call any other
2739 function then we can be economical and
2740 save only those registers that are used */
2741 if (!IFFUNC_HASFCALL(sym->type))
2745 /* if any registers used */
2748 /* save the registers used */
2749 for (i = 0; i < sym->regsUsed->size; i++)
2751 if (bitVectBitValue (sym->regsUsed, i) ||
2752 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2753 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2760 /* this function has a function call cannot
2761 determines register usage so we will have to push the
2763 saveRBank (0, ic, FALSE);
2768 /* This ISR uses a non-zero bank.
2770 * We assume that the bank is available for our
2773 * However, if this ISR calls a function which uses some
2774 * other bank, we must save that bank entirely.
2776 unsigned long banksToSave = 0;
2778 if (IFFUNC_HASFCALL(sym->type))
2781 #define MAX_REGISTER_BANKS 4
2786 for (i = ic; i; i = i->next)
2788 if (i->op == ENDFUNCTION)
2790 /* we got to the end OK. */
2798 dtype = operandType (IC_LEFT(i));
2800 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2802 /* Mark this bank for saving. */
2803 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2805 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2809 banksToSave |= (1 << FUNC_REGBANK(dtype));
2812 /* And note that we don't need to do it in
2820 /* This is a mess; we have no idea what
2821 * register bank the called function might
2824 * The only thing I can think of to do is
2825 * throw a warning and hope.
2827 werror(W_FUNCPTR_IN_USING_ISR);
2831 if (banksToSave && options.useXstack)
2833 /* Since we aren't passing it an ic,
2834 * saveRBank will assume r0 is available to abuse.
2836 * So switch to our (trashable) bank now, so
2837 * the caller's R0 isn't trashed.
2839 emitcode ("push", "psw");
2840 emitcode ("mov", "psw,#!constbyte",
2841 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2845 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2847 if (banksToSave & (1 << ix))
2849 saveRBank(ix, NULL, FALSE);
2853 // jwk: this needs a closer look
2854 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2859 /* if callee-save to be used for this function
2860 then save the registers being used in this function */
2861 if (IFFUNC_CALLEESAVES(sym->type))
2865 /* if any registers used */
2868 /* save the registers used */
2869 for (i = 0; i < sym->regsUsed->size; i++)
2871 if (bitVectBitValue (sym->regsUsed, i) ||
2872 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2874 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2882 /* set the register bank to the desired value */
2883 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2886 emitcode ("push", "psw");
2887 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2890 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2891 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2892 if (options.stack10bit) {
2893 emitcode ("push","_bpx");
2894 emitcode ("push","_bpx+1");
2895 emitcode ("mov","_bpx,%s",spname);
2896 emitcode ("mov","_bpx+1,esp");
2897 emitcode ("anl","_bpx+1,#3");
2899 if (options.useXstack) {
2900 emitcode ("mov", "r0,%s", spname);
2901 emitcode ("mov", "a,_bp");
2902 emitcode ("movx", "@r0,a");
2903 emitcode ("inc", "%s", spname);
2905 /* set up the stack */
2906 emitcode ("push", "_bp"); /* save the callers stack */
2908 emitcode ("mov", "_bp,%s", spname);
2912 /* adjust the stack for the function */
2915 if (options.stack10bit) {
2916 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2917 assert (sym->recvSize <= 4);
2918 emitcode ("mov","a,sp");
2919 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2920 emitcode ("mov","sp,a");
2921 emitcode ("mov","a,esp");
2922 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2923 emitcode ("mov","esp,a");
2926 werror (W_STACK_OVERFLOW, sym->name);
2928 if (i > 3 && sym->recvSize < 4) {
2930 emitcode ("mov", "a,sp");
2931 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2932 emitcode ("mov", "sp,a");
2936 emitcode ("inc", "sp");
2943 emitcode ("mov", "a,_spx");
2944 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2945 emitcode ("mov", "_spx,a");
2950 /*-----------------------------------------------------------------*/
2951 /* genEndFunction - generates epilogue for functions */
2952 /*-----------------------------------------------------------------*/
2954 genEndFunction (iCode * ic)
2956 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2958 D (emitcode (";", "genEndFunction "););
2960 if (IFFUNC_ISNAKED(sym->type))
2962 emitcode(";", "naked function: no epilogue.");
2966 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2967 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2969 if (options.stack10bit) {
2970 emitcode ("mov", "sp,_bpx", spname);
2971 emitcode ("mov", "esp,_bpx+1", spname);
2973 emitcode ("mov", "%s,_bp", spname);
2977 /* if use external stack but some variables were
2978 added to the local stack then decrement the
2980 if (options.useXstack && sym->stack) {
2981 emitcode ("mov", "a,sp");
2982 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2983 emitcode ("mov", "sp,a");
2987 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2988 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2990 if (options.useXstack) {
2991 emitcode ("mov", "r0,%s", spname);
2992 emitcode ("movx", "a,@r0");
2993 emitcode ("mov", "_bp,a");
2994 emitcode ("dec", "%s", spname);
2996 if (options.stack10bit) {
2997 emitcode ("pop", "_bpx+1");
2998 emitcode ("pop", "_bpx");
3000 emitcode ("pop", "_bp");
3005 /* restore the register bank */
3006 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3008 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3009 || !options.useXstack)
3011 /* Special case of ISR using non-zero bank with useXstack
3014 emitcode ("pop", "psw");
3018 if (IFFUNC_ISISR (sym->type))
3021 /* now we need to restore the registers */
3022 /* if this isr has no bank i.e. is going to
3023 run with bank 0 , then we need to save more
3025 if (!FUNC_REGBANK (sym->type))
3027 /* if this function does not call any other
3028 function then we can be economical and
3029 save only those registers that are used */
3030 if (!IFFUNC_HASFCALL(sym->type))
3034 /* if any registers used */
3037 /* save the registers used */
3038 for (i = sym->regsUsed->size; i >= 0; i--)
3040 if (bitVectBitValue (sym->regsUsed, i) ||
3041 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3042 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3049 /* this function has a function call cannot
3050 determines register usage so we will have to pop the
3052 unsaveRBank (0, ic, FALSE);
3057 /* This ISR uses a non-zero bank.
3059 * Restore any register banks saved by genFunction
3062 // jwk: this needs a closer look
3063 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3066 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3068 if (savedBanks & (1 << ix))
3070 unsaveRBank(ix, NULL, FALSE);
3074 if (options.useXstack)
3076 /* Restore bank AFTER calling unsaveRBank,
3077 * since it can trash r0.
3079 emitcode ("pop", "psw");
3083 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3085 if (options.stack10bit)
3087 emitcode ("pop", DP2_RESULT_REG);
3088 emitcode ("pop", "dpx1");
3089 emitcode ("pop", "dph1");
3090 emitcode ("pop", "dpl1");
3092 emitcode ("pop", "dps");
3093 emitcode ("pop", "dpx");
3095 if (!inExcludeList ("dph"))
3096 emitcode ("pop", "dph");
3097 if (!inExcludeList ("dpl"))
3098 emitcode ("pop", "dpl");
3099 if (!inExcludeList ("b"))
3100 emitcode ("pop", "b");
3101 if (!inExcludeList ("acc"))
3102 emitcode ("pop", "acc");
3104 if (IFFUNC_ISCRITICAL (sym->type))
3105 emitcode ("setb", "ea");
3107 /* if debug then send end of function */
3108 if (options.debug && currFunc) {
3110 emitcode ("", "C$%s$%d$%d$%d ==.",
3111 FileBaseName (ic->filename), currFunc->lastLine,
3112 ic->level, ic->block);
3113 if (IS_STATIC (currFunc->etype))
3114 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3116 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3120 emitcode ("reti", "");
3124 if (IFFUNC_ISCRITICAL (sym->type))
3125 emitcode ("setb", "ea");
3127 if (IFFUNC_CALLEESAVES(sym->type))
3131 /* if any registers used */
3134 /* save the registers used */
3135 for (i = sym->regsUsed->size; i >= 0; i--)
3137 if (bitVectBitValue (sym->regsUsed, i) ||
3138 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3139 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3145 /* if debug then send end of function */
3146 if (options.debug && currFunc)
3149 emitcode ("", "C$%s$%d$%d$%d ==.",
3150 FileBaseName (ic->filename), currFunc->lastLine,
3151 ic->level, ic->block);
3152 if (IS_STATIC (currFunc->etype))
3153 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3155 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3159 emitcode ("ret", "");
3164 /*-----------------------------------------------------------------*/
3165 /* genJavaNativeRet - generate code for return JavaNative */
3166 /*-----------------------------------------------------------------*/
3167 static void genJavaNativeRet(iCode *ic)
3171 aopOp (IC_LEFT (ic), ic, FALSE,
3172 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3173 size = AOP_SIZE (IC_LEFT (ic));
3177 /* it is assigned to GPR0-R3 then push them */
3178 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3179 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3180 for (i = 0 ; i < size ; i++ ) {
3181 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3183 for (i = (size-1) ; i >= 0 ; i--) {
3184 emitcode ("pop","a%s",javaRet[i]);
3187 for (i = 0 ; i < size ; i++)
3188 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3190 for (i = size ; i < 4 ; i++ )
3191 emitcode ("mov","%s,#0",javaRet[i]);
3195 /*-----------------------------------------------------------------*/
3196 /* genRet - generate code for return statement */
3197 /*-----------------------------------------------------------------*/
3201 int size, offset = 0, pushed = 0;
3203 D (emitcode (";", "genRet ");
3206 /* if we have no return value then
3207 just generate the "ret" */
3211 /* if this is a JavaNative function then return
3212 value in different register */
3213 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3214 genJavaNativeRet(ic);
3217 /* we have something to return then
3218 move the return value into place */
3219 aopOp (IC_LEFT (ic), ic, FALSE,
3220 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3221 size = AOP_SIZE (IC_LEFT (ic));
3223 _startLazyDPSEvaluation ();
3227 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3229 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3230 FALSE, TRUE, FALSE);
3231 emitcode ("push", "%s", l);
3236 /* Since A is the last element of fReturn,
3237 * is is OK to clobber it in the aopGet.
3239 l = aopGet (AOP (IC_LEFT (ic)), offset,
3240 FALSE, FALSE, TRUE);
3241 if (strcmp (fReturn[offset], l))
3242 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3245 _endLazyDPSEvaluation ();
3252 if (strcmp (fReturn[pushed], "a"))
3253 emitcode ("pop", fReturn[pushed]);
3255 emitcode ("pop", "acc");
3258 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3261 /* generate a jump to the return label
3262 if the next is not the return statement */
3263 if (!(ic->next && ic->next->op == LABEL &&
3264 IC_LABEL (ic->next) == returnLabel))
3266 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3270 /*-----------------------------------------------------------------*/
3271 /* genLabel - generates a label */
3272 /*-----------------------------------------------------------------*/
3274 genLabel (iCode * ic)
3276 /* special case never generate */
3277 if (IC_LABEL (ic) == entryLabel)
3280 D (emitcode (";", "genLabel ");
3283 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3286 /*-----------------------------------------------------------------*/
3287 /* genGoto - generates a ljmp */
3288 /*-----------------------------------------------------------------*/
3290 genGoto (iCode * ic)
3292 D (emitcode (";", "genGoto ");
3294 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3297 /*-----------------------------------------------------------------*/
3298 /* findLabelBackwards: walks back through the iCode chain looking */
3299 /* for the given label. Returns number of iCode instructions */
3300 /* between that label and given ic. */
3301 /* Returns zero if label not found. */
3302 /*-----------------------------------------------------------------*/
3304 findLabelBackwards (iCode * ic, int key)
3313 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3315 /* printf("findLabelBackwards = %d\n", count); */
3323 /*-----------------------------------------------------------------*/
3324 /* genPlusIncr :- does addition with increment if possible */
3325 /*-----------------------------------------------------------------*/
3327 genPlusIncr (iCode * ic)
3329 unsigned int icount;
3330 unsigned int size = getDataSize (IC_RESULT (ic));
3332 /* will try to generate an increment */
3333 /* if the right side is not a literal
3335 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3338 /* if the literal value of the right hand side
3339 is greater than 4 then it is not worth it */
3340 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3343 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3344 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3346 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3350 /* if increment 16 bits in register */
3352 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3353 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3354 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3362 /* If the next instruction is a goto and the goto target
3363 * is <= 5 instructions previous to this, we can generate
3364 * jumps straight to that target.
3366 if (ic->next && ic->next->op == GOTO
3367 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3370 emitcode (";", "tail increment optimized (range %d)", labelRange);
3371 tlbl = IC_LABEL (ic->next);
3376 tlbl = newiTempLabel (NULL);
3379 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3380 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3381 IS_AOP_PREG (IC_RESULT (ic)))
3382 emitcode ("cjne", "%s,#0,!tlabel"
3383 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3387 emitcode ("clr", "a");
3388 emitcode ("cjne", "a,%s,!tlabel"
3389 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3393 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3396 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3397 IS_AOP_PREG (IC_RESULT (ic)))
3398 emitcode ("cjne", "%s,#0,!tlabel"
3399 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3402 emitcode ("cjne", "a,%s,!tlabel"
3403 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3406 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3410 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411 IS_AOP_PREG (IC_RESULT (ic)))
3412 emitcode ("cjne", "%s,#0,!tlabel"
3413 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3417 emitcode ("cjne", "a,%s,!tlabel"
3418 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3421 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3426 emitcode ("", "!tlabeldef", tlbl->key + 100);
3431 /* if the sizes are greater than 1 then we cannot */
3432 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3433 AOP_SIZE (IC_LEFT (ic)) > 1)
3436 /* we can if the aops of the left & result match or
3437 if they are in registers and the registers are the
3440 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3441 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3442 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3447 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3448 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3449 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3454 _startLazyDPSEvaluation ();
3457 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3459 _endLazyDPSEvaluation ();
3468 /*-----------------------------------------------------------------*/
3469 /* outBitAcc - output a bit in acc */
3470 /*-----------------------------------------------------------------*/
3472 outBitAcc (operand * result)
3474 symbol *tlbl = newiTempLabel (NULL);
3475 /* if the result is a bit */
3476 if (AOP_TYPE (result) == AOP_CRY)
3478 aopPut (AOP (result), "a", 0);
3482 emitcode ("jz", "!tlabel", tlbl->key + 100);
3483 emitcode ("mov", "a,%s", one);
3484 emitcode ("", "!tlabeldef", tlbl->key + 100);
3489 /*-----------------------------------------------------------------*/
3490 /* genPlusBits - generates code for addition of two bits */
3491 /*-----------------------------------------------------------------*/
3493 genPlusBits (iCode * ic)
3495 D (emitcode (";", "genPlusBits ");
3497 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3499 symbol *lbl = newiTempLabel (NULL);
3500 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3501 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3502 emitcode ("cpl", "c");
3503 emitcode ("", "!tlabeldef", (lbl->key + 100));
3504 outBitC (IC_RESULT (ic));
3508 emitcode ("clr", "a");
3509 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3510 emitcode ("rlc", "a");
3511 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3512 emitcode ("addc", "a,#0");
3513 outAcc (IC_RESULT (ic));
3518 adjustArithmeticResult (iCode * ic)
3520 if (opIsGptr (IC_RESULT (ic)) &&
3521 opIsGptr (IC_LEFT (ic)) &&
3522 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3524 aopPut (AOP (IC_RESULT (ic)),
3525 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3529 if (opIsGptr (IC_RESULT (ic)) &&
3530 opIsGptr (IC_RIGHT (ic)) &&
3531 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3533 aopPut (AOP (IC_RESULT (ic)),
3534 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3538 if (opIsGptr (IC_RESULT (ic)) &&
3539 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3540 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3541 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3542 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3545 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3546 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3550 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3551 // Please don't bring it back without a really good reason.
3552 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3553 // (because all three operands are in far space).
3554 #define AOP_OP_3(ic) \
3555 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3556 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3557 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3558 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3559 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3560 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3562 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3564 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3568 // Macro to aopOp all three operands of an ic. If this cannot be done,
3569 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3570 // will be set TRUE. The caller must then handle the case specially, noting
3571 // that the IC_RESULT operand is not aopOp'd.
3572 #define AOP_OP_3_NOFATAL(ic, rc) \
3573 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3574 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3575 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3576 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3577 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3579 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3584 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3585 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3587 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3588 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3590 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3592 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3596 // aopOp the left & right operands of an ic.
3597 #define AOP_OP_2(ic) \
3598 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3599 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3601 // convienience macro.
3602 #define AOP_SET_LOCALS(ic) \
3603 left = IC_LEFT(ic); \
3604 right = IC_RIGHT(ic); \
3605 result = IC_RESULT(ic);
3608 // Given an integer value of pushedSize bytes on the stack,
3609 // adjust it to be resultSize bytes, either by discarding
3610 // the most significant bytes or by zero-padding.
3612 // On exit from this macro, pushedSize will have been adjusted to
3613 // equal resultSize, and ACC may be trashed.
3614 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3615 /* If the pushed data is bigger than the result, \
3616 * simply discard unused bytes. Icky, but works. \
3618 while (pushedSize > resultSize) \
3620 D (emitcode (";", "discarding unused result byte."););\
3621 emitcode ("pop", "acc"); \
3624 if (pushedSize < resultSize) \
3626 emitcode ("clr", "a"); \
3627 /* Conversly, we haven't pushed enough here. \
3628 * just zero-pad, and all is well. \
3630 while (pushedSize < resultSize) \
3632 emitcode("push", "acc"); \
3636 assert(pushedSize == resultSize);
3638 /*-----------------------------------------------------------------*/
3639 /* genPlus - generates code for addition */
3640 /*-----------------------------------------------------------------*/
3642 genPlus (iCode * ic)
3644 int size, offset = 0;
3645 bool pushResult = FALSE;
3648 D (emitcode (";", "genPlus "););
3650 /* special cases :- */
3651 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3652 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3653 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3654 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3656 while (size--) emitcode ("inc","dptr");
3658 emitcode ("mov","a,dpl");
3659 emitcode ("add","a,#!constbyte",size & 0xff);
3660 emitcode ("mov","dpl,a");
3661 emitcode ("mov","a,dph");
3662 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3663 emitcode ("mov","dph,a");
3664 emitcode ("mov","a,dpx");
3665 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3666 emitcode ("mov","dpx,a");
3668 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3671 if ( IS_SYMOP(IC_LEFT(ic)) &&
3672 OP_SYMBOL(IC_LEFT(ic))->remat &&
3673 isOperandInFarSpace(IC_RIGHT(ic))) {
3674 operand *op = IC_RIGHT(ic);
3675 IC_RIGHT(ic) = IC_LEFT(ic);
3679 AOP_OP_3_NOFATAL (ic, pushResult);
3682 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3687 /* if literal, literal on the right or
3688 if left requires ACC or right is already
3690 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3691 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3692 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3694 operand *t = IC_RIGHT (ic);
3695 IC_RIGHT (ic) = IC_LEFT (ic);
3697 emitcode (";", "Swapped plus args.");
3700 /* if both left & right are in bit
3702 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3703 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3709 /* if left in bit space & right literal */
3710 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3711 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3713 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3714 /* if result in bit space */
3715 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3717 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3718 emitcode ("cpl", "c");
3719 outBitC (IC_RESULT (ic));
3723 size = getDataSize (IC_RESULT (ic));
3724 _startLazyDPSEvaluation ();
3727 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3728 emitcode ("addc", "a,#0");
3729 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3731 _endLazyDPSEvaluation ();
3736 /* if I can do an increment instead
3737 of add then GOOD for ME */
3738 if (genPlusIncr (ic) == TRUE)
3740 emitcode (";", "did genPlusIncr");
3745 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3747 _startLazyDPSEvaluation ();
3750 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3752 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3754 emitcode ("add", "a,%s",
3755 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3757 emitcode ("addc", "a,%s",
3758 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3762 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3764 /* right is going to use ACC or we would have taken the
3767 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3769 D(emitcode(";", "+ AOP_ACC special case."););
3770 emitcode("xch", "a, %s", DP2_RESULT_REG);
3772 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3775 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3778 emitcode("add", "a, %s", DP2_RESULT_REG);
3782 emitcode ("add", "a,%s",
3783 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3788 emitcode ("addc", "a,%s",
3789 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3794 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3798 emitcode ("push", "acc");
3802 _endLazyDPSEvaluation ();
3806 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3808 size = getDataSize (IC_LEFT (ic));
3809 rSize = getDataSize (IC_RESULT (ic));
3811 ADJUST_PUSHED_RESULT(size, rSize);
3813 _startLazyDPSEvaluation ();
3816 emitcode ("pop", "acc");
3817 aopPut (AOP (IC_RESULT (ic)), "a", size);
3819 _endLazyDPSEvaluation ();
3822 adjustArithmeticResult (ic);
3825 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3826 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3827 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3830 /*-----------------------------------------------------------------*/
3831 /* genMinusDec :- does subtraction with deccrement if possible */
3832 /*-----------------------------------------------------------------*/
3834 genMinusDec (iCode * ic)
3836 unsigned int icount;
3837 unsigned int size = getDataSize (IC_RESULT (ic));
3839 /* will try to generate an increment */
3840 /* if the right side is not a literal
3842 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3845 /* if the literal value of the right hand side
3846 is greater than 4 then it is not worth it */
3847 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3850 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3851 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3853 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3857 /* if decrement 16 bits in register */
3858 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3859 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3860 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3868 /* If the next instruction is a goto and the goto target
3869 * is <= 5 instructions previous to this, we can generate
3870 * jumps straight to that target.
3872 if (ic->next && ic->next->op == GOTO
3873 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3876 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3877 tlbl = IC_LABEL (ic->next);
3882 tlbl = newiTempLabel (NULL);
3886 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3887 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3888 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3889 IS_AOP_PREG (IC_RESULT (ic)))
3890 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3891 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3895 emitcode ("mov", "a,#!constbyte",0xff);
3896 emitcode ("cjne", "a,%s,!tlabel"
3897 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3900 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3903 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3904 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3905 IS_AOP_PREG (IC_RESULT (ic)))
3906 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3907 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3911 emitcode ("cjne", "a,%s,!tlabel"
3912 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3915 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3919 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3920 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3921 IS_AOP_PREG (IC_RESULT (ic)))
3922 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3923 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3927 emitcode ("cjne", "a,%s,!tlabel"
3928 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3931 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3935 emitcode ("", "!tlabeldef", tlbl->key + 100);
3940 /* if the sizes are greater than 1 then we cannot */
3941 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3942 AOP_SIZE (IC_LEFT (ic)) > 1)
3945 /* we can if the aops of the left & result match or
3946 if they are in registers and the registers are the
3949 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3950 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3951 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3954 _startLazyDPSEvaluation ();
3957 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3959 _endLazyDPSEvaluation ();
3967 /*-----------------------------------------------------------------*/
3968 /* addSign - complete with sign */
3969 /*-----------------------------------------------------------------*/
3971 addSign (operand * result, int offset, int sign)
3973 int size = (getDataSize (result) - offset);
3976 _startLazyDPSEvaluation();
3979 emitcode ("rlc", "a");
3980 emitcode ("subb", "a,acc");
3983 aopPut (AOP (result), "a", offset++);
3990 aopPut (AOP (result), zero, offset++);
3993 _endLazyDPSEvaluation();
3997 /*-----------------------------------------------------------------*/
3998 /* genMinusBits - generates code for subtraction of two bits */
3999 /*-----------------------------------------------------------------*/
4001 genMinusBits (iCode * ic)
4003 symbol *lbl = newiTempLabel (NULL);
4005 D (emitcode (";", "genMinusBits "););
4007 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4009 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4010 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4011 emitcode ("cpl", "c");
4012 emitcode ("", "!tlabeldef", (lbl->key + 100));
4013 outBitC (IC_RESULT (ic));
4017 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4018 emitcode ("subb", "a,acc");
4019 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4020 emitcode ("inc", "a");
4021 emitcode ("", "!tlabeldef", (lbl->key + 100));
4022 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4023 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4027 /*-----------------------------------------------------------------*/
4028 /* genMinus - generates code for subtraction */
4029 /*-----------------------------------------------------------------*/
4031 genMinus (iCode * ic)
4033 int size, offset = 0;
4035 unsigned long lit = 0L;
4036 bool pushResult = FALSE;
4038 D (emitcode (";", "genMinus "););
4040 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4041 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4042 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4043 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4049 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4051 /* special cases :- */
4052 /* if both left & right are in bit space */
4053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4054 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4060 /* if I can do an decrement instead
4061 of subtract then GOOD for ME */
4062 if (genMinusDec (ic) == TRUE)
4067 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4069 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4075 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4080 /* if literal, add a,#-lit, else normal subb */
4081 _startLazyDPSEvaluation ();
4084 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4085 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4086 emitcode ("subb", "a,%s",
4087 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4090 /* first add without previous c */
4092 if (!size && lit==-1) {
4093 emitcode ("dec", "a");
4095 emitcode ("add", "a,#!constbyte",
4096 (unsigned int) (lit & 0x0FFL));
4099 emitcode ("addc", "a,#!constbyte",
4100 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4106 emitcode ("push", "acc");
4110 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4114 _endLazyDPSEvaluation ();
4118 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4120 size = getDataSize (IC_LEFT (ic));
4121 rSize = getDataSize (IC_RESULT (ic));
4123 ADJUST_PUSHED_RESULT(size, rSize);
4125 _startLazyDPSEvaluation ();
4128 emitcode ("pop", "acc");
4129 aopPut (AOP (IC_RESULT (ic)), "a", size);
4131 _endLazyDPSEvaluation ();
4134 adjustArithmeticResult (ic);
4137 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4138 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4143 /*-----------------------------------------------------------------*/
4144 /* genMultbits :- multiplication of bits */
4145 /*-----------------------------------------------------------------*/
4147 genMultbits (operand * left,
4152 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4153 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4154 aopOp(result, ic, TRUE, FALSE);
4159 /*-----------------------------------------------------------------*/
4160 /* genMultOneByte : 8*8=8/16 bit multiplication */
4161 /*-----------------------------------------------------------------*/
4163 genMultOneByte (operand * left,
4168 sym_link *opetype = operandType (result);
4172 /* (if two literals: the value is computed before) */
4173 /* if one literal, literal on the right */
4174 if (AOP_TYPE (left) == AOP_LIT)
4179 emitcode (";", "swapped left and right");
4182 if (SPEC_USIGN(opetype)
4183 // ignore the sign of left and right, what else can we do?
4184 || (SPEC_USIGN(operandType(left)) &&
4185 SPEC_USIGN(operandType(right)))) {
4186 // just an unsigned 8*8=8/16 multiply
4187 //emitcode (";","unsigned");
4188 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4189 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4190 emitcode ("mul", "ab");
4192 _G.accInUse++; _G.bInUse++;
4193 aopOp(result, ic, TRUE, FALSE);
4195 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4197 // this should never happen
4198 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4199 AOP_SIZE(result), __FILE__, lineno);
4203 aopPut (AOP (result), "a", 0);
4204 _G.accInUse--; _G.bInUse--;
4205 if (AOP_SIZE(result)==2)
4207 aopPut (AOP (result), "b", 1);
4212 // we have to do a signed multiply
4214 emitcode (";", "signed");
4215 emitcode ("clr", "F0"); // reset sign flag
4216 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4218 lbl=newiTempLabel(NULL);
4219 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4220 // left side is negative, 8-bit two's complement, this fails for -128
4221 emitcode ("setb", "F0"); // set sign flag
4222 emitcode ("cpl", "a");
4223 emitcode ("inc", "a");
4225 emitcode ("", "!tlabeldef", lbl->key+100);
4228 if (AOP_TYPE(right)==AOP_LIT) {
4229 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4230 /* AND literal negative */
4231 if ((int) val < 0) {
4232 emitcode ("cpl", "F0"); // complement sign flag
4233 emitcode ("mov", "b,#!constbyte", -val);
4235 emitcode ("mov", "b,#!constbyte", val);
4238 lbl=newiTempLabel(NULL);
4239 emitcode ("mov", "b,a");
4240 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4241 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4242 // right side is negative, 8-bit two's complement
4243 emitcode ("cpl", "F0"); // complement sign flag
4244 emitcode ("cpl", "a");
4245 emitcode ("inc", "a");
4246 emitcode ("", "!tlabeldef", lbl->key+100);
4248 emitcode ("mul", "ab");
4250 _G.accInUse++;_G.bInUse++;
4251 aopOp(result, ic, TRUE, FALSE);
4253 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4255 // this should never happen
4256 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4257 AOP_SIZE(result), __FILE__, lineno);
4261 lbl=newiTempLabel(NULL);
4262 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4263 // only ONE op was negative, we have to do a 8/16-bit two's complement
4264 emitcode ("cpl", "a"); // lsb
4265 if (AOP_SIZE(result)==1) {
4266 emitcode ("inc", "a");
4268 emitcode ("add", "a,#1");
4269 emitcode ("xch", "a,b");
4270 emitcode ("cpl", "a"); // msb
4271 emitcode ("addc", "a,#0");
4272 emitcode ("xch", "a,b");
4275 emitcode ("", "!tlabeldef", lbl->key+100);
4276 aopPut (AOP (result), "a", 0);
4277 _G.accInUse--;_G.bInUse--;
4278 if (AOP_SIZE(result)==2) {
4279 aopPut (AOP (result), "b", 1);
4283 /*-----------------------------------------------------------------*/
4284 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4285 /*-----------------------------------------------------------------*/
4286 static void genMultTwoByte (operand *left, operand *right,
4287 operand *result, iCode *ic)
4289 sym_link *retype = getSpec(operandType(right));
4290 sym_link *letype = getSpec(operandType(left));
4291 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4294 if (AOP_TYPE (left) == AOP_LIT) {
4299 /* save EA bit in F1 */
4300 lbl = newiTempLabel(NULL);
4301 emitcode ("setb","F1");
4302 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4303 emitcode ("clr","F1");
4304 emitcode("","!tlabeldef",lbl->key+100);
4306 /* load up MB with right */
4308 emitcode("clr","F0");
4309 if (AOP_TYPE(right) == AOP_LIT) {
4310 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4312 emitcode("setb","F0");
4315 emitcode ("mov","mb,#!constbyte",val & 0xff);
4316 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4318 lbl = newiTempLabel(NULL);
4319 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4320 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4321 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4322 emitcode ("xch", "a,b");
4323 emitcode ("cpl","a");
4324 emitcode ("add", "a,#1");
4325 emitcode ("xch", "a,b");
4326 emitcode ("cpl", "a"); // msb
4327 emitcode ("addc", "a,#0");
4328 emitcode ("setb","F0");
4329 emitcode ("","!tlabeldef",lbl->key+100);
4330 emitcode ("mov","mb,b");
4331 emitcode ("mov","mb,a");
4334 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4335 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4337 /* load up MA with left */
4339 lbl = newiTempLabel(NULL);
4340 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4341 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4342 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4343 emitcode ("xch", "a,b");
4344 emitcode ("cpl","a");
4345 emitcode ("add", "a,#1");
4346 emitcode ("xch", "a,b");
4347 emitcode ("cpl", "a"); // msb
4348 emitcode ("addc","a,#0");
4349 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4350 emitcode ("setb","F0");
4351 emitcode ("","!tlabeldef",lbl->key+100);
4352 emitcode ("mov","ma,b");
4353 emitcode ("mov","ma,a");
4355 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4356 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4358 /* wait for multiplication to finish */
4359 lbl = newiTempLabel(NULL);
4360 emitcode("","!tlabeldef", lbl->key+100);
4361 emitcode("mov","a,mcnt1");
4362 emitcode("anl","a,#!constbyte",0x80);
4363 emitcode("jnz","!tlabel",lbl->key+100);
4365 freeAsmop (left, NULL, ic, TRUE);
4366 freeAsmop (right, NULL, ic,TRUE);
4367 aopOp(result, ic, TRUE, FALSE);
4369 /* if unsigned then simple */
4371 emitcode ("mov","a,ma");
4372 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4373 emitcode ("mov","a,ma");
4374 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4375 aopPut(AOP(result),"ma",1);
4376 aopPut(AOP(result),"ma",0);
4378 emitcode("push","ma");
4379 emitcode("push","ma");
4380 emitcode("push","ma");
4382 /* negate result if needed */
4383 lbl = newiTempLabel(NULL);
4384 emitcode("jnb","F0,!tlabel",lbl->key+100);
4385 emitcode("cpl","a");
4386 emitcode("add","a,#1");
4387 emitcode("","!tlabeldef", lbl->key+100);
4388 if (AOP_TYPE(result) == AOP_ACC)
4390 D(emitcode(";", "ACC special case."););
4391 /* We know result is the only live aop, and
4392 * it's obviously not a DPTR2, so AP is available.
4394 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4398 aopPut(AOP(result),"a",0);
4401 emitcode("pop","acc");
4402 lbl = newiTempLabel(NULL);
4403 emitcode("jnb","F0,!tlabel",lbl->key+100);
4404 emitcode("cpl","a");
4405 emitcode("addc","a,#0");
4406 emitcode("","!tlabeldef", lbl->key+100);
4407 aopPut(AOP(result),"a",1);
4408 emitcode("pop","acc");
4409 if (AOP_SIZE(result) >= 3) {
4410 lbl = newiTempLabel(NULL);
4411 emitcode("jnb","F0,!tlabel",lbl->key+100);
4412 emitcode("cpl","a");
4413 emitcode("addc","a,#0");
4414 emitcode("","!tlabeldef", lbl->key+100);
4415 aopPut(AOP(result),"a",2);
4417 emitcode("pop","acc");
4418 if (AOP_SIZE(result) >= 4) {
4419 lbl = newiTempLabel(NULL);
4420 emitcode("jnb","F0,!tlabel",lbl->key+100);
4421 emitcode("cpl","a");
4422 emitcode("addc","a,#0");
4423 emitcode("","!tlabeldef", lbl->key+100);
4424 aopPut(AOP(result),"a",3);
4426 if (AOP_TYPE(result) == AOP_ACC)
4428 /* We stashed the result away above. */
4429 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4433 freeAsmop (result, NULL, ic, TRUE);
4435 /* restore EA bit in F1 */
4436 lbl = newiTempLabel(NULL);
4437 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4438 emitcode ("setb","EA");
4439 emitcode("","!tlabeldef",lbl->key+100);
4443 /*-----------------------------------------------------------------*/
4444 /* genMult - generates code for multiplication */
4445 /*-----------------------------------------------------------------*/
4447 genMult (iCode * ic)
4449 operand *left = IC_LEFT (ic);
4450 operand *right = IC_RIGHT (ic);
4451 operand *result = IC_RESULT (ic);
4453 D (emitcode (";", "genMult "););
4455 /* assign the amsops */
4458 /* special cases first */
4460 if (AOP_TYPE (left) == AOP_CRY &&
4461 AOP_TYPE (right) == AOP_CRY)
4463 genMultbits (left, right, result, ic);
4467 /* if both are of size == 1 */
4468 if (AOP_SIZE (left) == 1 &&
4469 AOP_SIZE (right) == 1)
4471 genMultOneByte (left, right, result, ic);
4475 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4476 /* use the ds390 ARITHMETIC accel UNIT */
4477 genMultTwoByte (left, right, result, ic);
4480 /* should have been converted to function call */
4484 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4485 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4486 freeAsmop (result, NULL, ic, TRUE);
4489 /*-----------------------------------------------------------------*/
4490 /* genDivbits :- division of bits */
4491 /*-----------------------------------------------------------------*/
4493 genDivbits (operand * left,
4501 /* the result must be bit */
4502 LOAD_AB_FOR_DIV (left, right, l);
4503 emitcode ("div", "ab");
4504 emitcode ("rrc", "a");
4505 aopOp(result, ic, TRUE, FALSE);
4507 aopPut (AOP (result), "c", 0);
4510 /*-----------------------------------------------------------------*/
4511 /* genDivOneByte : 8 bit division */
4512 /*-----------------------------------------------------------------*/
4514 genDivOneByte (operand * left,
4519 sym_link *opetype = operandType (result);
4525 /* signed or unsigned */
4526 if (SPEC_USIGN (opetype))
4528 /* unsigned is easy */
4529 LOAD_AB_FOR_DIV (left, right, l);
4530 emitcode ("div", "ab");
4533 aopOp(result, ic, TRUE, FALSE);
4534 aopPut (AOP (result), "a", 0);
4537 size = AOP_SIZE (result) - 1;
4541 aopPut (AOP (result), zero, offset++);
4546 /* signed is a little bit more difficult */
4548 /* save the signs of the operands */
4549 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4551 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4552 emitcode ("push", "acc"); /* save it on the stack */
4554 /* now sign adjust for both left & right */
4555 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4557 lbl = newiTempLabel (NULL);
4558 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4559 emitcode ("cpl", "a");
4560 emitcode ("inc", "a");
4561 emitcode ("", "!tlabeldef", (lbl->key + 100));
4562 emitcode ("mov", "b,a");
4564 /* sign adjust left side */
4565 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4568 lbl = newiTempLabel (NULL);
4569 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4570 emitcode ("cpl", "a");
4571 emitcode ("inc", "a");
4572 emitcode ("", "!tlabeldef", (lbl->key + 100));
4574 /* now the division */
4575 emitcode ("nop", "; workaround for DS80C390 div bug.");
4576 emitcode ("div", "ab");
4577 /* we are interested in the lower order
4579 emitcode ("mov", "b,a");
4580 lbl = newiTempLabel (NULL);
4581 emitcode ("pop", "acc");
4582 /* if there was an over flow we don't
4583 adjust the sign of the result */
4584 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4585 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4587 emitcode ("clr", "a");
4588 emitcode ("subb", "a,b");
4589 emitcode ("mov", "b,a");
4590 emitcode ("", "!tlabeldef", (lbl->key + 100));
4592 /* now we are done */
4593 _G.accInUse++; _G.bInUse++;
4594 aopOp(result, ic, TRUE, FALSE);
4596 aopPut (AOP (result), "b", 0);
4598 size = AOP_SIZE (result) - 1;
4602 emitcode ("mov", "c,b.7");
4603 emitcode ("subb", "a,acc");
4607 aopPut (AOP (result), "a", offset++);
4609 _G.accInUse--; _G.bInUse--;
4613 /*-----------------------------------------------------------------*/
4614 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4615 /*-----------------------------------------------------------------*/
4616 static void genDivTwoByte (operand *left, operand *right,
4617 operand *result, iCode *ic)
4619 sym_link *retype = getSpec(operandType(right));
4620 sym_link *letype = getSpec(operandType(left));
4621 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4624 /* save EA bit in F1 */
4625 lbl = newiTempLabel(NULL);
4626 emitcode ("setb","F1");
4627 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4628 emitcode ("clr","F1");
4629 emitcode("","!tlabeldef",lbl->key+100);
4631 /* load up MA with left */
4633 emitcode("clr","F0");
4634 lbl = newiTempLabel(NULL);
4635 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4636 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4637 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4638 emitcode ("xch", "a,b");
4639 emitcode ("cpl","a");
4640 emitcode ("add", "a,#1");
4641 emitcode ("xch", "a,b");
4642 emitcode ("cpl", "a"); // msb
4643 emitcode ("addc","a,#0");
4644 emitcode ("setb","F0");
4645 emitcode ("","!tlabeldef",lbl->key+100);
4646 emitcode ("mov","ma,b");
4647 emitcode ("mov","ma,a");
4649 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4650 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4653 /* load up MB with right */
4655 if (AOP_TYPE(right) == AOP_LIT) {
4656 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4658 lbl = newiTempLabel(NULL);
4659 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4660 emitcode("setb","F0");
4661 emitcode ("","!tlabeldef",lbl->key+100);
4664 emitcode ("mov","mb,#!constbyte",val & 0xff);
4665 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4667 lbl = newiTempLabel(NULL);
4668 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4669 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4670 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4671 emitcode ("xch", "a,b");
4672 emitcode ("cpl","a");
4673 emitcode ("add", "a,#1");
4674 emitcode ("xch", "a,b");
4675 emitcode ("cpl", "a"); // msb
4676 emitcode ("addc", "a,#0");
4677 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4678 emitcode ("setb","F0");
4679 emitcode ("","!tlabeldef",lbl->key+100);
4680 emitcode ("mov","mb,b");
4681 emitcode ("mov","mb,a");
4684 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4685 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4688 /* wait for multiplication to finish */
4689 lbl = newiTempLabel(NULL);
4690 emitcode("","!tlabeldef", lbl->key+100);
4691 emitcode("mov","a,mcnt1");
4692 emitcode("anl","a,#!constbyte",0x80);
4693 emitcode("jnz","!tlabel",lbl->key+100);
4695 freeAsmop (left, NULL, ic, TRUE);
4696 freeAsmop (right, NULL, ic,TRUE);
4697 aopOp(result, ic, TRUE, FALSE);
4699 /* if unsigned then simple */
4701 aopPut(AOP(result),"ma",1);
4702 aopPut(AOP(result),"ma",0);
4704 emitcode("push","ma");
4706 /* negate result if needed */
4707 lbl = newiTempLabel(NULL);
4708 emitcode("jnb","F0,!tlabel",lbl->key+100);
4709 emitcode("cpl","a");
4710 emitcode("add","a,#1");
4711 emitcode("","!tlabeldef", lbl->key+100);
4712 aopPut(AOP(result),"a",0);
4713 emitcode("pop","acc");
4714 lbl = newiTempLabel(NULL);
4715 emitcode("jnb","F0,!tlabel",lbl->key+100);
4716 emitcode("cpl","a");
4717 emitcode("addc","a,#0");
4718 emitcode("","!tlabeldef", lbl->key+100);
4719 aopPut(AOP(result),"a",1);
4721 freeAsmop (result, NULL, ic, TRUE);
4722 /* restore EA bit in F1 */
4723 lbl = newiTempLabel(NULL);
4724 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4725 emitcode ("setb","EA");
4726 emitcode("","!tlabeldef",lbl->key+100);
4730 /*-----------------------------------------------------------------*/
4731 /* genDiv - generates code for division */
4732 /*-----------------------------------------------------------------*/
4736 operand *left = IC_LEFT (ic);
4737 operand *right = IC_RIGHT (ic);
4738 operand *result = IC_RESULT (ic);
4740 D (emitcode (";", "genDiv "););
4742 /* assign the amsops */
4745 /* special cases first */
4747 if (AOP_TYPE (left) == AOP_CRY &&
4748 AOP_TYPE (right) == AOP_CRY)
4750 genDivbits (left, right, result, ic);
4754 /* if both are of size == 1 */
4755 if (AOP_SIZE (left) == 1 &&
4756 AOP_SIZE (right) == 1)
4758 genDivOneByte (left, right, result, ic);
4762 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4763 /* use the ds390 ARITHMETIC accel UNIT */
4764 genDivTwoByte (left, right, result, ic);
4767 /* should have been converted to function call */
4770 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772 freeAsmop (result, NULL, ic, TRUE);
4775 /*-----------------------------------------------------------------*/
4776 /* genModbits :- modulus of bits */
4777 /*-----------------------------------------------------------------*/
4779 genModbits (operand * left,
4787 /* the result must be bit */
4788 LOAD_AB_FOR_DIV (left, right, l);
4789 emitcode ("div", "ab");
4790 emitcode ("mov", "a,b");
4791 emitcode ("rrc", "a");
4792 aopOp(result, ic, TRUE, FALSE);
4793 aopPut (AOP (result), "c", 0);
4796 /*-----------------------------------------------------------------*/
4797 /* genModOneByte : 8 bit modulus */
4798 /*-----------------------------------------------------------------*/
4800 genModOneByte (operand * left,
4805 sym_link *opetype = operandType (result);
4809 /* signed or unsigned */
4810 if (SPEC_USIGN (opetype))
4812 /* unsigned is easy */
4813 LOAD_AB_FOR_DIV (left, right, l);
4814 emitcode ("div", "ab");
4815 aopOp(result, ic, TRUE, FALSE);
4816 aopPut (AOP (result), "b", 0);
4820 /* signed is a little bit more difficult */
4822 /* save the signs of the operands */
4823 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4826 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4827 emitcode ("push", "acc"); /* save it on the stack */
4829 /* now sign adjust for both left & right */
4830 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4833 lbl = newiTempLabel (NULL);
4834 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4835 emitcode ("cpl", "a");
4836 emitcode ("inc", "a");
4837 emitcode ("", "!tlabeldef", (lbl->key + 100));
4838 emitcode ("mov", "b,a");
4840 /* sign adjust left side */
4841 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4844 lbl = newiTempLabel (NULL);
4845 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4846 emitcode ("cpl", "a");
4847 emitcode ("inc", "a");
4848 emitcode ("", "!tlabeldef", (lbl->key + 100));
4850 /* now the multiplication */
4851 emitcode ("nop", "; workaround for DS80C390 div bug.");
4852 emitcode ("div", "ab");
4853 /* we are interested in the lower order
4855 lbl = newiTempLabel (NULL);
4856 emitcode ("pop", "acc");
4857 /* if there was an over flow we don't
4858 adjust the sign of the result */
4859 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4860 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4862 emitcode ("clr", "a");
4863 emitcode ("subb", "a,b");
4864 emitcode ("mov", "b,a");
4865 emitcode ("", "!tlabeldef", (lbl->key + 100));
4868 /* now we are done */
4869 aopOp(result, ic, TRUE, FALSE);
4870 aopPut (AOP (result), "b", 0);
4875 /*-----------------------------------------------------------------*/
4876 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4877 /*-----------------------------------------------------------------*/
4878 static void genModTwoByte (operand *left, operand *right,
4879 operand *result, iCode *ic)
4881 sym_link *retype = getSpec(operandType(right));
4882 sym_link *letype = getSpec(operandType(left));
4883 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4886 /* load up MA with left */
4887 /* save EA bit in F1 */
4888 lbl = newiTempLabel(NULL);
4889 emitcode ("setb","F1");
4890 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4891 emitcode ("clr","F1");
4892 emitcode("","!tlabeldef",lbl->key+100);
4895 lbl = newiTempLabel(NULL);
4896 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4897 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4898 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4899 emitcode ("xch", "a,b");
4900 emitcode ("cpl","a");
4901 emitcode ("add", "a,#1");
4902 emitcode ("xch", "a,b");
4903 emitcode ("cpl", "a"); // msb
4904 emitcode ("addc","a,#0");
4905 emitcode ("","!tlabeldef",lbl->key+100);
4906 emitcode ("mov","ma,b");
4907 emitcode ("mov","ma,a");
4909 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4910 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4913 /* load up MB with right */
4915 if (AOP_TYPE(right) == AOP_LIT) {
4916 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4920 emitcode ("mov","mb,#!constbyte",val & 0xff);
4921 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4923 lbl = newiTempLabel(NULL);
4924 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4925 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4926 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4927 emitcode ("xch", "a,b");
4928 emitcode ("cpl","a");
4929 emitcode ("add", "a,#1");
4930 emitcode ("xch", "a,b");
4931 emitcode ("cpl", "a"); // msb
4932 emitcode ("addc", "a,#0");
4933 emitcode ("","!tlabeldef",lbl->key+100);
4934 emitcode ("mov","mb,b");
4935 emitcode ("mov","mb,a");
4938 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4939 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4942 /* wait for multiplication to finish */
4943 lbl = newiTempLabel(NULL);
4944 emitcode("","!tlabeldef", lbl->key+100);
4945 emitcode("mov","a,mcnt1");
4946 emitcode("anl","a,#!constbyte",0x80);
4947 emitcode("jnz","!tlabel",lbl->key+100);
4949 freeAsmop (left, NULL, ic, TRUE);
4950 freeAsmop (right, NULL, ic,TRUE);
4951 aopOp(result, ic, TRUE, FALSE);
4953 aopPut(AOP(result),"mb",1);
4954 aopPut(AOP(result),"mb",0);
4955 freeAsmop (result, NULL, ic, TRUE);
4957 /* restore EA bit in F1 */
4958 lbl = newiTempLabel(NULL);
4959 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4960 emitcode ("setb","EA");
4961 emitcode("","!tlabeldef",lbl->key+100);
4965 /*-----------------------------------------------------------------*/
4966 /* genMod - generates code for division */
4967 /*-----------------------------------------------------------------*/
4971 operand *left = IC_LEFT (ic);
4972 operand *right = IC_RIGHT (ic);
4973 operand *result = IC_RESULT (ic);
4975 D (emitcode (";", "genMod "); );
4977 /* assign the amsops */
4980 /* special cases first */
4982 if (AOP_TYPE (left) == AOP_CRY &&
4983 AOP_TYPE (right) == AOP_CRY)
4985 genModbits (left, right, result, ic);
4989 /* if both are of size == 1 */
4990 if (AOP_SIZE (left) == 1 &&
4991 AOP_SIZE (right) == 1)
4993 genModOneByte (left, right, result, ic);
4997 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4998 /* use the ds390 ARITHMETIC accel UNIT */
4999 genModTwoByte (left, right, result, ic);
5003 /* should have been converted to function call */
5007 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5009 freeAsmop (result, NULL, ic, TRUE);
5012 /*-----------------------------------------------------------------*/
5013 /* genIfxJump :- will create a jump depending on the ifx */
5014 /*-----------------------------------------------------------------*/
5016 genIfxJump (iCode * ic, char *jval)
5019 symbol *tlbl = newiTempLabel (NULL);
5022 D (emitcode (";", "genIfxJump ");
5025 /* if true label then we jump if condition
5029 jlbl = IC_TRUE (ic);
5030 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5031 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5035 /* false label is present */
5036 jlbl = IC_FALSE (ic);
5037 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5038 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5040 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5041 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5043 emitcode (inst, "!tlabel", tlbl->key + 100);
5044 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5045 emitcode ("", "!tlabeldef", tlbl->key + 100);
5047 /* mark the icode as generated */
5051 /*-----------------------------------------------------------------*/
5052 /* genCmp :- greater or less than comparison */
5053 /*-----------------------------------------------------------------*/
5055 genCmp (operand * left, operand * right,
5056 iCode * ic, iCode * ifx, int sign)
5058 int size, offset = 0;
5059 unsigned long lit = 0L;
5062 D (emitcode (";", "genCmp");
5065 result = IC_RESULT (ic);
5067 /* if left & right are bit variables */
5068 if (AOP_TYPE (left) == AOP_CRY &&
5069 AOP_TYPE (right) == AOP_CRY)
5071 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5072 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5076 /* subtract right from left if at the
5077 end the carry flag is set then we know that
5078 left is greater than right */
5079 size = max (AOP_SIZE (left), AOP_SIZE (right));
5081 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5082 if ((size == 1) && !sign &&
5083 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5085 symbol *lbl = newiTempLabel (NULL);
5086 emitcode ("cjne", "%s,%s,!tlabel",
5087 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5088 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5090 emitcode ("", "!tlabeldef", lbl->key + 100);
5094 if (AOP_TYPE (right) == AOP_LIT)
5096 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5097 /* optimize if(x < 0) or if(x >= 0) */
5106 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5108 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5109 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5111 aopOp (result, ic, FALSE, FALSE);
5113 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5115 freeAsmop (result, NULL, ic, TRUE);
5116 genIfxJump (ifx, "acc.7");
5121 emitcode ("rlc", "a");
5123 goto release_freedLR;
5131 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5132 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5133 //emitcode (";", "genCmp #2");
5134 if (sign && (size == 0))
5136 //emitcode (";", "genCmp #3");
5137 emitcode ("xrl", "a,#!constbyte",0x80);
5138 if (AOP_TYPE (right) == AOP_LIT)
5140 unsigned long lit = (unsigned long)
5141 floatFromVal (AOP (right)->aopu.aop_lit);
5142 //emitcode (";", "genCmp #3.1");
5143 emitcode ("subb", "a,#!constbyte",
5144 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5148 //emitcode (";", "genCmp #3.2");
5149 if (AOP_NEEDSACC (right))
5151 emitcode ("push", "acc");
5153 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5154 FALSE, FALSE, FALSE));
5155 emitcode ("xrl", "b,#!constbyte",0x80);
5156 if (AOP_NEEDSACC (right))
5158 emitcode ("pop", "acc");
5160 emitcode ("subb", "a,b");
5167 //emitcode (";", "genCmp #4");
5168 if (AOP_NEEDSACC (right))
5171 //emitcode (";", "genCmp #4.1");
5172 emitcode ("xch", "a, b");
5173 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5174 emitcode ("xch", "a, b");
5179 //emitcode (";", "genCmp #4.2");
5180 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5183 emitcode ("subb", "a,%s", s);
5190 /* Don't need the left & right operands any more; do need the result. */
5191 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5192 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5194 aopOp (result, ic, FALSE, FALSE);
5198 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5204 /* if the result is used in the next
5205 ifx conditional branch then generate
5206 code a little differently */
5209 genIfxJump (ifx, "c");
5215 /* leave the result in acc */
5217 freeAsmop (result, NULL, ic, TRUE);
5220 /*-----------------------------------------------------------------*/
5221 /* genCmpGt :- greater than comparison */
5222 /*-----------------------------------------------------------------*/
5224 genCmpGt (iCode * ic, iCode * ifx)
5226 operand *left, *right;
5227 sym_link *letype, *retype;
5230 D (emitcode (";", "genCmpGt ");
5233 left = IC_LEFT (ic);
5234 right = IC_RIGHT (ic);
5236 letype = getSpec (operandType (left));
5237 retype = getSpec (operandType (right));
5238 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5240 /* assign the left & right amsops */
5243 genCmp (right, left, ic, ifx, sign);
5246 /*-----------------------------------------------------------------*/
5247 /* genCmpLt - less than comparisons */
5248 /*-----------------------------------------------------------------*/
5250 genCmpLt (iCode * ic, iCode * ifx)
5252 operand *left, *right;
5253 sym_link *letype, *retype;
5256 D (emitcode (";", "genCmpLt "););
5258 left = IC_LEFT (ic);
5259 right = IC_RIGHT (ic);
5261 letype = getSpec (operandType (left));
5262 retype = getSpec (operandType (right));
5263 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5265 /* assign the left & right amsops */
5268 genCmp (left, right, ic, ifx, sign);
5271 /*-----------------------------------------------------------------*/
5272 /* gencjneshort - compare and jump if not equal */
5273 /*-----------------------------------------------------------------*/
5275 gencjneshort (operand * left, operand * right, symbol * lbl)
5277 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5279 unsigned long lit = 0L;
5281 D (emitcode (";", "gencjneshort");
5284 /* if the left side is a literal or
5285 if the right is in a pointer register and left
5287 if ((AOP_TYPE (left) == AOP_LIT) ||
5288 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5295 if (AOP_TYPE (right) == AOP_LIT)
5296 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5298 if (opIsGptr (left) || opIsGptr (right))
5300 /* We are comparing a generic pointer to something.
5301 * Exclude the generic type byte from the comparison.
5304 D (emitcode (";", "cjneshort: generic ptr special case.");
5309 /* if the right side is a literal then anything goes */
5310 if (AOP_TYPE (right) == AOP_LIT &&
5311 AOP_TYPE (left) != AOP_DIR)
5315 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5317 emitcode ("cjne", "a,%s,!tlabel",
5318 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5324 /* if the right side is in a register or in direct space or
5325 if the left is a pointer register & right is not */
5326 else if (AOP_TYPE (right) == AOP_REG ||
5327 AOP_TYPE (right) == AOP_DIR ||
5328 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5329 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5333 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5334 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5335 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5336 emitcode ("jnz", "!tlabel", lbl->key + 100);
5338 emitcode ("cjne", "a,%s,!tlabel",
5339 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5346 /* right is a pointer reg need both a & b */
5349 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5350 if (strcmp (l, "b"))
5351 emitcode ("mov", "b,%s", l);
5352 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5353 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5359 /*-----------------------------------------------------------------*/
5360 /* gencjne - compare and jump if not equal */
5361 /*-----------------------------------------------------------------*/
5363 gencjne (operand * left, operand * right, symbol * lbl)
5365 symbol *tlbl = newiTempLabel (NULL);
5367 D (emitcode (";", "gencjne");
5370 gencjneshort (left, right, lbl);
5372 emitcode ("mov", "a,%s", one);
5373 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5374 emitcode ("", "!tlabeldef", lbl->key + 100);
5375 emitcode ("clr", "a");
5376 emitcode ("", "!tlabeldef", tlbl->key + 100);
5379 /*-----------------------------------------------------------------*/
5380 /* genCmpEq - generates code for equal to */
5381 /*-----------------------------------------------------------------*/
5383 genCmpEq (iCode * ic, iCode * ifx)
5385 operand *left, *right, *result;
5387 D (emitcode (";", "genCmpEq ");
5391 AOP_SET_LOCALS (ic);
5393 /* if literal, literal on the right or
5394 if the right is in a pointer register and left
5396 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5397 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5399 operand *t = IC_RIGHT (ic);
5400 IC_RIGHT (ic) = IC_LEFT (ic);
5404 if (ifx && /* !AOP_SIZE(result) */
5405 OP_SYMBOL (result) &&
5406 OP_SYMBOL (result)->regType == REG_CND)
5409 /* if they are both bit variables */
5410 if (AOP_TYPE (left) == AOP_CRY &&
5411 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5413 if (AOP_TYPE (right) == AOP_LIT)
5415 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5418 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5419 emitcode ("cpl", "c");
5423 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5427 emitcode ("clr", "c");
5429 /* AOP_TYPE(right) == AOP_CRY */
5433 symbol *lbl = newiTempLabel (NULL);
5434 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5435 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5436 emitcode ("cpl", "c");
5437 emitcode ("", "!tlabeldef", (lbl->key + 100));
5439 /* if true label then we jump if condition
5441 tlbl = newiTempLabel (NULL);
5444 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5445 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5449 emitcode ("jc", "!tlabel", tlbl->key + 100);
5450 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5452 emitcode ("", "!tlabeldef", tlbl->key + 100);
5456 tlbl = newiTempLabel (NULL);
5457 gencjneshort (left, right, tlbl);
5460 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5461 emitcode ("", "!tlabeldef", tlbl->key + 100);
5465 symbol *lbl = newiTempLabel (NULL);
5466 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5467 emitcode ("", "!tlabeldef", tlbl->key + 100);
5468 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5469 emitcode ("", "!tlabeldef", lbl->key + 100);
5472 /* mark the icode as generated */
5475 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5480 /* if they are both bit variables */
5481 if (AOP_TYPE (left) == AOP_CRY &&
5482 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5484 if (AOP_TYPE (right) == AOP_LIT)
5486 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5489 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5490 emitcode ("cpl", "c");
5494 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5498 emitcode ("clr", "c");
5500 /* AOP_TYPE(right) == AOP_CRY */
5504 symbol *lbl = newiTempLabel (NULL);
5505 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5506 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5507 emitcode ("cpl", "c");
5508 emitcode ("", "!tlabeldef", (lbl->key + 100));
5511 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5512 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5514 aopOp (result, ic, TRUE, FALSE);
5517 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5524 genIfxJump (ifx, "c");
5527 /* if the result is used in an arithmetic operation
5528 then put the result in place */
5533 gencjne (left, right, newiTempLabel (NULL));
5535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5536 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5538 aopOp (result, ic, TRUE, FALSE);
5540 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5542 aopPut (AOP (result), "a", 0);
5547 genIfxJump (ifx, "a");
5550 /* if the result is used in an arithmetic operation
5551 then put the result in place */
5552 if (AOP_TYPE (result) != AOP_CRY)
5554 /* leave the result in acc */
5558 freeAsmop (result, NULL, ic, TRUE);
5561 /*-----------------------------------------------------------------*/
5562 /* ifxForOp - returns the icode containing the ifx for operand */
5563 /*-----------------------------------------------------------------*/
5565 ifxForOp (operand * op, iCode * ic)
5567 /* if true symbol then needs to be assigned */
5568 if (IS_TRUE_SYMOP (op))
5571 /* if this has register type condition and
5572 the next instruction is ifx with the same operand
5573 and live to of the operand is upto the ifx only then */
5575 ic->next->op == IFX &&
5576 IC_COND (ic->next)->key == op->key &&
5577 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5582 /*-----------------------------------------------------------------*/
5583 /* hasInc - operand is incremented before any other use */
5584 /*-----------------------------------------------------------------*/
5586 hasInc (operand *op, iCode *ic, int osize)
5588 sym_link *type = operandType(op);
5589 sym_link *retype = getSpec (type);
5590 iCode *lic = ic->next;
5593 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5594 if (!IS_SYMOP(op)) return NULL;
5596 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5597 if (IS_AGGREGATE(type->next)) return NULL;
5598 if (osize != (isize = getSize(type->next))) return NULL;
5601 /* if operand of the form op = op + <sizeof *op> */
5602 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5603 isOperandEqual(IC_RESULT(lic),op) &&
5604 isOperandLiteral(IC_RIGHT(lic)) &&
5605 operandLitValue(IC_RIGHT(lic)) == isize) {
5608 /* if the operand used or deffed */
5609 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5612 /* if GOTO or IFX */
5613 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5619 /*-----------------------------------------------------------------*/
5620 /* genAndOp - for && operation */
5621 /*-----------------------------------------------------------------*/
5623 genAndOp (iCode * ic)
5625 operand *left, *right, *result;
5628 D (emitcode (";", "genAndOp "););
5630 /* note here that && operations that are in an
5631 if statement are taken away by backPatchLabels
5632 only those used in arthmetic operations remain */
5634 AOP_SET_LOCALS (ic);
5636 /* if both are bit variables */
5637 if (AOP_TYPE (left) == AOP_CRY &&
5638 AOP_TYPE (right) == AOP_CRY)
5640 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5641 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5642 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5643 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5645 aopOp (result,ic,FALSE, FALSE);
5650 tlbl = newiTempLabel (NULL);
5652 emitcode ("jz", "!tlabel", tlbl->key + 100);
5654 emitcode ("", "!tlabeldef", tlbl->key + 100);
5655 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5656 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5658 aopOp (result,ic,FALSE, FALSE);
5661 freeAsmop (result, NULL, ic, TRUE);
5665 /*-----------------------------------------------------------------*/
5666 /* genOrOp - for || operation */
5667 /*-----------------------------------------------------------------*/
5669 genOrOp (iCode * ic)
5671 operand *left, *right, *result;
5674 D (emitcode (";", "genOrOp "););
5676 /* note here that || operations that are in an
5677 if statement are taken away by backPatchLabels
5678 only those used in arthmetic operations remain */
5680 AOP_SET_LOCALS (ic);
5682 /* if both are bit variables */
5683 if (AOP_TYPE (left) == AOP_CRY &&
5684 AOP_TYPE (right) == AOP_CRY)
5686 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5687 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5688 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5691 aopOp (result,ic,FALSE, FALSE);
5697 tlbl = newiTempLabel (NULL);
5699 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5701 emitcode ("", "!tlabeldef", tlbl->key + 100);
5702 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5703 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5705 aopOp (result,ic,FALSE, FALSE);
5710 freeAsmop (result, NULL, ic, TRUE);
5713 /*-----------------------------------------------------------------*/
5714 /* isLiteralBit - test if lit == 2^n */
5715 /*-----------------------------------------------------------------*/
5717 isLiteralBit (unsigned long lit)
5719 unsigned long pw[32] =
5720 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5721 0x100L, 0x200L, 0x400L, 0x800L,
5722 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5723 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5724 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5725 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5726 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5729 for (idx = 0; idx < 32; idx++)
5735 /*-----------------------------------------------------------------*/
5736 /* continueIfTrue - */
5737 /*-----------------------------------------------------------------*/
5739 continueIfTrue (iCode * ic)
5742 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5746 /*-----------------------------------------------------------------*/
5748 /*-----------------------------------------------------------------*/
5750 jumpIfTrue (iCode * ic)
5753 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5757 /*-----------------------------------------------------------------*/
5758 /* jmpTrueOrFalse - */
5759 /*-----------------------------------------------------------------*/
5761 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5763 // ugly but optimized by peephole
5766 symbol *nlbl = newiTempLabel (NULL);
5767 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5768 emitcode ("", "!tlabeldef", tlbl->key + 100);
5769 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5770 emitcode ("", "!tlabeldef", nlbl->key + 100);
5774 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5775 emitcode ("", "!tlabeldef", tlbl->key + 100);
5780 // Generate code to perform a bit-wise logic operation
5781 // on two operands in far space (assumed to already have been
5782 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5783 // in far space. This requires pushing the result on the stack
5784 // then popping it into the result.
5786 genFarFarLogicOp(iCode *ic, char *logicOp)
5788 int size, resultSize, compSize;
5792 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5793 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5794 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5796 _startLazyDPSEvaluation();
5797 for (size = compSize; (size--); offset++)
5799 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5800 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5801 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5803 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5804 emitcode ("push", "acc");
5806 _endLazyDPSEvaluation();
5808 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5809 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5810 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5812 resultSize = AOP_SIZE(IC_RESULT(ic));
5814 ADJUST_PUSHED_RESULT(compSize, resultSize);
5816 _startLazyDPSEvaluation();
5819 emitcode ("pop", "acc");
5820 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5822 _endLazyDPSEvaluation();
5823 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5827 /*-----------------------------------------------------------------*/
5828 /* genAnd - code for and */
5829 /*-----------------------------------------------------------------*/
5831 genAnd (iCode * ic, iCode * ifx)
5833 operand *left, *right, *result;
5834 int size, offset = 0;
5835 unsigned long lit = 0L;
5840 D (emitcode (";", "genAnd "););
5842 AOP_OP_3_NOFATAL (ic, pushResult);
5843 AOP_SET_LOCALS (ic);
5847 genFarFarLogicOp(ic, "anl");
5852 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5854 AOP_TYPE (left), AOP_TYPE (right));
5855 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5857 AOP_SIZE (left), AOP_SIZE (right));
5860 /* if left is a literal & right is not then exchange them */
5861 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5862 #ifdef LOGIC_OPS_BROKEN
5863 || AOP_NEEDSACC (left)
5867 operand *tmp = right;
5872 /* if result = right then exchange them */
5873 if (sameRegs (AOP (result), AOP (right)))
5875 operand *tmp = right;
5880 /* if right is bit then exchange them */
5881 if (AOP_TYPE (right) == AOP_CRY &&
5882 AOP_TYPE (left) != AOP_CRY)
5884 operand *tmp = right;
5888 if (AOP_TYPE (right) == AOP_LIT)
5889 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5891 size = AOP_SIZE (result);
5894 // result = bit & yy;
5895 if (AOP_TYPE (left) == AOP_CRY)
5897 // c = bit & literal;
5898 if (AOP_TYPE (right) == AOP_LIT)
5902 if (size && sameRegs (AOP (result), AOP (left)))
5905 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5910 if (size && (AOP_TYPE (result) == AOP_CRY))
5912 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5915 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5920 emitcode ("clr", "c");
5925 if (AOP_TYPE (right) == AOP_CRY)
5928 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5929 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5934 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5936 emitcode ("rrc", "a");
5937 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5945 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5946 genIfxJump (ifx, "c");
5950 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5951 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5952 if ((AOP_TYPE (right) == AOP_LIT) &&
5953 (AOP_TYPE (result) == AOP_CRY) &&
5954 (AOP_TYPE (left) != AOP_CRY))
5956 int posbit = isLiteralBit (lit);
5961 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5964 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5970 sprintf (buffer, "acc.%d", posbit & 0x07);
5971 genIfxJump (ifx, buffer);
5978 symbol *tlbl = newiTempLabel (NULL);
5979 int sizel = AOP_SIZE (left);
5981 emitcode ("setb", "c");
5984 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5986 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5988 if ((posbit = isLiteralBit (bytelit)) != 0)
5989 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5992 if (bytelit != 0x0FFL)
5993 emitcode ("anl", "a,%s",
5994 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5995 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6000 // bit = left & literal
6003 emitcode ("clr", "c");
6004 emitcode ("", "!tlabeldef", tlbl->key + 100);
6006 // if(left & literal)
6010 jmpTrueOrFalse (ifx, tlbl);
6018 /* if left is same as result */
6019 if (sameRegs (AOP (result), AOP (left)))
6021 for (; size--; offset++)
6023 if (AOP_TYPE (right) == AOP_LIT)
6025 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6027 else if (bytelit == 0)
6028 aopPut (AOP (result), zero, offset);
6029 else if (IS_AOP_PREG (result))
6031 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6032 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6033 aopPut (AOP (result), "a", offset);
6036 emitcode ("anl", "%s,%s",
6037 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6038 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6042 if (AOP_TYPE (left) == AOP_ACC)
6043 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6046 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6047 if (IS_AOP_PREG (result))
6049 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6050 aopPut (AOP (result), "a", offset);
6054 emitcode ("anl", "%s,a",
6055 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6062 // left & result in different registers
6063 if (AOP_TYPE (result) == AOP_CRY)
6066 // if(size), result in bit
6067 // if(!size && ifx), conditional oper: if(left & right)
6068 symbol *tlbl = newiTempLabel (NULL);
6069 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6071 emitcode ("setb", "c");
6074 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6075 emitcode ("anl", "a,%s",
6076 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6078 if (AOP_TYPE(left)==AOP_ACC) {
6079 emitcode("mov", "b,a");
6080 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6081 emitcode("anl", "a,b");
6083 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6084 emitcode ("anl", "a,%s",
6085 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6088 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6094 emitcode ("", "!tlabeldef", tlbl->key + 100);
6098 jmpTrueOrFalse (ifx, tlbl);
6102 for (; (size--); offset++)
6105 // result = left & right
6106 if (AOP_TYPE (right) == AOP_LIT)
6108 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6110 aopPut (AOP (result),
6111 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6115 else if (bytelit == 0)
6117 aopPut (AOP (result), zero, offset);
6120 D (emitcode (";", "better literal AND."););
6121 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6122 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6123 FALSE, FALSE, FALSE));
6128 // faster than result <- left, anl result,right
6129 // and better if result is SFR
6130 if (AOP_TYPE (left) == AOP_ACC)
6132 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6133 FALSE, FALSE, FALSE));
6137 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6138 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6140 emitcode("mov", "b,a");
6144 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6145 emitcode ("anl", "a,%s", rOp);
6148 aopPut (AOP (result), "a", offset);
6154 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6155 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6156 freeAsmop (result, NULL, ic, TRUE);
6160 /*-----------------------------------------------------------------*/
6161 /* genOr - code for or */
6162 /*-----------------------------------------------------------------*/
6164 genOr (iCode * ic, iCode * ifx)
6166 operand *left, *right, *result;
6167 int size, offset = 0;
6168 unsigned long lit = 0L;
6171 D (emitcode (";", "genOr "););
6173 AOP_OP_3_NOFATAL (ic, pushResult);
6174 AOP_SET_LOCALS (ic);
6178 genFarFarLogicOp(ic, "orl");
6184 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6186 AOP_TYPE (left), AOP_TYPE (right));
6187 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6189 AOP_SIZE (left), AOP_SIZE (right));
6192 /* if left is a literal & right is not then exchange them */
6193 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6194 #ifdef LOGIC_OPS_BROKEN
6195 || AOP_NEEDSACC (left) // I think this is a net loss now.
6199 operand *tmp = right;
6204 /* if result = right then exchange them */
6205 if (sameRegs (AOP (result), AOP (right)))
6207 operand *tmp = right;
6212 /* if right is bit then exchange them */
6213 if (AOP_TYPE (right) == AOP_CRY &&
6214 AOP_TYPE (left) != AOP_CRY)
6216 operand *tmp = right;
6220 if (AOP_TYPE (right) == AOP_LIT)
6221 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6223 size = AOP_SIZE (result);
6227 if (AOP_TYPE (left) == AOP_CRY)
6229 if (AOP_TYPE (right) == AOP_LIT)
6231 // c = bit & literal;
6234 // lit != 0 => result = 1
6235 if (AOP_TYPE (result) == AOP_CRY)
6238 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6240 continueIfTrue (ifx);
6243 emitcode ("setb", "c");
6247 // lit == 0 => result = left
6248 if (size && sameRegs (AOP (result), AOP (left)))
6250 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6255 if (AOP_TYPE (right) == AOP_CRY)
6258 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6259 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6264 symbol *tlbl = newiTempLabel (NULL);
6265 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6266 emitcode ("setb", "c");
6267 emitcode ("jb", "%s,!tlabel",
6268 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6270 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6271 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6273 jmpTrueOrFalse (ifx, tlbl);
6279 emitcode ("", "!tlabeldef", tlbl->key + 100);
6288 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6289 genIfxJump (ifx, "c");
6293 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6294 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6295 if ((AOP_TYPE (right) == AOP_LIT) &&
6296 (AOP_TYPE (result) == AOP_CRY) &&
6297 (AOP_TYPE (left) != AOP_CRY))
6303 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6305 continueIfTrue (ifx);
6310 // lit = 0, result = boolean(left)
6312 emitcode ("setb", "c");
6316 symbol *tlbl = newiTempLabel (NULL);
6317 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6319 emitcode ("", "!tlabeldef", tlbl->key + 100);
6323 genIfxJump (ifx, "a");
6331 /* if left is same as result */
6332 if (sameRegs (AOP (result), AOP (left)))
6334 for (; size--; offset++)
6336 if (AOP_TYPE (right) == AOP_LIT)
6338 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6344 if (IS_AOP_PREG (left))
6346 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6347 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6348 aopPut (AOP (result), "a", offset);
6352 emitcode ("orl", "%s,%s",
6353 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6354 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6360 if (AOP_TYPE (left) == AOP_ACC)
6362 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6366 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6367 if (IS_AOP_PREG (left))
6369 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6370 aopPut (AOP (result), "a", offset);
6374 emitcode ("orl", "%s,a",
6375 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6383 // left & result in different registers
6384 if (AOP_TYPE (result) == AOP_CRY)
6387 // if(size), result in bit
6388 // if(!size && ifx), conditional oper: if(left | right)
6389 symbol *tlbl = newiTempLabel (NULL);
6390 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6392 emitcode ("setb", "c");
6395 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6396 emitcode ("orl", "a,%s",
6397 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6399 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6400 emitcode ("orl", "a,%s",
6401 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6403 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6409 emitcode ("", "!tlabeldef", tlbl->key + 100);
6413 jmpTrueOrFalse (ifx, tlbl);
6417 _startLazyDPSEvaluation();
6418 for (; (size--); offset++)
6421 // result = left & right
6422 if (AOP_TYPE (right) == AOP_LIT)
6424 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6426 aopPut (AOP (result),
6427 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6431 D (emitcode (";", "better literal OR."););
6432 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6433 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6434 FALSE, FALSE, FALSE));
6439 // faster than result <- left, anl result,right
6440 // and better if result is SFR
6441 if (AOP_TYPE (left) == AOP_ACC)
6443 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6444 FALSE, FALSE, FALSE));
6448 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6450 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6452 emitcode("mov", "b,a");
6456 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6457 emitcode ("orl", "a,%s", rOp);
6460 aopPut (AOP (result), "a", offset);
6462 _endLazyDPSEvaluation();
6467 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6468 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469 freeAsmop (result, NULL, ic, TRUE);
6472 /*-----------------------------------------------------------------*/
6473 /* genXor - code for xclusive or */
6474 /*-----------------------------------------------------------------*/
6476 genXor (iCode * ic, iCode * ifx)
6478 operand *left, *right, *result;
6479 int size, offset = 0;
6480 unsigned long lit = 0L;
6483 D (emitcode (";", "genXor "););
6485 AOP_OP_3_NOFATAL (ic, pushResult);
6486 AOP_SET_LOCALS (ic);
6490 genFarFarLogicOp(ic, "xrl");
6495 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6497 AOP_TYPE (left), AOP_TYPE (right));
6498 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6500 AOP_SIZE (left), AOP_SIZE (right));
6503 /* if left is a literal & right is not ||
6504 if left needs acc & right does not */
6505 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6506 #ifdef LOGIC_OPS_BROKEN
6507 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6511 operand *tmp = right;
6516 /* if result = right then exchange them */
6517 if (sameRegs (AOP (result), AOP (right)))
6519 operand *tmp = right;
6524 /* if right is bit then exchange them */
6525 if (AOP_TYPE (right) == AOP_CRY &&
6526 AOP_TYPE (left) != AOP_CRY)
6528 operand *tmp = right;
6532 if (AOP_TYPE (right) == AOP_LIT)
6533 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6535 size = AOP_SIZE (result);
6539 if (AOP_TYPE (left) == AOP_CRY)
6541 if (AOP_TYPE (right) == AOP_LIT)
6543 // c = bit & literal;
6546 // lit>>1 != 0 => result = 1
6547 if (AOP_TYPE (result) == AOP_CRY)
6550 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6552 continueIfTrue (ifx);
6555 emitcode ("setb", "c");
6562 // lit == 0, result = left
6563 if (size && sameRegs (AOP (result), AOP (left)))
6565 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6569 // lit == 1, result = not(left)
6570 if (size && sameRegs (AOP (result), AOP (left)))
6572 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6577 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6578 emitcode ("cpl", "c");
6587 symbol *tlbl = newiTempLabel (NULL);
6588 if (AOP_TYPE (right) == AOP_CRY)
6591 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6595 int sizer = AOP_SIZE (right);
6597 // if val>>1 != 0, result = 1
6598 emitcode ("setb", "c");
6601 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6603 // test the msb of the lsb
6604 emitcode ("anl", "a,#!constbyte",0xfe);
6605 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6609 emitcode ("rrc", "a");
6611 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6612 emitcode ("cpl", "c");
6613 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6620 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6621 genIfxJump (ifx, "c");
6625 if (sameRegs (AOP (result), AOP (left)))
6627 /* if left is same as result */
6628 for (; size--; offset++)
6630 if (AOP_TYPE (right) == AOP_LIT)
6632 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6634 else if (IS_AOP_PREG (left))
6636 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6637 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6638 aopPut (AOP (result), "a", offset);
6641 emitcode ("xrl", "%s,%s",
6642 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6643 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6647 if (AOP_TYPE (left) == AOP_ACC)
6648 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6651 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6652 if (IS_AOP_PREG (left))
6654 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6655 aopPut (AOP (result), "a", offset);
6658 emitcode ("xrl", "%s,a",
6659 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6666 // left & result in different registers
6667 if (AOP_TYPE (result) == AOP_CRY)
6670 // if(size), result in bit
6671 // if(!size && ifx), conditional oper: if(left ^ right)
6672 symbol *tlbl = newiTempLabel (NULL);
6673 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6676 emitcode ("setb", "c");
6679 if ((AOP_TYPE (right) == AOP_LIT) &&
6680 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6682 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6686 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6687 emitcode ("xrl", "a,%s",
6688 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6690 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6691 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6693 emitcode("mov", "b,a");
6697 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6698 emitcode ("xrl", "a,%s", rOp);
6701 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6707 emitcode ("", "!tlabeldef", tlbl->key + 100);
6711 jmpTrueOrFalse (ifx, tlbl);
6715 for (; (size--); offset++)
6718 // result = left & right
6719 if (AOP_TYPE (right) == AOP_LIT)
6721 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6723 aopPut (AOP (result),
6724 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6728 D (emitcode (";", "better literal XOR."););
6729 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6730 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6731 FALSE, FALSE, FALSE));
6735 // faster than result <- left, anl result,right
6736 // and better if result is SFR
6737 if (AOP_TYPE (left) == AOP_ACC)
6739 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6740 FALSE, FALSE, FALSE));
6744 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6745 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6747 emitcode("mov", "b,a");
6751 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6752 emitcode ("xrl", "a,%s", rOp);
6755 aopPut (AOP (result), "a", offset);
6762 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6763 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6764 freeAsmop (result, NULL, ic, TRUE);
6767 /*-----------------------------------------------------------------*/
6768 /* genInline - write the inline code out */
6769 /*-----------------------------------------------------------------*/
6771 genInline (iCode * ic)
6773 char *buffer, *bp, *bp1;
6775 D (emitcode (";", "genInline ");
6778 _G.inLine += (!options.asmpeep);
6780 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6781 strcpy (buffer, IC_INLINE (ic));
6783 /* emit each line as a code */
6808 /* emitcode("",buffer); */
6809 _G.inLine -= (!options.asmpeep);
6812 /*-----------------------------------------------------------------*/
6813 /* genRRC - rotate right with carry */
6814 /*-----------------------------------------------------------------*/
6818 operand *left, *result;
6819 int size, offset = 0;
6822 D (emitcode (";", "genRRC ");
6825 /* rotate right with carry */
6826 left = IC_LEFT (ic);
6827 result = IC_RESULT (ic);
6828 aopOp (left, ic, FALSE, FALSE);
6829 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6831 /* move it to the result */
6832 size = AOP_SIZE (result);
6836 _startLazyDPSEvaluation ();
6839 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6841 emitcode ("rrc", "a");
6842 if (AOP_SIZE (result) > 1)
6843 aopPut (AOP (result), "a", offset--);
6845 _endLazyDPSEvaluation ();
6847 /* now we need to put the carry into the
6848 highest order byte of the result */
6849 if (AOP_SIZE (result) > 1)
6851 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6854 emitcode ("mov", "acc.7,c");
6855 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6856 freeAsmop (left, NULL, ic, TRUE);
6857 freeAsmop (result, NULL, ic, TRUE);
6860 /*-----------------------------------------------------------------*/
6861 /* genRLC - generate code for rotate left with carry */
6862 /*-----------------------------------------------------------------*/
6866 operand *left, *result;
6867 int size, offset = 0;
6870 D (emitcode (";", "genRLC ");
6873 /* rotate right with carry */
6874 left = IC_LEFT (ic);
6875 result = IC_RESULT (ic);
6876 aopOp (left, ic, FALSE, FALSE);
6877 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6879 /* move it to the result */
6880 size = AOP_SIZE (result);
6884 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6886 emitcode ("add", "a,acc");
6887 if (AOP_SIZE (result) > 1)
6889 aopPut (AOP (result), "a", offset++);
6892 _startLazyDPSEvaluation ();
6895 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6897 emitcode ("rlc", "a");
6898 if (AOP_SIZE (result) > 1)
6899 aopPut (AOP (result), "a", offset++);
6901 _endLazyDPSEvaluation ();
6903 /* now we need to put the carry into the
6904 highest order byte of the result */
6905 if (AOP_SIZE (result) > 1)
6907 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6910 emitcode ("mov", "acc.0,c");
6911 aopPut (AOP (result), "a", 0);
6912 freeAsmop (left, NULL, ic, TRUE);
6913 freeAsmop (result, NULL, ic, TRUE);
6916 /*-----------------------------------------------------------------*/
6917 /* genGetHbit - generates code get highest order bit */
6918 /*-----------------------------------------------------------------*/
6920 genGetHbit (iCode * ic)
6922 operand *left, *result;
6923 left = IC_LEFT (ic);
6924 result = IC_RESULT (ic);
6925 aopOp (left, ic, FALSE, FALSE);
6926 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6928 D (emitcode (";", "genGetHbit ");
6931 /* get the highest order byte into a */
6932 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6933 if (AOP_TYPE (result) == AOP_CRY)
6935 emitcode ("rlc", "a");
6940 emitcode ("rl", "a");
6941 emitcode ("anl", "a,#1");
6946 freeAsmop (left, NULL, ic, TRUE);
6947 freeAsmop (result, NULL, ic, TRUE);
6950 /*-----------------------------------------------------------------*/
6951 /* AccRol - rotate left accumulator by known count */
6952 /*-----------------------------------------------------------------*/
6954 AccRol (int shCount)
6956 shCount &= 0x0007; // shCount : 0..7
6963 emitcode ("rl", "a");
6966 emitcode ("rl", "a");
6967 emitcode ("rl", "a");
6970 emitcode ("swap", "a");
6971 emitcode ("rr", "a");
6974 emitcode ("swap", "a");
6977 emitcode ("swap", "a");
6978 emitcode ("rl", "a");
6981 emitcode ("rr", "a");
6982 emitcode ("rr", "a");
6985 emitcode ("rr", "a");
6990 /*-----------------------------------------------------------------*/
6991 /* AccLsh - left shift accumulator by known count */
6992 /*-----------------------------------------------------------------*/
6994 AccLsh (int shCount)
6999 emitcode ("add", "a,acc");
7000 else if (shCount == 2)
7002 emitcode ("add", "a,acc");
7003 emitcode ("add", "a,acc");
7007 /* rotate left accumulator */
7009 /* and kill the lower order bits */
7010 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7015 /*-----------------------------------------------------------------*/
7016 /* AccRsh - right shift accumulator by known count */
7017 /*-----------------------------------------------------------------*/
7019 AccRsh (int shCount)
7026 emitcode ("rrc", "a");
7030 /* rotate right accumulator */
7031 AccRol (8 - shCount);
7032 /* and kill the higher order bits */
7033 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7038 #ifdef BETTER_LITERAL_SHIFT
7039 /*-----------------------------------------------------------------*/
7040 /* AccSRsh - signed right shift accumulator by known count */
7041 /*-----------------------------------------------------------------*/
7043 AccSRsh (int shCount)
7050 emitcode ("mov", "c,acc.7");
7051 emitcode ("rrc", "a");
7053 else if (shCount == 2)
7055 emitcode ("mov", "c,acc.7");
7056 emitcode ("rrc", "a");
7057 emitcode ("mov", "c,acc.7");
7058 emitcode ("rrc", "a");
7062 tlbl = newiTempLabel (NULL);
7063 /* rotate right accumulator */
7064 AccRol (8 - shCount);
7065 /* and kill the higher order bits */
7066 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7067 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7068 emitcode ("orl", "a,#!constbyte",
7069 (unsigned char) ~SRMask[shCount]);
7070 emitcode ("", "!tlabeldef", tlbl->key + 100);
7076 #ifdef BETTER_LITERAL_SHIFT
7077 /*-----------------------------------------------------------------*/
7078 /* shiftR1Left2Result - shift right one byte from left to result */
7079 /*-----------------------------------------------------------------*/
7081 shiftR1Left2Result (operand * left, int offl,
7082 operand * result, int offr,
7083 int shCount, int sign)
7085 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7086 /* shift right accumulator */
7091 aopPut (AOP (result), "a", offr);
7095 #ifdef BETTER_LITERAL_SHIFT
7096 /*-----------------------------------------------------------------*/
7097 /* shiftL1Left2Result - shift left one byte from left to result */
7098 /*-----------------------------------------------------------------*/
7100 shiftL1Left2Result (operand * left, int offl,
7101 operand * result, int offr, int shCount)
7103 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7104 /* shift left accumulator */
7106 aopPut (AOP (result), "a", offr);
7110 #ifdef BETTER_LITERAL_SHIFT
7111 /*-----------------------------------------------------------------*/
7112 /* movLeft2Result - move byte from left to result */
7113 /*-----------------------------------------------------------------*/
7115 movLeft2Result (operand * left, int offl,
7116 operand * result, int offr, int sign)
7119 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7121 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7123 if (*l == '@' && (IS_AOP_PREG (result)))
7125 emitcode ("mov", "a,%s", l);
7126 aopPut (AOP (result), "a", offr);
7132 aopPut (AOP (result), l, offr);
7136 /* MSB sign in acc.7 ! */
7137 if (getDataSize (left) == offl + 1)
7139 emitcode ("mov", "a,%s", l);
7140 aopPut (AOP (result), "a", offr);
7148 #ifdef BETTER_LITERAL_SHIFT
7149 /*-----------------------------------------------------------------*/
7150 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7151 /*-----------------------------------------------------------------*/
7155 emitcode ("rrc", "a");
7156 emitcode ("xch", "a,%s", x);
7157 emitcode ("rrc", "a");
7158 emitcode ("xch", "a,%s", x);
7162 #ifdef BETTER_LITERAL_SHIFT
7164 /*-----------------------------------------------------------------*/
7165 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7166 /*-----------------------------------------------------------------*/
7170 emitcode ("xch", "a,%s", x);
7171 emitcode ("rlc", "a");
7172 emitcode ("xch", "a,%s", x);
7173 emitcode ("rlc", "a");
7177 #ifdef BETTER_LITERAL_SHIFT
7178 /*-----------------------------------------------------------------*/
7179 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7180 /*-----------------------------------------------------------------*/
7184 emitcode ("xch", "a,%s", x);
7185 emitcode ("add", "a,acc");
7186 emitcode ("xch", "a,%s", x);
7187 emitcode ("rlc", "a");
7191 #ifdef BETTER_LITERAL_SHIFT
7192 /*-----------------------------------------------------------------*/
7193 /* AccAXLsh - left shift a:x by known count (0..7) */
7194 /*-----------------------------------------------------------------*/
7196 AccAXLsh (char *x, int shCount)
7211 case 5: // AAAAABBB:CCCCCDDD
7213 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7215 emitcode ("anl", "a,#!constbyte",
7216 SLMask[shCount]); // BBB00000:CCCCCDDD
7218 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7220 AccRol (shCount); // DDDCCCCC:BBB00000
7222 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7224 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7226 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7228 emitcode ("anl", "a,#!constbyte",
7229 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7231 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7233 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7236 case 6: // AAAAAABB:CCCCCCDD
7237 emitcode ("anl", "a,#!constbyte",
7238 SRMask[shCount]); // 000000BB:CCCCCCDD
7239 emitcode ("mov", "c,acc.0"); // c = B
7240 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7242 AccAXRrl1 (x); // BCCCCCCD:D000000B
7243 AccAXRrl1 (x); // BBCCCCCC:DD000000
7245 emitcode("rrc","a");
7246 emitcode("xch","a,%s", x);
7247 emitcode("rrc","a");
7248 emitcode("mov","c,acc.0"); //<< get correct bit
7249 emitcode("xch","a,%s", x);
7251 emitcode("rrc","a");
7252 emitcode("xch","a,%s", x);
7253 emitcode("rrc","a");
7254 emitcode("xch","a,%s", x);
7257 case 7: // a:x <<= 7
7259 emitcode ("anl", "a,#!constbyte",
7260 SRMask[shCount]); // 0000000B:CCCCCCCD
7262 emitcode ("mov", "c,acc.0"); // c = B
7264 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7266 AccAXRrl1 (x); // BCCCCCCC:D0000000
7275 #ifdef BETTER_LITERAL_SHIFT
7277 /*-----------------------------------------------------------------*/
7278 /* AccAXRsh - right shift a:x known count (0..7) */
7279 /*-----------------------------------------------------------------*/
7281 AccAXRsh (char *x, int shCount)
7289 AccAXRrl1 (x); // 0->a:x
7294 AccAXRrl1 (x); // 0->a:x
7297 AccAXRrl1 (x); // 0->a:x
7302 case 5: // AAAAABBB:CCCCCDDD = a:x
7304 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7306 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7308 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7310 emitcode ("anl", "a,#!constbyte",
7311 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7313 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7315 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7317 emitcode ("anl", "a,#!constbyte",
7318 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7320 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7322 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7324 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7327 case 6: // AABBBBBB:CCDDDDDD
7329 emitcode ("mov", "c,acc.7");
7330 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7332 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7334 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7336 emitcode ("anl", "a,#!constbyte",
7337 SRMask[shCount]); // 000000AA:BBBBBBCC
7340 case 7: // ABBBBBBB:CDDDDDDD
7342 emitcode ("mov", "c,acc.7"); // c = A
7344 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7346 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7348 emitcode ("anl", "a,#!constbyte",
7349 SRMask[shCount]); // 0000000A:BBBBBBBC
7358 #ifdef BETTER_LITERAL_SHIFT
7359 /*-----------------------------------------------------------------*/
7360 /* AccAXRshS - right shift signed a:x known count (0..7) */
7361 /*-----------------------------------------------------------------*/
7363 AccAXRshS (char *x, int shCount)
7371 emitcode ("mov", "c,acc.7");
7372 AccAXRrl1 (x); // s->a:x
7376 emitcode ("mov", "c,acc.7");
7377 AccAXRrl1 (x); // s->a:x
7379 emitcode ("mov", "c,acc.7");
7380 AccAXRrl1 (x); // s->a:x
7385 case 5: // AAAAABBB:CCCCCDDD = a:x
7387 tlbl = newiTempLabel (NULL);
7388 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7390 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7392 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7394 emitcode ("anl", "a,#!constbyte",
7395 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7397 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7399 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7401 emitcode ("anl", "a,#!constbyte",
7402 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7404 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7406 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7408 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7410 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7411 emitcode ("orl", "a,#!constbyte",
7412 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7414 emitcode ("", "!tlabeldef", tlbl->key + 100);
7415 break; // SSSSAAAA:BBBCCCCC
7417 case 6: // AABBBBBB:CCDDDDDD
7419 tlbl = newiTempLabel (NULL);
7420 emitcode ("mov", "c,acc.7");
7421 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7423 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7425 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7427 emitcode ("anl", "a,#!constbyte",
7428 SRMask[shCount]); // 000000AA:BBBBBBCC
7430 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7431 emitcode ("orl", "a,#!constbyte",
7432 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7434 emitcode ("", "!tlabeldef", tlbl->key + 100);
7436 case 7: // ABBBBBBB:CDDDDDDD
7438 tlbl = newiTempLabel (NULL);
7439 emitcode ("mov", "c,acc.7"); // c = A
7441 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7443 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7445 emitcode ("anl", "a,#!constbyte",
7446 SRMask[shCount]); // 0000000A:BBBBBBBC
7448 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7449 emitcode ("orl", "a,#!constbyte",
7450 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7452 emitcode ("", "!tlabeldef", tlbl->key + 100);
7460 #ifdef BETTER_LITERAL_SHIFT
7462 _loadLeftIntoAx(char **lsb,
7468 // Get the initial value from left into a pair of registers.
7469 // MSB must be in A, LSB can be any register.
7471 // If the result is held in registers, it is an optimization
7472 // if the LSB can be held in the register which will hold the,
7473 // result LSB since this saves us from having to copy it into
7474 // the result following AccAXLsh.
7476 // If the result is addressed indirectly, this is not a gain.
7477 if (AOP_NEEDSACC(result))
7481 _startLazyDPSEvaluation();
7482 if (AOP_TYPE(left) == AOP_DPTR2)
7485 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7486 // get LSB in DP2_RESULT_REG.
7487 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7488 assert(!strcmp(leftByte, DP2_RESULT_REG));
7492 // get LSB into DP2_RESULT_REG
7493 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7494 if (strcmp(leftByte, DP2_RESULT_REG))
7497 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7500 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7501 assert(strcmp(leftByte, DP2_RESULT_REG));
7504 _endLazyDPSEvaluation();
7505 *lsb = DP2_RESULT_REG;
7509 if (sameRegs (AOP (result), AOP (left)) &&
7510 ((offl + MSB16) == offr))
7512 /* don't crash result[offr] */
7513 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7514 emitcode ("xch", "a,%s",
7515 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7519 movLeft2Result (left, offl, result, offr, 0);
7520 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7522 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7523 assert(strcmp(*lsb,"a"));
7528 _storeAxResults(char *lsb,
7532 _startLazyDPSEvaluation();
7533 if (AOP_NEEDSACC(result))
7535 /* We have to explicitly update the result LSB.
7537 emitcode("xch","a,%s", lsb);
7538 aopPut(AOP(result), "a", offr);
7539 emitcode("mov","a,%s", lsb);
7541 if (getDataSize (result) > 1)
7543 aopPut (AOP (result), "a", offr + MSB16);
7545 _endLazyDPSEvaluation();
7548 /*-----------------------------------------------------------------*/
7549 /* shiftL2Left2Result - shift left two bytes from left to result */
7550 /*-----------------------------------------------------------------*/
7552 shiftL2Left2Result (operand * left, int offl,
7553 operand * result, int offr, int shCount)
7557 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7559 AccAXLsh (lsb, shCount);
7561 _storeAxResults(lsb, result, offr);
7565 #ifdef BETTER_LITERAL_SHIFT
7566 /*-----------------------------------------------------------------*/
7567 /* shiftR2Left2Result - shift right two bytes from left to result */
7568 /*-----------------------------------------------------------------*/
7570 shiftR2Left2Result (operand * left, int offl,
7571 operand * result, int offr,
7572 int shCount, int sign)
7576 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7578 /* a:x >> shCount (x = lsb(result)) */
7581 AccAXRshS(lsb, shCount);
7585 AccAXRsh(lsb, shCount);
7588 _storeAxResults(lsb, result, offr);
7594 /*-----------------------------------------------------------------*/
7595 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7596 /*-----------------------------------------------------------------*/
7598 shiftLLeftOrResult (operand * left, int offl,
7599 operand * result, int offr, int shCount)
7601 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7602 /* shift left accumulator */
7604 /* or with result */
7605 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7606 /* back to result */
7607 aopPut (AOP (result), "a", offr);
7613 /*-----------------------------------------------------------------*/
7614 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7615 /*-----------------------------------------------------------------*/
7617 shiftRLeftOrResult (operand * left, int offl,
7618 operand * result, int offr, int shCount)
7620 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7621 /* shift right accumulator */
7623 /* or with result */
7624 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7625 /* back to result */
7626 aopPut (AOP (result), "a", offr);
7630 #ifdef BETTER_LITERAL_SHIFT
7631 /*-----------------------------------------------------------------*/
7632 /* genlshOne - left shift a one byte quantity by known count */
7633 /*-----------------------------------------------------------------*/
7635 genlshOne (operand * result, operand * left, int shCount)
7637 D (emitcode (";", "genlshOne "););
7638 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7642 #ifdef BETTER_LITERAL_SHIFT
7643 /*-----------------------------------------------------------------*/
7644 /* genlshTwo - left shift two bytes by known amount != 0 */
7645 /*-----------------------------------------------------------------*/
7647 genlshTwo (operand * result, operand * left, int shCount)
7651 D (emitcode (";", "genlshTwo "););
7653 size = getDataSize (result);
7655 /* if shCount >= 8 */
7660 _startLazyDPSEvaluation();
7666 _endLazyDPSEvaluation();
7667 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7668 aopPut (AOP (result), zero, LSB);
7672 movLeft2Result (left, LSB, result, MSB16, 0);
7673 aopPut (AOP (result), zero, LSB);
7674 _endLazyDPSEvaluation();
7679 aopPut (AOP (result), zero, LSB);
7680 _endLazyDPSEvaluation();
7684 /* 1 <= shCount <= 7 */
7689 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7693 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7701 /*-----------------------------------------------------------------*/
7702 /* shiftLLong - shift left one long from left to result */
7703 /* offl = LSB or MSB16 */
7704 /*-----------------------------------------------------------------*/
7706 shiftLLong (operand * left, operand * result, int offr)
7709 int size = AOP_SIZE (result);
7711 if (size >= LSB + offr)
7713 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7715 emitcode ("add", "a,acc");
7716 if (sameRegs (AOP (left), AOP (result)) &&
7717 size >= MSB16 + offr && offr != LSB)
7718 emitcode ("xch", "a,%s",
7719 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7721 aopPut (AOP (result), "a", LSB + offr);
7724 if (size >= MSB16 + offr)
7726 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7728 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7731 emitcode ("rlc", "a");
7732 if (sameRegs (AOP (left), AOP (result)) &&
7733 size >= MSB24 + offr && offr != LSB)
7734 emitcode ("xch", "a,%s",
7735 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7737 aopPut (AOP (result), "a", MSB16 + offr);
7740 if (size >= MSB24 + offr)
7742 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7744 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7747 emitcode ("rlc", "a");
7748 if (sameRegs (AOP (left), AOP (result)) &&
7749 size >= MSB32 + offr && offr != LSB)
7750 emitcode ("xch", "a,%s",
7751 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7753 aopPut (AOP (result), "a", MSB24 + offr);
7756 if (size > MSB32 + offr)
7758 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7760 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7763 emitcode ("rlc", "a");
7764 aopPut (AOP (result), "a", MSB32 + offr);
7767 aopPut (AOP (result), zero, LSB);
7773 /*-----------------------------------------------------------------*/
7774 /* genlshFour - shift four byte by a known amount != 0 */
7775 /*-----------------------------------------------------------------*/
7777 genlshFour (operand * result, operand * left, int shCount)
7781 D (emitcode (";", "genlshFour ");
7784 size = AOP_SIZE (result);
7786 /* if shifting more that 3 bytes */
7791 /* lowest order of left goes to the highest
7792 order of the destination */
7793 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7795 movLeft2Result (left, LSB, result, MSB32, 0);
7796 aopPut (AOP (result), zero, LSB);
7797 aopPut (AOP (result), zero, MSB16);
7798 aopPut (AOP (result), zero, MSB24);
7802 /* more than two bytes */
7803 else if (shCount >= 16)
7805 /* lower order two bytes goes to higher order two bytes */
7807 /* if some more remaining */
7809 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7812 movLeft2Result (left, MSB16, result, MSB32, 0);
7813 movLeft2Result (left, LSB, result, MSB24, 0);
7815 aopPut (AOP (result), zero, MSB16);
7816 aopPut (AOP (result), zero, LSB);
7820 /* if more than 1 byte */
7821 else if (shCount >= 8)
7823 /* lower order three bytes goes to higher order three bytes */
7828 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7830 movLeft2Result (left, LSB, result, MSB16, 0);
7836 movLeft2Result (left, MSB24, result, MSB32, 0);
7837 movLeft2Result (left, MSB16, result, MSB24, 0);
7838 movLeft2Result (left, LSB, result, MSB16, 0);
7839 aopPut (AOP (result), zero, LSB);
7841 else if (shCount == 1)
7842 shiftLLong (left, result, MSB16);
7845 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7846 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7847 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7848 aopPut (AOP (result), zero, LSB);
7853 /* 1 <= shCount <= 7 */
7854 else if (shCount <= 2)
7856 shiftLLong (left, result, LSB);
7858 shiftLLong (result, result, LSB);
7860 /* 3 <= shCount <= 7, optimize */
7863 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7864 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7865 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7870 #ifdef BETTER_LITERAL_SHIFT
7871 /*-----------------------------------------------------------------*/
7872 /* genLeftShiftLiteral - left shifting by known count */
7873 /*-----------------------------------------------------------------*/
7875 genLeftShiftLiteral (operand * left,
7880 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7883 size = getSize (operandType (result));
7885 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7887 /* We only handle certain easy cases so far. */
7889 && (shCount < (size * 8))
7893 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7897 freeAsmop (right, NULL, ic, TRUE);
7899 aopOp(left, ic, FALSE, FALSE);
7900 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7903 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7905 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7906 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7908 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7911 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7913 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7914 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7916 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7922 emitcode ("; shift left ", "result %d, left %d", size,
7926 /* I suppose that the left size >= result size */
7929 _startLazyDPSEvaluation();
7932 movLeft2Result (left, size, result, size, 0);
7934 _endLazyDPSEvaluation();
7936 else if (shCount >= (size * 8))
7938 _startLazyDPSEvaluation();
7941 aopPut (AOP (result), zero, size);
7943 _endLazyDPSEvaluation();
7950 genlshOne (result, left, shCount);
7954 genlshTwo (result, left, shCount);
7958 genlshFour (result, left, shCount);
7962 fprintf(stderr, "*** ack! mystery literal shift!\n");
7966 freeAsmop (left, NULL, ic, TRUE);
7967 freeAsmop (result, NULL, ic, TRUE);
7972 /*-----------------------------------------------------------------*/
7973 /* genLeftShift - generates code for left shifting */
7974 /*-----------------------------------------------------------------*/
7976 genLeftShift (iCode * ic)
7978 operand *left, *right, *result;
7981 symbol *tlbl, *tlbl1;
7983 D (emitcode (";", "genLeftShift "););
7985 right = IC_RIGHT (ic);
7986 left = IC_LEFT (ic);
7987 result = IC_RESULT (ic);
7989 aopOp (right, ic, FALSE, FALSE);
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /* if the shift count is known then do it
7994 as efficiently as possible */
7995 if (AOP_TYPE (right) == AOP_LIT)
7997 if (genLeftShiftLiteral (left, right, result, ic))
8004 /* shift count is unknown then we have to form
8005 a loop get the loop count in B : Note: we take
8006 only the lower order byte since shifting
8007 more that 32 bits make no sense anyway, ( the
8008 largest size of an object can be only 32 bits ) */
8010 if (AOP_TYPE (right) == AOP_LIT)
8012 /* Really should be handled by genLeftShiftLiteral,
8013 * but since I'm too lazy to fix that today, at least we can make
8014 * some small improvement.
8016 emitcode("mov", "b,#!constbyte",
8017 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8021 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8022 emitcode ("inc", "b");
8024 freeAsmop (right, NULL, ic, TRUE);
8025 aopOp (left, ic, FALSE, FALSE);
8026 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8028 /* now move the left to the result if they are not the
8030 if (!sameRegs (AOP (left), AOP (result)) &&
8031 AOP_SIZE (result) > 1)
8034 size = AOP_SIZE (result);
8036 _startLazyDPSEvaluation ();
8039 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8040 if (*l == '@' && (IS_AOP_PREG (result)))
8043 emitcode ("mov", "a,%s", l);
8044 aopPut (AOP (result), "a", offset);
8047 aopPut (AOP (result), l, offset);
8050 _endLazyDPSEvaluation ();
8053 tlbl = newiTempLabel (NULL);
8054 size = AOP_SIZE (result);
8056 tlbl1 = newiTempLabel (NULL);
8058 /* if it is only one byte then */
8061 symbol *tlbl1 = newiTempLabel (NULL);
8063 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8065 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8066 emitcode ("", "!tlabeldef", tlbl->key + 100);
8067 emitcode ("add", "a,acc");
8068 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8069 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8070 aopPut (AOP (result), "a", 0);
8074 reAdjustPreg (AOP (result));
8076 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8077 emitcode ("", "!tlabeldef", tlbl->key + 100);
8078 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8080 emitcode ("add", "a,acc");
8081 aopPut (AOP (result), "a", offset++);
8082 _startLazyDPSEvaluation ();
8085 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8087 emitcode ("rlc", "a");
8088 aopPut (AOP (result), "a", offset++);
8090 _endLazyDPSEvaluation ();
8091 reAdjustPreg (AOP (result));
8093 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8094 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8096 freeAsmop (left, NULL, ic, TRUE);
8097 freeAsmop (result, NULL, ic, TRUE);
8100 #ifdef BETTER_LITERAL_SHIFT
8101 /*-----------------------------------------------------------------*/
8102 /* genrshOne - right shift a one byte quantity by known count */
8103 /*-----------------------------------------------------------------*/
8105 genrshOne (operand * result, operand * left,
8106 int shCount, int sign)
8108 D (emitcode (";", "genrshOne"););
8109 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8113 #ifdef BETTER_LITERAL_SHIFT
8114 /*-----------------------------------------------------------------*/
8115 /* genrshTwo - right shift two bytes by known amount != 0 */
8116 /*-----------------------------------------------------------------*/
8118 genrshTwo (operand * result, operand * left,
8119 int shCount, int sign)
8121 D (emitcode (";", "genrshTwo"););
8123 /* if shCount >= 8 */
8127 _startLazyDPSEvaluation();
8130 shiftR1Left2Result (left, MSB16, result, LSB,
8135 movLeft2Result (left, MSB16, result, LSB, sign);
8137 addSign (result, MSB16, sign);
8138 _endLazyDPSEvaluation();
8141 /* 1 <= shCount <= 7 */
8144 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8151 /*-----------------------------------------------------------------*/
8152 /* shiftRLong - shift right one long from left to result */
8153 /* offl = LSB or MSB16 */
8154 /*-----------------------------------------------------------------*/
8156 shiftRLong (operand * left, int offl,
8157 operand * result, int sign)
8159 int isSameRegs=sameRegs(AOP(left),AOP(result));
8161 if (isSameRegs && offl>1) {
8162 // we are in big trouble, but this shouldn't happen
8163 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8166 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8171 emitcode ("rlc", "a");
8172 emitcode ("subb", "a,acc");
8173 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8175 aopPut (AOP(result), zero, MSB32);
8180 emitcode ("clr", "c");
8182 emitcode ("mov", "c,acc.7");
8185 emitcode ("rrc", "a");
8187 if (isSameRegs && offl==MSB16) {
8188 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8190 aopPut (AOP (result), "a", MSB32);
8191 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8194 emitcode ("rrc", "a");
8195 if (isSameRegs && offl==1) {
8196 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8198 aopPut (AOP (result), "a", MSB24);
8199 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8201 emitcode ("rrc", "a");
8202 aopPut (AOP (result), "a", MSB16 - offl);
8206 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8207 emitcode ("rrc", "a");
8208 aopPut (AOP (result), "a", LSB);
8215 /*-----------------------------------------------------------------*/
8216 /* genrshFour - shift four byte by a known amount != 0 */
8217 /*-----------------------------------------------------------------*/
8219 genrshFour (operand * result, operand * left,
8220 int shCount, int sign)
8222 D (emitcode (";", "genrshFour");
8225 /* if shifting more that 3 bytes */
8230 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8232 movLeft2Result (left, MSB32, result, LSB, sign);
8233 addSign (result, MSB16, sign);
8235 else if (shCount >= 16)
8239 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8242 movLeft2Result (left, MSB24, result, LSB, 0);
8243 movLeft2Result (left, MSB32, result, MSB16, sign);
8245 addSign (result, MSB24, sign);
8247 else if (shCount >= 8)
8251 shiftRLong (left, MSB16, result, sign);
8252 else if (shCount == 0)
8254 movLeft2Result (left, MSB16, result, LSB, 0);
8255 movLeft2Result (left, MSB24, result, MSB16, 0);
8256 movLeft2Result (left, MSB32, result, MSB24, sign);
8257 addSign (result, MSB32, sign);
8261 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8262 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8263 /* the last shift is signed */
8264 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8265 addSign (result, MSB32, sign);
8269 { /* 1 <= shCount <= 7 */
8272 shiftRLong (left, LSB, result, sign);
8274 shiftRLong (result, LSB, result, sign);
8278 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8279 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8280 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8286 #ifdef BETTER_LITERAL_SHIFT
8287 /*-----------------------------------------------------------------*/
8288 /* genRightShiftLiteral - right shifting by known count */
8289 /*-----------------------------------------------------------------*/
8291 genRightShiftLiteral (operand * left,
8297 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8300 size = getSize (operandType (result));
8302 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8304 /* We only handle certain easy cases so far. */
8306 && (shCount < (size * 8))
8310 D(emitcode (";", "genRightShiftLiteral wimping out"););
8314 freeAsmop (right, NULL, ic, TRUE);
8316 aopOp (left, ic, FALSE, FALSE);
8317 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8320 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8324 /* test the LEFT size !!! */
8326 /* I suppose that the left size >= result size */
8329 size = getDataSize (result);
8330 _startLazyDPSEvaluation();
8333 movLeft2Result (left, size, result, size, 0);
8335 _endLazyDPSEvaluation();
8337 else if (shCount >= (size * 8))
8341 /* get sign in acc.7 */
8342 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8344 addSign (result, LSB, sign);
8351 genrshOne (result, left, shCount, sign);
8355 genrshTwo (result, left, shCount, sign);
8359 genrshFour (result, left, shCount, sign);
8366 freeAsmop (left, NULL, ic, TRUE);
8367 freeAsmop (result, NULL, ic, TRUE);
8373 /*-----------------------------------------------------------------*/
8374 /* genSignedRightShift - right shift of signed number */
8375 /*-----------------------------------------------------------------*/
8377 genSignedRightShift (iCode * ic)
8379 operand *right, *left, *result;
8382 symbol *tlbl, *tlbl1;
8384 D (emitcode (";", "genSignedRightShift "););
8386 /* we do it the hard way put the shift count in b
8387 and loop thru preserving the sign */
8389 right = IC_RIGHT (ic);
8390 left = IC_LEFT (ic);
8391 result = IC_RESULT (ic);
8393 aopOp (right, ic, FALSE, FALSE);
8395 #ifdef BETTER_LITERAL_SHIFT
8396 if (AOP_TYPE (right) == AOP_LIT)
8398 if (genRightShiftLiteral (left, right, result, ic, 1))
8404 /* shift count is unknown then we have to form
8405 a loop get the loop count in B : Note: we take
8406 only the lower order byte since shifting
8407 more that 32 bits make no sense anyway, ( the
8408 largest size of an object can be only 32 bits ) */
8410 if (AOP_TYPE (right) == AOP_LIT)
8412 /* Really should be handled by genRightShiftLiteral,
8413 * but since I'm too lazy to fix that today, at least we can make
8414 * some small improvement.
8416 emitcode("mov", "b,#!constbyte",
8417 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8421 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8422 emitcode ("inc", "b");
8424 freeAsmop (right, NULL, ic, TRUE);
8425 aopOp (left, ic, FALSE, FALSE);
8426 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8428 /* now move the left to the result if they are not the
8430 if (!sameRegs (AOP (left), AOP (result)) &&
8431 AOP_SIZE (result) > 1)
8434 size = AOP_SIZE (result);
8436 _startLazyDPSEvaluation ();
8439 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8440 if (*l == '@' && IS_AOP_PREG (result))
8443 emitcode ("mov", "a,%s", l);
8444 aopPut (AOP (result), "a", offset);
8447 aopPut (AOP (result), l, offset);
8450 _endLazyDPSEvaluation ();
8453 /* mov the highest order bit to OVR */
8454 tlbl = newiTempLabel (NULL);
8455 tlbl1 = newiTempLabel (NULL);
8457 size = AOP_SIZE (result);
8459 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8460 emitcode ("rlc", "a");
8461 emitcode ("mov", "ov,c");
8462 /* if it is only one byte then */
8465 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8467 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8468 emitcode ("", "!tlabeldef", tlbl->key + 100);
8469 emitcode ("mov", "c,ov");
8470 emitcode ("rrc", "a");
8471 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8472 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8473 aopPut (AOP (result), "a", 0);
8477 reAdjustPreg (AOP (result));
8478 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8479 emitcode ("", "!tlabeldef", tlbl->key + 100);
8480 emitcode ("mov", "c,ov");
8481 _startLazyDPSEvaluation ();
8484 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8486 emitcode ("rrc", "a");
8487 aopPut (AOP (result), "a", offset--);
8489 _endLazyDPSEvaluation ();
8490 reAdjustPreg (AOP (result));
8491 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8492 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8495 freeAsmop (left, NULL, ic, TRUE);
8496 freeAsmop (result, NULL, ic, TRUE);
8499 /*-----------------------------------------------------------------*/
8500 /* genRightShift - generate code for right shifting */
8501 /*-----------------------------------------------------------------*/
8503 genRightShift (iCode * ic)
8505 operand *right, *left, *result;
8509 symbol *tlbl, *tlbl1;
8511 D (emitcode (";", "genRightShift "););
8513 /* if signed then we do it the hard way preserve the
8514 sign bit moving it inwards */
8515 retype = getSpec (operandType (IC_RESULT (ic)));
8517 if (!SPEC_USIGN (retype))
8519 genSignedRightShift (ic);
8523 /* signed & unsigned types are treated the same : i.e. the
8524 signed is NOT propagated inwards : quoting from the
8525 ANSI - standard : "for E1 >> E2, is equivalent to division
8526 by 2**E2 if unsigned or if it has a non-negative value,
8527 otherwise the result is implementation defined ", MY definition
8528 is that the sign does not get propagated */
8530 right = IC_RIGHT (ic);
8531 left = IC_LEFT (ic);
8532 result = IC_RESULT (ic);
8534 aopOp (right, ic, FALSE, FALSE);
8536 #ifdef BETTER_LITERAL_SHIFT
8537 /* if the shift count is known then do it
8538 as efficiently as possible */
8539 if (AOP_TYPE (right) == AOP_LIT)
8541 if (genRightShiftLiteral (left, right, result, ic, 0))
8548 /* shift count is unknown then we have to form
8549 a loop get the loop count in B : Note: we take
8550 only the lower order byte since shifting
8551 more that 32 bits make no sense anyway, ( the
8552 largest size of an object can be only 32 bits ) */
8554 if (AOP_TYPE (right) == AOP_LIT)
8556 /* Really should be handled by genRightShiftLiteral,
8557 * but since I'm too lazy to fix that today, at least we can make
8558 * some small improvement.
8560 emitcode("mov", "b,#!constbyte",
8561 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8565 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8566 emitcode ("inc", "b");
8568 freeAsmop (right, NULL, ic, TRUE);
8569 aopOp (left, ic, FALSE, FALSE);
8570 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8572 /* now move the left to the result if they are not the
8574 if (!sameRegs (AOP (left), AOP (result)) &&
8575 AOP_SIZE (result) > 1)
8578 size = AOP_SIZE (result);
8580 _startLazyDPSEvaluation ();
8583 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8584 if (*l == '@' && IS_AOP_PREG (result))
8587 emitcode ("mov", "a,%s", l);
8588 aopPut (AOP (result), "a", offset);
8591 aopPut (AOP (result), l, offset);
8594 _endLazyDPSEvaluation ();
8597 tlbl = newiTempLabel (NULL);
8598 tlbl1 = newiTempLabel (NULL);
8599 size = AOP_SIZE (result);
8602 /* if it is only one byte then */
8605 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8607 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8608 emitcode ("", "!tlabeldef", tlbl->key + 100);
8610 emitcode ("rrc", "a");
8611 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8612 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8613 aopPut (AOP (result), "a", 0);
8617 reAdjustPreg (AOP (result));
8618 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8619 emitcode ("", "!tlabeldef", tlbl->key + 100);
8621 _startLazyDPSEvaluation ();
8624 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8626 emitcode ("rrc", "a");
8627 aopPut (AOP (result), "a", offset--);
8629 _endLazyDPSEvaluation ();
8630 reAdjustPreg (AOP (result));
8632 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8633 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8636 freeAsmop (left, NULL, ic, TRUE);
8637 freeAsmop (result, NULL, ic, TRUE);
8640 /*-----------------------------------------------------------------*/
8641 /* genUnpackBits - generates code for unpacking bits */
8642 /*-----------------------------------------------------------------*/
8644 genUnpackBits (operand * result, char *rname, int ptype)
8651 D (emitcode (";", "genUnpackBits ");
8654 etype = getSpec (operandType (result));
8656 /* read the first byte */
8662 emitcode ("mov", "a,@%s", rname);
8666 emitcode ("movx", "a,@%s", rname);
8670 emitcode ("movx", "a,@dptr");
8674 emitcode ("clr", "a");
8675 emitcode ("movc", "a,@a+dptr");
8679 emitcode ("lcall", "__gptrget");
8683 /* if we have bitdisplacement then it fits */
8684 /* into this byte completely or if length is */
8685 /* less than a byte */
8686 if ((shCnt = SPEC_BSTR (etype)) ||
8687 (SPEC_BLEN (etype) <= 8))
8690 /* shift right acc */
8693 emitcode ("anl", "a,#!constbyte",
8694 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8695 aopPut (AOP (result), "a", offset);
8699 /* bit field did not fit in a byte */
8700 rlen = SPEC_BLEN (etype) - 8;
8701 aopPut (AOP (result), "a", offset++);
8710 emitcode ("inc", "%s", rname);
8711 emitcode ("mov", "a,@%s", rname);
8715 emitcode ("inc", "%s", rname);
8716 emitcode ("movx", "a,@%s", rname);
8720 emitcode ("inc", "dptr");
8721 emitcode ("movx", "a,@dptr");
8725 emitcode ("clr", "a");
8726 emitcode ("inc", "dptr");
8727 emitcode ("movc", "a,@a+dptr");
8731 emitcode ("inc", "dptr");
8732 emitcode ("lcall", "__gptrget");
8737 /* if we are done */
8741 aopPut (AOP (result), "a", offset++);
8747 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8748 aopPut (AOP (result), "a", offset);
8755 /*-----------------------------------------------------------------*/
8756 /* genDataPointerGet - generates code when ptr offset is known */
8757 /*-----------------------------------------------------------------*/
8759 genDataPointerGet (operand * left,
8765 int size, offset = 0;
8766 aopOp (result, ic, TRUE, FALSE);
8768 /* get the string representation of the name */
8769 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8770 size = AOP_SIZE (result);
8771 _startLazyDPSEvaluation ();
8775 sprintf (buffer, "(%s + %d)", l + 1, offset);
8777 sprintf (buffer, "%s", l + 1);
8778 aopPut (AOP (result), buffer, offset++);
8780 _endLazyDPSEvaluation ();
8782 freeAsmop (left, NULL, ic, TRUE);
8783 freeAsmop (result, NULL, ic, TRUE);
8786 /*-----------------------------------------------------------------*/
8787 /* genNearPointerGet - emitcode for near pointer fetch */
8788 /*-----------------------------------------------------------------*/
8790 genNearPointerGet (operand * left,
8798 sym_link *rtype, *retype, *letype;
8799 sym_link *ltype = operandType (left);
8802 rtype = operandType (result);
8803 retype = getSpec (rtype);
8804 letype = getSpec (ltype);
8806 aopOp (left, ic, FALSE, FALSE);
8808 /* if left is rematerialisable and
8809 result is not bit variable type and
8810 the left is pointer to data space i.e
8811 lower 128 bytes of space */
8812 if (AOP_TYPE (left) == AOP_IMMD &&
8813 !IS_BITVAR (retype) &&
8814 !IS_BITVAR (letype) &&
8815 DCL_TYPE (ltype) == POINTER)
8817 genDataPointerGet (left, result, ic);
8821 /* if the value is already in a pointer register
8822 then don't need anything more */
8823 if (!AOP_INPREG (AOP (left)))
8825 /* otherwise get a free pointer register */
8827 preg = getFreePtr (ic, &aop, FALSE);
8828 emitcode ("mov", "%s,%s",
8830 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8834 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8836 freeAsmop (left, NULL, ic, TRUE);
8837 aopOp (result, ic, FALSE, FALSE);
8839 /* if bitfield then unpack the bits */
8840 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8841 genUnpackBits (result, rname, POINTER);
8844 /* we have can just get the values */
8845 int size = AOP_SIZE (result);
8850 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8853 emitcode ("mov", "a,@%s", rname);
8854 aopPut (AOP (result), "a", offset);
8858 sprintf (buffer, "@%s", rname);
8859 aopPut (AOP (result), buffer, offset);
8863 emitcode ("inc", "%s", rname);
8867 /* now some housekeeping stuff */
8870 /* we had to allocate for this iCode */
8871 if (pi) { /* post increment present */
8872 aopPut(AOP ( left ),rname,0);
8874 freeAsmop (NULL, aop, ic, TRUE);
8878 /* we did not allocate which means left
8879 already in a pointer register, then
8880 if size > 0 && this could be used again
8881 we have to point it back to where it
8883 if (AOP_SIZE (result) > 1 &&
8884 !OP_SYMBOL (left)->remat &&
8885 (OP_SYMBOL (left)->liveTo > ic->seq ||
8889 int size = AOP_SIZE (result) - 1;
8891 emitcode ("dec", "%s", rname);
8896 freeAsmop (result, NULL, ic, TRUE);
8897 if (pi) pi->generated = 1;
8900 /*-----------------------------------------------------------------*/
8901 /* genPagedPointerGet - emitcode for paged pointer fetch */
8902 /*-----------------------------------------------------------------*/
8904 genPagedPointerGet (operand * left,
8912 sym_link *rtype, *retype, *letype;
8914 rtype = operandType (result);
8915 retype = getSpec (rtype);
8916 letype = getSpec (operandType (left));
8917 aopOp (left, ic, FALSE, FALSE);
8919 /* if the value is already in a pointer register
8920 then don't need anything more */
8921 if (!AOP_INPREG (AOP (left)))
8923 /* otherwise get a free pointer register */
8925 preg = getFreePtr (ic, &aop, FALSE);
8926 emitcode ("mov", "%s,%s",
8928 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8932 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8934 freeAsmop (left, NULL, ic, TRUE);
8935 aopOp (result, ic, FALSE, FALSE);
8937 /* if bitfield then unpack the bits */
8938 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8939 genUnpackBits (result, rname, PPOINTER);
8942 /* we have can just get the values */
8943 int size = AOP_SIZE (result);
8949 emitcode ("movx", "a,@%s", rname);
8950 aopPut (AOP (result), "a", offset);
8955 emitcode ("inc", "%s", rname);
8959 /* now some housekeeping stuff */
8962 /* we had to allocate for this iCode */
8963 if (pi) aopPut ( AOP (left), rname, 0);
8964 freeAsmop (NULL, aop, ic, TRUE);
8968 /* we did not allocate which means left
8969 already in a pointer register, then
8970 if size > 0 && this could be used again
8971 we have to point it back to where it
8973 if (AOP_SIZE (result) > 1 &&
8974 !OP_SYMBOL (left)->remat &&
8975 (OP_SYMBOL (left)->liveTo > ic->seq ||
8979 int size = AOP_SIZE (result) - 1;
8981 emitcode ("dec", "%s", rname);
8986 freeAsmop (result, NULL, ic, TRUE);
8987 if (pi) pi->generated = 1;
8990 /*-----------------------------------------------------------------*/
8991 /* genFarPointerGet - gget value from far space */
8992 /*-----------------------------------------------------------------*/
8994 genFarPointerGet (operand * left,
8995 operand * result, iCode * ic, iCode *pi)
8997 int size, offset, dopi=1;
8998 sym_link *retype = getSpec (operandType (result));
8999 sym_link *letype = getSpec (operandType (left));
9000 D (emitcode (";", "genFarPointerGet");
9003 aopOp (left, ic, FALSE, FALSE);
9005 /* if the operand is already in dptr
9006 then we do nothing else we move the value to dptr */
9007 if (AOP_TYPE (left) != AOP_STR)
9009 /* if this is remateriazable */
9010 if (AOP_TYPE (left) == AOP_IMMD)
9012 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9016 /* we need to get it byte by byte */
9017 _startLazyDPSEvaluation ();
9018 if (AOP_TYPE (left) != AOP_DPTR)
9020 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9021 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9022 if (options.model == MODEL_FLAT24)
9023 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9027 /* We need to generate a load to DPTR indirect through DPTR. */
9028 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9030 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9031 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9032 if (options.model == MODEL_FLAT24)
9033 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9034 emitcode ("pop", "dph");
9035 emitcode ("pop", "dpl");
9038 _endLazyDPSEvaluation ();
9041 /* so dptr know contains the address */
9042 aopOp (result, ic, FALSE, TRUE);
9044 /* if bit then unpack */
9045 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9046 genUnpackBits (result, "dptr", FPOINTER);
9049 size = AOP_SIZE (result);
9052 _startLazyDPSEvaluation ();
9059 emitcode ("movx", "a,@dptr");
9060 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9061 emitcode ("inc", "dptr");
9063 aopPut (AOP (result), "a", offset++);
9065 _endLazyDPSEvaluation ();
9067 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9068 aopPut ( AOP (left), "dpl", 0);
9069 aopPut ( AOP (left), "dph", 1);
9070 if (options.model == MODEL_FLAT24)
9071 aopPut ( AOP (left), "dpx", 2);
9073 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9074 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9076 size = AOP_SIZE (result) - 1;
9077 while (size--) emitcode ("lcall","__decdptr");
9080 freeAsmop (left, NULL, ic, TRUE);
9081 freeAsmop (result, NULL, ic, TRUE);
9084 /*-----------------------------------------------------------------*/
9085 /* emitcodePointerGet - gget value from code space */
9086 /*-----------------------------------------------------------------*/
9088 emitcodePointerGet (operand * left,
9089 operand * result, iCode * ic, iCode *pi)
9091 int size, offset, dopi=1;
9092 sym_link *retype = getSpec (operandType (result));
9094 aopOp (left, ic, FALSE, FALSE);
9096 /* if the operand is already in dptr
9097 then we do nothing else we move the value to dptr */
9098 if (AOP_TYPE (left) != AOP_STR)
9100 /* if this is remateriazable */
9101 if (AOP_TYPE (left) == AOP_IMMD)
9103 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9106 { /* we need to get it byte by byte */
9107 _startLazyDPSEvaluation ();
9108 if (AOP_TYPE (left) != AOP_DPTR)
9110 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9111 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9112 if (options.model == MODEL_FLAT24)
9113 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9117 /* We need to generate a load to DPTR indirect through DPTR. */
9118 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9120 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9121 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9122 if (options.model == MODEL_FLAT24)
9123 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9124 emitcode ("pop", "dph");
9125 emitcode ("pop", "dpl");
9128 _endLazyDPSEvaluation ();
9131 /* so dptr know contains the address */
9132 aopOp (result, ic, FALSE, TRUE);
9134 /* if bit then unpack */
9135 if (IS_BITVAR (retype))
9136 genUnpackBits (result, "dptr", CPOINTER);
9139 size = AOP_SIZE (result);
9142 _startLazyDPSEvaluation ();
9148 emitcode ("clr", "a");
9149 emitcode ("movc", "a,@a+dptr");
9150 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9151 emitcode ("inc", "dptr");
9152 aopPut (AOP (result), "a", offset++);
9154 _endLazyDPSEvaluation ();
9156 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9157 aopPut ( AOP (left), "dpl", 0);
9158 aopPut ( AOP (left), "dph", 1);
9159 if (options.model == MODEL_FLAT24)
9160 aopPut ( AOP (left), "dpx", 2);
9162 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9163 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9165 size = AOP_SIZE (result) - 1;
9166 while (size--) emitcode ("lcall","__decdptr");
9169 freeAsmop (left, NULL, ic, TRUE);
9170 freeAsmop (result, NULL, ic, TRUE);
9173 /*-----------------------------------------------------------------*/
9174 /* genGenPointerGet - gget value from generic pointer space */
9175 /*-----------------------------------------------------------------*/
9177 genGenPointerGet (operand * left,
9178 operand * result, iCode * ic, iCode * pi)
9181 sym_link *retype = getSpec (operandType (result));
9182 sym_link *letype = getSpec (operandType (left));
9184 D (emitcode (";", "genGenPointerGet "); );
9186 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9188 /* if the operand is already in dptr
9189 then we do nothing else we move the value to dptr */
9190 if (AOP_TYPE (left) != AOP_STR)
9192 /* if this is remateriazable */
9193 if (AOP_TYPE (left) == AOP_IMMD)
9195 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9196 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9197 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9199 emitcode ("mov", "b,#%d", pointerCode (retype));
9202 { /* we need to get it byte by byte */
9203 _startLazyDPSEvaluation ();
9204 if (AOP(left)->type==AOP_DPTR2) {
9206 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9209 emitcode ("mov", "dpl,%s", l);
9210 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9213 emitcode ("mov", "dph,%s", l);
9214 if (options.model == MODEL_FLAT24) {
9215 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9218 emitcode ("mov", "dpx,%s", l);
9219 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9221 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9224 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9225 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9226 if (options.model == MODEL_FLAT24) {
9227 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9228 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9230 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9233 _endLazyDPSEvaluation ();
9236 /* so dptr know contains the address */
9237 aopOp (result, ic, FALSE, TRUE);
9239 /* if bit then unpack */
9240 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9241 genUnpackBits (result, "dptr", GPOINTER);
9244 size = AOP_SIZE (result);
9249 emitcode ("lcall", "__gptrget");
9250 aopPut (AOP (result), "a", offset++);
9251 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9252 emitcode ("inc", "dptr");
9256 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9257 aopPut ( AOP (left), "dpl", 0);
9258 aopPut ( AOP (left), "dph", 1);
9259 if (options.model == MODEL_FLAT24) {
9260 aopPut ( AOP (left), "dpx", 2);
9261 aopPut ( AOP (left), "b", 3);
9262 } else aopPut ( AOP (left), "b", 2);
9264 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9265 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9267 size = AOP_SIZE (result) - 1;
9268 while (size--) emitcode ("lcall","__decdptr");
9271 freeAsmop (left, NULL, ic, TRUE);
9272 freeAsmop (result, NULL, ic, TRUE);
9275 /*-----------------------------------------------------------------*/
9276 /* genPointerGet - generate code for pointer get */
9277 /*-----------------------------------------------------------------*/
9279 genPointerGet (iCode * ic, iCode *pi)
9281 operand *left, *result;
9282 sym_link *type, *etype;
9285 D (emitcode (";", "genPointerGet ");
9288 left = IC_LEFT (ic);
9289 result = IC_RESULT (ic);
9291 /* depending on the type of pointer we need to
9292 move it to the correct pointer register */
9293 type = operandType (left);
9294 etype = getSpec (type);
9295 /* if left is of type of pointer then it is simple */
9296 if (IS_PTR (type) && !IS_FUNC (type->next))
9297 p_type = DCL_TYPE (type);
9300 /* we have to go by the storage class */
9301 p_type = PTR_TYPE (SPEC_OCLS (etype));
9303 /* special case when cast remat */
9304 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9305 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9306 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9307 type = type = operandType (left);
9308 p_type = DCL_TYPE (type);
9310 /* now that we have the pointer type we assign
9311 the pointer values */
9317 genNearPointerGet (left, result, ic, pi);
9321 genPagedPointerGet (left, result, ic, pi);
9325 genFarPointerGet (left, result, ic, pi);
9329 emitcodePointerGet (left, result, ic, pi);
9333 genGenPointerGet (left, result, ic, pi);
9339 /*-----------------------------------------------------------------*/
9340 /* genPackBits - generates code for packed bit storage */
9341 /*-----------------------------------------------------------------*/
9343 genPackBits (sym_link * etype,
9345 char *rname, int p_type)
9353 blen = SPEC_BLEN (etype);
9354 bstr = SPEC_BSTR (etype);
9356 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9359 /* if the bit lenth is less than or */
9360 /* it exactly fits a byte then */
9361 if (SPEC_BLEN (etype) <= 8)
9363 shCount = SPEC_BSTR (etype);
9365 /* shift left acc */
9368 if (SPEC_BLEN (etype) < 8)
9369 { /* if smaller than a byte */
9375 emitcode ("mov", "b,a");
9376 emitcode ("mov", "a,@%s", rname);
9380 emitcode ("mov", "b,a");
9381 emitcode ("movx", "a,@dptr");
9385 emitcode ("push", "b");
9386 emitcode ("push", "acc");
9387 emitcode ("lcall", "__gptrget");
9388 emitcode ("pop", "b");
9392 emitcode ("anl", "a,#!constbyte", (unsigned char)
9393 ((unsigned char) (0xFF << (blen + bstr)) |
9394 (unsigned char) (0xFF >> (8 - bstr))));
9395 emitcode ("orl", "a,b");
9396 if (p_type == GPOINTER)
9397 emitcode ("pop", "b");
9404 emitcode ("mov", "@%s,a", rname);
9408 emitcode ("movx", "@dptr,a");
9412 emitcode ("lcall", "__gptrput");
9417 if (SPEC_BLEN (etype) <= 8)
9420 emitcode ("inc", "%s", rname);
9421 rLen = SPEC_BLEN (etype);
9423 /* now generate for lengths greater than one byte */
9427 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9439 emitcode ("mov", "@%s,a", rname);
9442 emitcode ("mov", "@%s,%s", rname, l);
9447 emitcode ("movx", "@dptr,a");
9452 emitcode ("lcall", "__gptrput");
9455 emitcode ("inc", "%s", rname);
9460 /* last last was not complete */
9463 /* save the byte & read byte */
9467 emitcode ("mov", "b,a");
9468 emitcode ("mov", "a,@%s", rname);
9472 emitcode ("mov", "b,a");
9473 emitcode ("movx", "a,@dptr");
9477 emitcode ("push", "b");
9478 emitcode ("push", "acc");
9479 emitcode ("lcall", "__gptrget");
9480 emitcode ("pop", "b");
9484 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9485 emitcode ("orl", "a,b");
9488 if (p_type == GPOINTER)
9489 emitcode ("pop", "b");
9495 emitcode ("mov", "@%s,a", rname);
9499 emitcode ("movx", "@dptr,a");
9503 emitcode ("lcall", "__gptrput");
9507 /*-----------------------------------------------------------------*/
9508 /* genDataPointerSet - remat pointer to data space */
9509 /*-----------------------------------------------------------------*/
9511 genDataPointerSet (operand * right,
9515 int size, offset = 0;
9516 char *l, buffer[256];
9518 aopOp (right, ic, FALSE, FALSE);
9520 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9521 size = AOP_SIZE (right);
9525 sprintf (buffer, "(%s + %d)", l + 1, offset);
9527 sprintf (buffer, "%s", l + 1);
9528 emitcode ("mov", "%s,%s", buffer,
9529 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9532 freeAsmop (right, NULL, ic, TRUE);
9533 freeAsmop (result, NULL, ic, TRUE);
9536 /*-----------------------------------------------------------------*/
9537 /* genNearPointerSet - emitcode for near pointer put */
9538 /*-----------------------------------------------------------------*/
9540 genNearPointerSet (operand * right,
9548 sym_link *retype, *letype;
9549 sym_link *ptype = operandType (result);
9551 retype = getSpec (operandType (right));
9552 letype = getSpec (ptype);
9554 aopOp (result, ic, FALSE, FALSE);
9556 /* if the result is rematerializable &
9557 in data space & not a bit variable */
9558 if (AOP_TYPE (result) == AOP_IMMD &&
9559 DCL_TYPE (ptype) == POINTER &&
9560 !IS_BITVAR (retype) &&
9561 !IS_BITVAR (letype))
9563 genDataPointerSet (right, result, ic);
9567 /* if the value is already in a pointer register
9568 then don't need anything more */
9569 if (!AOP_INPREG (AOP (result)))
9571 /* otherwise get a free pointer register */
9573 preg = getFreePtr (ic, &aop, FALSE);
9574 emitcode ("mov", "%s,%s",
9576 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9580 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9582 aopOp (right, ic, FALSE, FALSE);
9584 /* if bitfield then unpack the bits */
9585 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9586 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9589 /* we have can just get the values */
9590 int size = AOP_SIZE (right);
9595 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9599 emitcode ("mov", "@%s,a", rname);
9602 emitcode ("mov", "@%s,%s", rname, l);
9604 emitcode ("inc", "%s", rname);
9609 /* now some housekeeping stuff */
9612 /* we had to allocate for this iCode */
9613 if (pi) aopPut (AOP (result),rname,0);
9614 freeAsmop (NULL, aop, ic, TRUE);
9618 /* we did not allocate which means left
9619 already in a pointer register, then
9620 if size > 0 && this could be used again
9621 we have to point it back to where it
9623 if (AOP_SIZE (right) > 1 &&
9624 !OP_SYMBOL (result)->remat &&
9625 (OP_SYMBOL (result)->liveTo > ic->seq ||
9629 int size = AOP_SIZE (right) - 1;
9631 emitcode ("dec", "%s", rname);
9636 if (pi) pi->generated = 1;
9637 freeAsmop (result, NULL, ic, TRUE);
9638 freeAsmop (right, NULL, ic, TRUE);
9643 /*-----------------------------------------------------------------*/
9644 /* genPagedPointerSet - emitcode for Paged pointer put */
9645 /*-----------------------------------------------------------------*/
9647 genPagedPointerSet (operand * right,
9655 sym_link *retype, *letype;
9657 retype = getSpec (operandType (right));
9658 letype = getSpec (operandType (result));
9660 aopOp (result, ic, FALSE, FALSE);
9662 /* if the value is already in a pointer register
9663 then don't need anything more */
9664 if (!AOP_INPREG (AOP (result)))
9666 /* otherwise get a free pointer register */
9668 preg = getFreePtr (ic, &aop, FALSE);
9669 emitcode ("mov", "%s,%s",
9671 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9675 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9677 aopOp (right, ic, FALSE, FALSE);
9679 /* if bitfield then unpack the bits */
9680 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9681 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9684 /* we have can just get the values */
9685 int size = AOP_SIZE (right);
9690 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9693 emitcode ("movx", "@%s,a", rname);
9696 emitcode ("inc", "%s", rname);
9702 /* now some housekeeping stuff */
9705 if (pi) aopPut (AOP (result),rname,0);
9706 /* we had to allocate for this iCode */
9707 freeAsmop (NULL, aop, ic, TRUE);
9711 /* we did not allocate which means left
9712 already in a pointer register, then
9713 if size > 0 && this could be used again
9714 we have to point it back to where it
9716 if (AOP_SIZE (right) > 1 &&
9717 !OP_SYMBOL (result)->remat &&
9718 (OP_SYMBOL (result)->liveTo > ic->seq ||
9722 int size = AOP_SIZE (right) - 1;
9724 emitcode ("dec", "%s", rname);
9729 if (pi) pi->generated = 1;
9730 freeAsmop (result, NULL, ic, TRUE);
9731 freeAsmop (right, NULL, ic, TRUE);
9736 /*-----------------------------------------------------------------*/
9737 /* genFarPointerSet - set value from far space */
9738 /*-----------------------------------------------------------------*/
9740 genFarPointerSet (operand * right,
9741 operand * result, iCode * ic, iCode *pi)
9743 int size, offset, dopi=1;
9744 sym_link *retype = getSpec (operandType (right));
9745 sym_link *letype = getSpec (operandType (result));
9747 aopOp (result, ic, FALSE, FALSE);
9749 /* if the operand is already in dptr
9750 then we do nothing else we move the value to dptr */
9751 if (AOP_TYPE (result) != AOP_STR)
9753 /* if this is remateriazable */
9754 if (AOP_TYPE (result) == AOP_IMMD)
9755 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9758 /* we need to get it byte by byte */
9759 _startLazyDPSEvaluation ();
9760 if (AOP_TYPE (result) != AOP_DPTR)
9762 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9763 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9764 if (options.model == MODEL_FLAT24)
9765 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9769 /* We need to generate a load to DPTR indirect through DPTR. */
9770 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9772 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9773 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9774 if (options.model == MODEL_FLAT24)
9775 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9776 emitcode ("pop", "dph");
9777 emitcode ("pop", "dpl");
9780 _endLazyDPSEvaluation ();
9783 /* so dptr know contains the address */
9784 aopOp (right, ic, FALSE, TRUE);
9786 /* if bit then unpack */
9787 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9788 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9791 size = AOP_SIZE (right);
9794 _startLazyDPSEvaluation ();
9797 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9803 emitcode ("movx", "@dptr,a");
9804 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9805 emitcode ("inc", "dptr");
9807 _endLazyDPSEvaluation ();
9810 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9811 aopPut (AOP(result),"dpl",0);
9812 aopPut (AOP(result),"dph",1);
9813 if (options.model == MODEL_FLAT24)
9814 aopPut (AOP(result),"dpx",2);
9816 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9817 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9819 size = AOP_SIZE (right) - 1;
9820 while (size--) emitcode ("lcall","__decdptr");
9822 freeAsmop (result, NULL, ic, TRUE);
9823 freeAsmop (right, NULL, ic, TRUE);
9826 /*-----------------------------------------------------------------*/
9827 /* genGenPointerSet - set value from generic pointer space */
9828 /*-----------------------------------------------------------------*/
9830 genGenPointerSet (operand * right,
9831 operand * result, iCode * ic, iCode *pi)
9834 sym_link *retype = getSpec (operandType (right));
9835 sym_link *letype = getSpec (operandType (result));
9837 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9839 /* if the operand is already in dptr
9840 then we do nothing else we move the value to dptr */
9841 if (AOP_TYPE (result) != AOP_STR)
9843 _startLazyDPSEvaluation ();
9844 /* if this is remateriazable */
9845 if (AOP_TYPE (result) == AOP_IMMD)
9847 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9848 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9849 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9851 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9854 { /* we need to get it byte by byte */
9855 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9856 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9857 if (options.model == MODEL_FLAT24) {
9858 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9859 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9861 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9864 _endLazyDPSEvaluation ();
9866 /* so dptr know contains the address */
9867 aopOp (right, ic, FALSE, TRUE);
9869 /* if bit then unpack */
9870 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9871 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9874 size = AOP_SIZE (right);
9877 _startLazyDPSEvaluation ();
9880 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9886 emitcode ("lcall", "__gptrput");
9887 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9888 emitcode ("inc", "dptr");
9890 _endLazyDPSEvaluation ();
9893 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9894 aopPut (AOP(result),"dpl",0);
9895 aopPut (AOP(result),"dph",1);
9896 if (options.model == MODEL_FLAT24) {
9897 aopPut (AOP(result),"dpx",2);
9898 aopPut (AOP(result),"b",3);
9900 aopPut (AOP(result),"b",2);
9903 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9904 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9906 size = AOP_SIZE (right) - 1;
9907 while (size--) emitcode ("lcall","__decdptr");
9909 freeAsmop (result, NULL, ic, TRUE);
9910 freeAsmop (right, NULL, ic, TRUE);
9913 /*-----------------------------------------------------------------*/
9914 /* genPointerSet - stores the value into a pointer location */
9915 /*-----------------------------------------------------------------*/
9917 genPointerSet (iCode * ic, iCode *pi)
9919 operand *right, *result;
9920 sym_link *type, *etype;
9923 D (emitcode (";", "genPointerSet ");
9926 right = IC_RIGHT (ic);
9927 result = IC_RESULT (ic);
9929 /* depending on the type of pointer we need to
9930 move it to the correct pointer register */
9931 type = operandType (result);
9932 etype = getSpec (type);
9933 /* if left is of type of pointer then it is simple */
9934 if (IS_PTR (type) && !IS_FUNC (type->next))
9936 p_type = DCL_TYPE (type);
9940 /* we have to go by the storage class */
9941 p_type = PTR_TYPE (SPEC_OCLS (etype));
9943 /* special case when cast remat */
9944 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9945 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9946 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9947 type = type = operandType (result);
9948 p_type = DCL_TYPE (type);
9951 /* now that we have the pointer type we assign
9952 the pointer values */
9958 genNearPointerSet (right, result, ic, pi);
9962 genPagedPointerSet (right, result, ic, pi);
9966 genFarPointerSet (right, result, ic, pi);
9970 genGenPointerSet (right, result, ic, pi);
9976 /*-----------------------------------------------------------------*/
9977 /* genIfx - generate code for Ifx statement */
9978 /*-----------------------------------------------------------------*/
9980 genIfx (iCode * ic, iCode * popIc)
9982 operand *cond = IC_COND (ic);
9985 D (emitcode (";", "genIfx "););
9987 aopOp (cond, ic, FALSE, FALSE);
9989 /* get the value into acc */
9990 if (AOP_TYPE (cond) != AOP_CRY)
9994 /* the result is now in the accumulator */
9995 freeAsmop (cond, NULL, ic, TRUE);
9997 /* if there was something to be popped then do it */
10001 /* if the condition is a bit variable */
10002 if (isbit && IS_ITEMP (cond) &&
10004 genIfxJump (ic, SPIL_LOC (cond)->rname);
10005 else if (isbit && !IS_ITEMP (cond))
10006 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10008 genIfxJump (ic, "a");
10013 /*-----------------------------------------------------------------*/
10014 /* genAddrOf - generates code for address of */
10015 /*-----------------------------------------------------------------*/
10017 genAddrOf (iCode * ic)
10019 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10022 D (emitcode (";", "genAddrOf ");
10025 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10027 /* if the operand is on the stack then we
10028 need to get the stack offset of this
10030 if (sym->onStack) {
10032 /* if 10 bit stack */
10033 if (options.stack10bit) {
10035 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10036 /* if it has an offset then we need to compute it */
10037 emitcode ("subb", "a,#!constbyte",
10038 -((sym->stack < 0) ?
10039 ((short) (sym->stack - _G.nRegsSaved)) :
10040 ((short) sym->stack)) & 0xff);
10041 emitcode ("mov","b,a");
10042 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10043 ((short) (sym->stack - _G.nRegsSaved)) :
10044 ((short) sym->stack)) >> 8) & 0xff);
10046 emitcode ("mov", "a,_bpx");
10047 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10048 ((char) (sym->stack - _G.nRegsSaved)) :
10049 ((char) sym->stack )) & 0xff);
10050 emitcode ("mov", "b,a");
10051 emitcode ("mov", "a,_bpx+1");
10052 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10053 ((short) (sym->stack - _G.nRegsSaved)) :
10054 ((short) sym->stack )) >> 8) & 0xff);
10055 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10056 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10057 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10059 /* we can just move _bp */
10060 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10061 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10062 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10065 /* if it has an offset then we need to compute it */
10067 emitcode ("mov", "a,_bp");
10068 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10069 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10071 /* we can just move _bp */
10072 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10074 /* fill the result with zero */
10075 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10078 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10080 "*** warning: pointer to stack var truncated.\n");
10085 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10091 /* object not on stack then we need the name */
10092 size = AOP_SIZE (IC_RESULT (ic));
10097 char s[SDCC_NAME_MAX];
10101 tsprintf(s,"!his",sym->rname);
10104 tsprintf(s,"!hihis",sym->rname);
10107 tsprintf(s,"!hihihis",sym->rname);
10109 default: /* should not need this (just in case) */
10110 sprintf (s, "#(%s >> %d)",
10115 sprintf (s, "#%s", sym->rname);
10116 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10120 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10124 /*-----------------------------------------------------------------*/
10125 /* genArrayInit - generates code for address of */
10126 /*-----------------------------------------------------------------*/
10128 genArrayInit (iCode * ic)
10130 literalList *iLoop;
10132 int elementSize = 0, eIndex;
10133 unsigned val, lastVal;
10135 operand *left=IC_LEFT(ic);
10137 D (emitcode (";", "genArrayInit "););
10139 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10141 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10143 // Load immediate value into DPTR.
10144 emitcode("mov", "dptr, %s",
10145 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10147 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10150 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10151 "Unexpected operand to genArrayInit.\n");
10154 // a regression because of SDCCcse.c:1.52
10155 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10156 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10157 if (options.model == MODEL_FLAT24)
10158 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10162 type = operandType(IC_LEFT(ic));
10164 if (type && type->next)
10166 elementSize = getSize(type->next);
10170 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10171 "can't determine element size in genArrayInit.\n");
10175 iLoop = IC_ARRAYILIST(ic);
10180 bool firstpass = TRUE;
10182 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10183 iLoop->count, (int)iLoop->literalValue, elementSize);
10189 symbol *tlbl = NULL;
10191 count = ix > 256 ? 256 : ix;
10195 tlbl = newiTempLabel (NULL);
10196 if (firstpass || (count & 0xff))
10198 emitcode("mov", "b, #!constbyte", count & 0xff);
10201 emitcode ("", "!tlabeldef", tlbl->key + 100);
10206 for (eIndex = 0; eIndex < elementSize; eIndex++)
10208 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10209 if (val != lastVal)
10211 emitcode("mov", "a, #!constbyte", val);
10215 emitcode("movx", "@dptr, a");
10216 emitcode("inc", "dptr");
10221 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10227 iLoop = iLoop->next;
10230 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10233 /*-----------------------------------------------------------------*/
10234 /* genFarFarAssign - assignment when both are in far space */
10235 /*-----------------------------------------------------------------*/
10237 genFarFarAssign (operand * result, operand * right, iCode * ic)
10239 int size = AOP_SIZE (right);
10241 symbol *rSym = NULL;
10245 /* quick & easy case. */
10246 D(emitcode(";","genFarFarAssign (1 byte case)"););
10247 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10248 freeAsmop (right, NULL, ic, FALSE);
10249 /* now assign DPTR to result */
10251 aopOp(result, ic, FALSE, FALSE);
10253 aopPut(AOP(result), "a", 0);
10254 freeAsmop(result, NULL, ic, FALSE);
10258 /* See if we've got an underlying symbol to abuse. */
10259 if (IS_SYMOP(result) && OP_SYMBOL(result))
10261 if (IS_TRUE_SYMOP(result))
10263 rSym = OP_SYMBOL(result);
10265 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10267 rSym = OP_SYMBOL(result)->usl.spillLoc;
10271 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10273 /* We can use the '390 auto-toggle feature to good effect here. */
10275 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10276 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10277 emitcode ("mov", "dptr,#%s", rSym->rname);
10278 /* DP2 = result, DP1 = right, DP1 is current. */
10281 emitcode("movx", "a,@dptr");
10282 emitcode("movx", "@dptr,a");
10285 emitcode("inc", "dptr");
10286 emitcode("inc", "dptr");
10289 emitcode("mov", "dps,#0");
10290 freeAsmop (right, NULL, ic, FALSE);
10292 some alternative code for processors without auto-toggle
10293 no time to test now, so later well put in...kpb
10294 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10295 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10296 emitcode ("mov", "dptr,#%s", rSym->rname);
10297 /* DP2 = result, DP1 = right, DP1 is current. */
10301 emitcode("movx", "a,@dptr");
10303 emitcode("inc", "dptr");
10304 emitcode("inc", "dps");
10305 emitcode("movx", "@dptr,a");
10307 emitcode("inc", "dptr");
10308 emitcode("inc", "dps");
10310 emitcode("mov", "dps,#0");
10311 freeAsmop (right, NULL, ic, FALSE);
10316 D (emitcode (";", "genFarFarAssign"););
10317 aopOp (result, ic, TRUE, TRUE);
10319 _startLazyDPSEvaluation ();
10323 aopPut (AOP (result),
10324 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10327 _endLazyDPSEvaluation ();
10328 freeAsmop (result, NULL, ic, FALSE);
10329 freeAsmop (right, NULL, ic, FALSE);
10333 /*-----------------------------------------------------------------*/
10334 /* genAssign - generate code for assignment */
10335 /*-----------------------------------------------------------------*/
10337 genAssign (iCode * ic)
10339 operand *result, *right;
10341 unsigned long lit = 0L;
10343 D (emitcode (";", "genAssign ");
10346 result = IC_RESULT (ic);
10347 right = IC_RIGHT (ic);
10349 /* if they are the same */
10350 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10353 aopOp (right, ic, FALSE, FALSE);
10355 emitcode (";", "genAssign: resultIsFar = %s",
10356 isOperandInFarSpace (result) ?
10359 /* special case both in far space */
10360 if ((AOP_TYPE (right) == AOP_DPTR ||
10361 AOP_TYPE (right) == AOP_DPTR2) &&
10362 /* IS_TRUE_SYMOP(result) && */
10363 isOperandInFarSpace (result))
10365 genFarFarAssign (result, right, ic);
10369 aopOp (result, ic, TRUE, FALSE);
10371 /* if they are the same registers */
10372 if (sameRegs (AOP (right), AOP (result)))
10375 /* if the result is a bit */
10376 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10378 /* if the right size is a literal then
10379 we know what the value is */
10380 if (AOP_TYPE (right) == AOP_LIT)
10382 if (((int) operandLitValue (right)))
10383 aopPut (AOP (result), one, 0);
10385 aopPut (AOP (result), zero, 0);
10389 /* the right is also a bit variable */
10390 if (AOP_TYPE (right) == AOP_CRY)
10392 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10393 aopPut (AOP (result), "c", 0);
10397 /* we need to or */
10399 aopPut (AOP (result), "a", 0);
10403 /* bit variables done */
10405 size = AOP_SIZE (result);
10407 if (AOP_TYPE (right) == AOP_LIT)
10408 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10411 (AOP_TYPE (result) != AOP_REG) &&
10412 (AOP_TYPE (right) == AOP_LIT) &&
10413 !IS_FLOAT (operandType (right)))
10415 _startLazyDPSEvaluation ();
10416 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10418 aopPut (AOP (result),
10419 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10424 /* And now fill the rest with zeros. */
10427 emitcode ("clr", "a");
10431 aopPut (AOP (result), "a", offset++);
10433 _endLazyDPSEvaluation ();
10437 _startLazyDPSEvaluation ();
10440 aopPut (AOP (result),
10441 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10445 _endLazyDPSEvaluation ();
10449 freeAsmop (right, NULL, ic, FALSE);
10450 freeAsmop (result, NULL, ic, TRUE);
10453 /*-----------------------------------------------------------------*/
10454 /* genJumpTab - generates code for jump table */
10455 /*-----------------------------------------------------------------*/
10457 genJumpTab (iCode * ic)
10462 D (emitcode (";", "genJumpTab ");
10465 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10466 /* get the condition into accumulator */
10467 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10469 /* multiply by four! */
10470 emitcode ("add", "a,acc");
10471 emitcode ("add", "a,acc");
10472 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10474 jtab = newiTempLabel (NULL);
10475 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10476 emitcode ("jmp", "@a+dptr");
10477 emitcode ("", "!tlabeldef", jtab->key + 100);
10478 /* now generate the jump labels */
10479 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10480 jtab = setNextItem (IC_JTLABELS (ic)))
10481 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10485 /*-----------------------------------------------------------------*/
10486 /* genCast - gen code for casting */
10487 /*-----------------------------------------------------------------*/
10489 genCast (iCode * ic)
10491 operand *result = IC_RESULT (ic);
10492 sym_link *ctype = operandType (IC_LEFT (ic));
10493 sym_link *rtype = operandType (IC_RIGHT (ic));
10494 operand *right = IC_RIGHT (ic);
10497 D (emitcode (";", "genCast ");
10500 /* if they are equivalent then do nothing */
10501 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10504 aopOp (right, ic, FALSE, FALSE);
10505 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10507 /* if the result is a bit */
10508 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10509 if (IS_BITVAR(OP_SYMBOL(result)->type))
10511 /* if the right size is a literal then
10512 we know what the value is */
10513 if (AOP_TYPE (right) == AOP_LIT)
10515 if (((int) operandLitValue (right)))
10516 aopPut (AOP (result), one, 0);
10518 aopPut (AOP (result), zero, 0);
10523 /* the right is also a bit variable */
10524 if (AOP_TYPE (right) == AOP_CRY)
10526 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10527 aopPut (AOP (result), "c", 0);
10531 /* we need to or */
10533 aopPut (AOP (result), "a", 0);
10537 /* if they are the same size : or less */
10538 if (AOP_SIZE (result) <= AOP_SIZE (right))
10541 /* if they are in the same place */
10542 if (sameRegs (AOP (right), AOP (result)))
10545 /* if they in different places then copy */
10546 size = AOP_SIZE (result);
10548 _startLazyDPSEvaluation ();
10551 aopPut (AOP (result),
10552 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10556 _endLazyDPSEvaluation ();
10561 /* if the result is of type pointer */
10562 if (IS_PTR (ctype))
10566 sym_link *type = operandType (right);
10568 /* pointer to generic pointer */
10569 if (IS_GENPTR (ctype))
10575 p_type = DCL_TYPE (type);
10579 #if OLD_CAST_BEHAVIOR
10580 /* KV: we are converting a non-pointer type to
10581 * a generic pointer. This (ifdef'd out) code
10582 * says that the resulting generic pointer
10583 * should have the same class as the storage
10584 * location of the non-pointer variable.
10586 * For example, converting an int (which happens
10587 * to be stored in DATA space) to a pointer results
10588 * in a DATA generic pointer; if the original int
10589 * in XDATA space, so will be the resulting pointer.
10591 * I don't like that behavior, and thus this change:
10592 * all such conversions will be forced to XDATA and
10593 * throw a warning. If you want some non-XDATA
10594 * type, or you want to suppress the warning, you
10595 * must go through an intermediate cast, like so:
10597 * char _generic *gp = (char _xdata *)(intVar);
10599 sym_link *etype = getSpec (type);
10601 /* we have to go by the storage class */
10602 if (SPEC_OCLS (etype) != generic)
10604 p_type = PTR_TYPE (SPEC_OCLS (etype));
10609 /* Converting unknown class (i.e. register variable)
10610 * to generic pointer. This is not good, but
10611 * we'll make a guess (and throw a warning).
10614 werror (W_INT_TO_GEN_PTR_CAST);
10618 /* the first two bytes are known */
10619 size = GPTRSIZE - 1;
10621 _startLazyDPSEvaluation ();
10624 aopPut (AOP (result),
10625 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10629 _endLazyDPSEvaluation ();
10631 /* the last byte depending on type */
10649 /* this should never happen */
10650 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10651 "got unknown pointer type");
10654 aopPut (AOP (result), l, GPTRSIZE - 1);
10658 /* just copy the pointers */
10659 size = AOP_SIZE (result);
10661 _startLazyDPSEvaluation ();
10664 aopPut (AOP (result),
10665 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10669 _endLazyDPSEvaluation ();
10673 /* so we now know that the size of destination is greater
10674 than the size of the source */
10675 /* we move to result for the size of source */
10676 size = AOP_SIZE (right);
10678 _startLazyDPSEvaluation ();
10681 aopPut (AOP (result),
10682 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10686 _endLazyDPSEvaluation ();
10688 /* now depending on the sign of the source && destination */
10689 size = AOP_SIZE (result) - AOP_SIZE (right);
10690 /* if unsigned or not an integral type */
10691 /* also, if the source is a bit, we don't need to sign extend, because
10692 * it can't possibly have set the sign bit.
10694 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10698 aopPut (AOP (result), zero, offset++);
10703 /* we need to extend the sign :{ */
10704 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10705 FALSE, FALSE, TRUE);
10707 emitcode ("rlc", "a");
10708 emitcode ("subb", "a,acc");
10710 aopPut (AOP (result), "a", offset++);
10713 /* we are done hurray !!!! */
10716 freeAsmop (right, NULL, ic, TRUE);
10717 freeAsmop (result, NULL, ic, TRUE);
10721 /*-----------------------------------------------------------------*/
10722 /* genDjnz - generate decrement & jump if not zero instrucion */
10723 /*-----------------------------------------------------------------*/
10725 genDjnz (iCode * ic, iCode * ifx)
10727 symbol *lbl, *lbl1;
10731 /* if the if condition has a false label
10732 then we cannot save */
10733 if (IC_FALSE (ifx))
10736 /* if the minus is not of the form
10738 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10739 !IS_OP_LITERAL (IC_RIGHT (ic)))
10742 if (operandLitValue (IC_RIGHT (ic)) != 1)
10745 /* if the size of this greater than one then no
10747 if (getSize (operandType (IC_RESULT (ic))) > 1)
10750 /* otherwise we can save BIG */
10751 D(emitcode(";", "genDjnz"););
10753 lbl = newiTempLabel (NULL);
10754 lbl1 = newiTempLabel (NULL);
10756 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10758 if (AOP_NEEDSACC(IC_RESULT(ic)))
10760 /* If the result is accessed indirectly via
10761 * the accumulator, we must explicitly write
10762 * it back after the decrement.
10764 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10766 if (strcmp(rByte, "a"))
10768 /* Something is hopelessly wrong */
10769 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10770 __FILE__, __LINE__);
10771 /* We can just give up; the generated code will be inefficient,
10772 * but what the hey.
10774 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10777 emitcode ("dec", "%s", rByte);
10778 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10779 emitcode ("jnz", "!tlabel", lbl->key + 100);
10781 else if (IS_AOP_PREG (IC_RESULT (ic)))
10783 emitcode ("dec", "%s",
10784 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10785 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10786 emitcode ("jnz", "!tlabel", lbl->key + 100);
10790 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10793 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10794 emitcode ("", "!tlabeldef", lbl->key + 100);
10795 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10796 emitcode ("", "!tlabeldef", lbl1->key + 100);
10798 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10799 ifx->generated = 1;
10803 /*-----------------------------------------------------------------*/
10804 /* genReceive - generate code for a receive iCode */
10805 /*-----------------------------------------------------------------*/
10807 genReceive (iCode * ic)
10810 D (emitcode (";", "genReceive ");
10813 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10814 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10815 IS_TRUE_SYMOP (IC_RESULT (ic))))
10817 int size = getSize (operandType (IC_RESULT (ic)));
10818 int offset = fReturnSizeDS390 - size;
10821 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10822 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10825 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10826 size = AOP_SIZE (IC_RESULT (ic));
10830 emitcode ("pop", "acc");
10831 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10838 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10840 assignResultValue (IC_RESULT (ic));
10843 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10846 /*-----------------------------------------------------------------*/
10847 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10848 /*-----------------------------------------------------------------*/
10849 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10851 operand *from , *to , *count;
10856 /* we know it has to be 3 parameters */
10857 assert (nparms == 3);
10859 rsave = newBitVect(16);
10860 /* save DPTR if it needs to be saved */
10861 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10862 if (bitVectBitValue(ic->rMask,i))
10863 rsave = bitVectSetBit(rsave,i);
10865 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10866 ds390_rUmaskForOp (IC_RESULT(ic))));
10873 aopOp (from, ic->next, FALSE, FALSE);
10875 /* get from into DPTR1 */
10876 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10877 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10878 if (options.model == MODEL_FLAT24) {
10879 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10882 freeAsmop (from, NULL, ic, FALSE);
10883 aopOp (to, ic, FALSE, FALSE);
10884 /* get "to" into DPTR */
10885 /* if the operand is already in dptr
10886 then we do nothing else we move the value to dptr */
10887 if (AOP_TYPE (to) != AOP_STR) {
10888 /* if already in DPTR then we need to push */
10889 if (AOP_TYPE(to) == AOP_DPTR) {
10890 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10891 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10892 if (options.model == MODEL_FLAT24)
10893 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10894 emitcode ("pop", "dph");
10895 emitcode ("pop", "dpl");
10897 _startLazyDPSEvaluation ();
10898 /* if this is remateriazable */
10899 if (AOP_TYPE (to) == AOP_IMMD) {
10900 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10901 } else { /* we need to get it byte by byte */
10902 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10903 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10904 if (options.model == MODEL_FLAT24) {
10905 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10908 _endLazyDPSEvaluation ();
10911 freeAsmop (to, NULL, ic, FALSE);
10913 aopOp (count, ic->next->next, FALSE,FALSE);
10914 lbl =newiTempLabel(NULL);
10916 /* now for the actual copy */
10917 if (AOP_TYPE(count) == AOP_LIT &&
10918 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10919 emitcode (";","OH JOY auto increment with djnz (very fast)");
10920 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10921 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10922 emitcode ("","!tlabeldef",lbl->key+100);
10924 emitcode ("clr","a");
10925 emitcode ("movc", "a,@a+dptr");
10927 emitcode ("movx", "a,@dptr");
10928 emitcode ("movx", "@dptr,a");
10929 emitcode ("inc", "dptr");
10930 emitcode ("inc", "dptr");
10931 emitcode ("djnz","b,!tlabel",lbl->key+100);
10933 symbol *lbl1 = newiTempLabel(NULL);
10935 emitcode (";"," Auto increment but no djnz");
10936 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10937 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10938 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10939 emitcode ("","!tlabeldef",lbl->key+100);
10941 emitcode ("clr","a");
10942 emitcode ("movc", "a,@a+dptr");
10944 emitcode ("movx", "a,@dptr");
10945 emitcode ("movx", "@dptr,a");
10946 emitcode ("inc", "dptr");
10947 emitcode ("inc", "dptr");
10948 emitcode ("mov","a,b");
10949 emitcode ("orl","a,_ap");
10950 emitcode ("jz","!tlabel",lbl1->key+100);
10951 emitcode ("mov","a,_ap");
10952 emitcode ("add","a,#!constbyte",0xFF);
10953 emitcode ("mov","_ap,a");
10954 emitcode ("mov","a,b");
10955 emitcode ("addc","a,#!constbyte",0xFF);
10956 emitcode ("mov","b,a");
10957 emitcode ("sjmp","!tlabel",lbl->key+100);
10958 emitcode ("","!tlabeldef",lbl1->key+100);
10960 emitcode ("mov", "dps,#0");
10961 freeAsmop (count, NULL, ic, FALSE);
10962 unsavermask(rsave);
10966 /*-----------------------------------------------------------------*/
10967 /* genMemsetX - gencode for memSetX data */
10968 /*-----------------------------------------------------------------*/
10969 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10971 operand *to , *val , *count;
10975 bitVect *rsave = NULL;
10977 /* we know it has to be 3 parameters */
10978 assert (nparms == 3);
10984 /* save DPTR if it needs to be saved */
10985 rsave = newBitVect(16);
10986 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10987 if (bitVectBitValue(ic->rMask,i))
10988 rsave = bitVectSetBit(rsave,i);
10990 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10991 ds390_rUmaskForOp (IC_RESULT(ic))));
10994 aopOp (to, ic, FALSE, FALSE);
10995 /* get "to" into DPTR */
10996 /* if the operand is already in dptr
10997 then we do nothing else we move the value to dptr */
10998 if (AOP_TYPE (to) != AOP_STR) {
10999 /* if already in DPTR then we need to push */
11000 if (AOP_TYPE(to) == AOP_DPTR) {
11001 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11002 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11003 if (options.model == MODEL_FLAT24)
11004 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11005 emitcode ("pop", "dph");
11006 emitcode ("pop", "dpl");
11008 _startLazyDPSEvaluation ();
11009 /* if this is remateriazable */
11010 if (AOP_TYPE (to) == AOP_IMMD) {
11011 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11012 } else { /* we need to get it byte by byte */
11013 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11014 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11015 if (options.model == MODEL_FLAT24) {
11016 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11019 _endLazyDPSEvaluation ();
11022 freeAsmop (to, NULL, ic, FALSE);
11024 aopOp (val, ic->next->next, FALSE,FALSE);
11025 aopOp (count, ic->next->next, FALSE,FALSE);
11026 lbl =newiTempLabel(NULL);
11027 /* now for the actual copy */
11028 if (AOP_TYPE(count) == AOP_LIT &&
11029 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11030 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11031 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11033 emitcode ("","!tlabeldef",lbl->key+100);
11034 emitcode ("movx", "@dptr,a");
11035 emitcode ("inc", "dptr");
11036 emitcode ("djnz","b,!tlabel",lbl->key+100);
11038 symbol *lbl1 = newiTempLabel(NULL);
11040 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11041 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11042 emitcode ("","!tlabeldef",lbl->key+100);
11043 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11045 emitcode ("movx", "a,@dptr");
11046 emitcode ("inc", "dptr");
11047 emitcode ("mov","a,b");
11048 emitcode ("orl","a,_ap");
11049 emitcode ("jz","!tlabel",lbl1->key+100);
11050 emitcode ("mov","a,_ap");
11051 emitcode ("add","a,#!constbyte",0xFF);
11052 emitcode ("mov","_ap,a");
11053 emitcode ("mov","a,b");
11054 emitcode ("addc","a,#!constbyte",0xFF);
11055 emitcode ("mov","b,a");
11056 emitcode ("sjmp","!tlabel",lbl->key+100);
11057 emitcode ("","!tlabeldef",lbl1->key+100);
11059 freeAsmop (count, NULL, ic, FALSE);
11060 unsavermask(rsave);
11063 /*-----------------------------------------------------------------*/
11064 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11065 /*-----------------------------------------------------------------*/
11066 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11069 operand *pnum, *result;
11072 assert (nparms==1);
11073 /* save registers that need to be saved */
11074 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11075 ds390_rUmaskForOp (IC_RESULT(ic))));
11078 aopOp (pnum, ic, FALSE, FALSE);
11079 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11080 freeAsmop (pnum, NULL, ic, FALSE);
11081 emitcode ("lcall","NatLib_LoadPrimitive");
11082 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11083 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11084 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11085 for (i = (size-1) ; i >= 0 ; i-- ) {
11086 emitcode ("push","a%s",javaRet[i]);
11088 for (i=0; i < size ; i++ ) {
11089 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11092 for (i = 0 ; i < size ; i++ ) {
11093 aopPut(AOP(result),javaRet[i],i);
11096 freeAsmop (result, NULL, ic, FALSE);
11097 unsavermask(rsave);
11100 /*-----------------------------------------------------------------*/
11101 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11102 /*-----------------------------------------------------------------*/
11103 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11106 operand *pnum, *result;
11110 assert (nparms==1);
11111 /* save registers that need to be saved */
11112 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11113 ds390_rUmaskForOp (IC_RESULT(ic))));
11116 aopOp (pnum, ic, FALSE, FALSE);
11117 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11118 freeAsmop (pnum, NULL, ic, FALSE);
11119 emitcode ("lcall","NatLib_LoadPointer");
11120 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11121 if (AOP_TYPE(result)!=AOP_STR) {
11122 for (i = 0 ; i < size ; i++ ) {
11123 aopPut(AOP(result),fReturn[i],i);
11126 freeAsmop (result, NULL, ic, FALSE);
11127 unsavermask(rsave);
11130 /*-----------------------------------------------------------------*/
11131 /* genNatLibInstallStateBlock - */
11132 /*-----------------------------------------------------------------*/
11133 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11134 operand **parms, const char *name)
11137 operand *psb, *handle;
11138 assert (nparms==2);
11140 /* save registers that need to be saved */
11141 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11142 ds390_rUmaskForOp (IC_RESULT(ic))));
11146 /* put pointer to state block into DPTR1 */
11147 aopOp (psb, ic, FALSE, FALSE);
11148 if (AOP_TYPE (psb) == AOP_IMMD) {
11149 emitcode ("mov","dps,#1");
11150 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11151 emitcode ("mov","dps,#0");
11153 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11154 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11155 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11157 freeAsmop (psb, NULL, ic, FALSE);
11159 /* put libraryID into DPTR */
11160 emitcode ("mov","dptr,#LibraryID");
11162 /* put handle into r3:r2 */
11163 aopOp (handle, ic, FALSE, FALSE);
11164 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11165 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11166 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11167 emitcode ("pop","ar3");
11168 emitcode ("pop","ar2");
11170 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11171 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11173 freeAsmop (psb, NULL, ic, FALSE);
11175 /* make the call */
11176 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11178 /* put return value into place*/
11180 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11182 aopPut(AOP(IC_RESULT(ic)),"a",0);
11183 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11184 unsavermask(rsave);
11187 /*-----------------------------------------------------------------*/
11188 /* genNatLibRemoveStateBlock - */
11189 /*-----------------------------------------------------------------*/
11190 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11196 /* save registers that need to be saved */
11197 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11198 ds390_rUmaskForOp (IC_RESULT(ic))));
11200 /* put libraryID into DPTR */
11201 emitcode ("mov","dptr,#LibraryID");
11202 /* make the call */
11203 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11204 unsavermask(rsave);
11207 /*-----------------------------------------------------------------*/
11208 /* genNatLibGetStateBlock - */
11209 /*-----------------------------------------------------------------*/
11210 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11211 operand **parms,const char *name)
11214 symbol *lbl = newiTempLabel(NULL);
11217 /* save registers that need to be saved */
11218 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11219 ds390_rUmaskForOp (IC_RESULT(ic))));
11221 /* put libraryID into DPTR */
11222 emitcode ("mov","dptr,#LibraryID");
11223 /* make the call */
11224 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11225 emitcode ("jnz","!tlabel",lbl->key+100);
11227 /* put return value into place */
11228 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11229 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11230 emitcode ("push","ar3");
11231 emitcode ("push","ar2");
11232 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11233 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11235 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11236 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11238 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11239 emitcode ("","!tlabeldef",lbl->key+100);
11240 unsavermask(rsave);
11243 /*-----------------------------------------------------------------*/
11244 /* genMMMalloc - */
11245 /*-----------------------------------------------------------------*/
11246 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11247 int size, const char *name)
11252 symbol *lbl = newiTempLabel(NULL);
11254 assert (nparms == 1);
11255 /* save registers that need to be saved */
11256 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11257 ds390_rUmaskForOp (IC_RESULT(ic))));
11260 aopOp (bsize,ic,FALSE,FALSE);
11262 /* put the size in R4-R2 */
11263 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11264 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11265 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11267 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11268 emitcode("pop","ar4");
11270 emitcode("pop","ar3");
11271 emitcode("pop","ar2");
11273 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11274 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11276 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11279 freeAsmop (bsize, NULL, ic, FALSE);
11281 /* make the call */
11282 emitcode ("lcall","MM_%s",name);
11283 emitcode ("jz","!tlabel",lbl->key+100);
11284 emitcode ("mov","r2,#!constbyte",0xff);
11285 emitcode ("mov","r3,#!constbyte",0xff);
11286 emitcode ("","!tlabeldef",lbl->key+100);
11287 /* we don't care about the pointer : we just save the handle */
11288 rsym = OP_SYMBOL(IC_RESULT(ic));
11289 if (rsym->liveFrom != rsym->liveTo) {
11290 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11291 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11292 emitcode ("push","ar3");
11293 emitcode ("push","ar2");
11294 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11295 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11297 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11298 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11300 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11302 unsavermask(rsave);
11305 /*-----------------------------------------------------------------*/
11307 /*-----------------------------------------------------------------*/
11308 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11313 assert (nparms == 1);
11314 /* save registers that need to be saved */
11315 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11316 ds390_rUmaskForOp (IC_RESULT(ic))));
11319 aopOp (handle,ic,FALSE,FALSE);
11321 /* put the size in R4-R2 */
11322 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11323 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11324 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11325 emitcode("pop","ar3");
11326 emitcode("pop","ar2");
11328 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11329 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11331 freeAsmop (handle, NULL, ic, FALSE);
11333 /* make the call */
11334 emitcode ("lcall","MM_Deref");
11337 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11338 if (rsym->liveFrom != rsym->liveTo) {
11339 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11340 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11341 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11342 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11343 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11347 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11348 unsavermask(rsave);
11351 /*-----------------------------------------------------------------*/
11352 /* genMMUnrestrictedPersist - */
11353 /*-----------------------------------------------------------------*/
11354 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11359 assert (nparms == 1);
11360 /* save registers that need to be saved */
11361 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11362 ds390_rUmaskForOp (IC_RESULT(ic))));
11365 aopOp (handle,ic,FALSE,FALSE);
11367 /* put the size in R3-R2 */
11368 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11369 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11370 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11371 emitcode("pop","ar3");
11372 emitcode("pop","ar2");
11374 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11375 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11377 freeAsmop (handle, NULL, ic, FALSE);
11379 /* make the call */
11380 emitcode ("lcall","MM_UnrestrictedPersist");
11383 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11384 if (rsym->liveFrom != rsym->liveTo) {
11385 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11386 aopPut(AOP(IC_RESULT(ic)),"a",0);
11387 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11390 unsavermask(rsave);
11393 /*-----------------------------------------------------------------*/
11394 /* genSystemExecJavaProcess - */
11395 /*-----------------------------------------------------------------*/
11396 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11399 operand *handle, *pp;
11401 assert (nparms==2);
11402 /* save registers that need to be saved */
11403 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11404 ds390_rUmaskForOp (IC_RESULT(ic))));
11409 /* put the handle in R3-R2 */
11410 aopOp (handle,ic,FALSE,FALSE);
11411 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11412 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11413 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11414 emitcode("pop","ar3");
11415 emitcode("pop","ar2");
11417 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11418 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11420 freeAsmop (handle, NULL, ic, FALSE);
11422 /* put pointer in DPTR */
11423 aopOp (pp,ic,FALSE,FALSE);
11424 if (AOP_TYPE(pp) == AOP_IMMD) {
11425 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11426 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11427 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11428 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11429 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11431 freeAsmop (handle, NULL, ic, FALSE);
11433 /* make the call */
11434 emitcode ("lcall","System_ExecJavaProcess");
11436 /* put result in place */
11438 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11439 if (rsym->liveFrom != rsym->liveTo) {
11440 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11441 aopPut(AOP(IC_RESULT(ic)),"a",0);
11442 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11446 unsavermask(rsave);
11449 /*-----------------------------------------------------------------*/
11450 /* genSystemRTCRegisters - */
11451 /*-----------------------------------------------------------------*/
11452 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11458 assert (nparms==1);
11459 /* save registers that need to be saved */
11460 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11461 ds390_rUmaskForOp (IC_RESULT(ic))));
11464 /* put pointer in DPTR */
11465 aopOp (pp,ic,FALSE,FALSE);
11466 if (AOP_TYPE (pp) == AOP_IMMD) {
11467 emitcode ("mov","dps,#1");
11468 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11469 emitcode ("mov","dps,#0");
11471 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11472 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11473 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11475 freeAsmop (pp, NULL, ic, FALSE);
11477 /* make the call */
11478 emitcode ("lcall","System_%sRTCRegisters",name);
11480 unsavermask(rsave);
11483 /*-----------------------------------------------------------------*/
11484 /* genSystemThreadSleep - */
11485 /*-----------------------------------------------------------------*/
11486 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11491 assert (nparms==1);
11492 /* save registers that need to be saved */
11493 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11494 ds390_rUmaskForOp (IC_RESULT(ic))));
11497 aopOp(to,ic,FALSE,FALSE);
11498 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11499 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11500 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11501 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11502 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11503 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11504 emitcode ("pop","ar3");
11505 emitcode ("pop","ar2");
11506 emitcode ("pop","ar1");
11507 emitcode ("pop","ar0");
11509 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11510 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11511 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11512 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11514 freeAsmop (to, NULL, ic, FALSE);
11516 /* suspend in acc */
11518 aopOp(s,ic,FALSE,FALSE);
11519 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11520 freeAsmop (s, NULL, ic, FALSE);
11522 /* make the call */
11523 emitcode ("lcall","System_%s",name);
11525 unsavermask(rsave);
11528 /*-----------------------------------------------------------------*/
11529 /* genSystemThreadResume - */
11530 /*-----------------------------------------------------------------*/
11531 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11536 assert (nparms==2);
11537 /* save registers that need to be saved */
11538 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11539 ds390_rUmaskForOp (IC_RESULT(ic))));
11545 aopOp(pid,ic,FALSE,FALSE);
11546 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11547 freeAsmop (pid, NULL, ic, FALSE);
11550 aopOp(tid,ic,FALSE,FALSE);
11551 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11552 freeAsmop (tid, NULL, ic, FALSE);
11554 emitcode ("lcall","System_ThreadResume");
11556 /* put result into place */
11558 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11559 if (rsym->liveFrom != rsym->liveTo) {
11560 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11561 aopPut(AOP(IC_RESULT(ic)),"a",0);
11562 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11565 unsavermask(rsave);
11568 /*-----------------------------------------------------------------*/
11569 /* genSystemProcessResume - */
11570 /*-----------------------------------------------------------------*/
11571 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11576 assert (nparms==1);
11577 /* save registers that need to be saved */
11578 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11579 ds390_rUmaskForOp (IC_RESULT(ic))));
11584 aopOp(pid,ic,FALSE,FALSE);
11585 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11586 freeAsmop (pid, NULL, ic, FALSE);
11588 emitcode ("lcall","System_ProcessResume");
11590 unsavermask(rsave);
11593 /*-----------------------------------------------------------------*/
11595 /*-----------------------------------------------------------------*/
11596 static void genSystem (iCode *ic,int nparms,char *name)
11598 assert(nparms == 0);
11600 emitcode ("lcall","System_%s",name);
11603 /*-----------------------------------------------------------------*/
11604 /* genSystemPoll - */
11605 /*-----------------------------------------------------------------*/
11606 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11611 assert (nparms==1);
11612 /* save registers that need to be saved */
11613 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11614 ds390_rUmaskForOp (IC_RESULT(ic))));
11617 aopOp (fp,ic,FALSE,FALSE);
11618 if (AOP_TYPE (fp) == AOP_IMMD) {
11619 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11620 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11621 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11622 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11623 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11625 freeAsmop (fp, NULL, ic, FALSE);
11627 emitcode ("lcall","System_%sPoll",name);
11629 /* put result into place */
11631 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11632 if (rsym->liveFrom != rsym->liveTo) {
11633 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11634 aopPut(AOP(IC_RESULT(ic)),"a",0);
11635 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11638 unsavermask(rsave);
11641 /*-----------------------------------------------------------------*/
11642 /* genSystemGetCurrentID - */
11643 /*-----------------------------------------------------------------*/
11644 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11646 assert (nparms==0);
11648 emitcode ("lcall","System_GetCurrent%sId",name);
11649 /* put result into place */
11651 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11652 if (rsym->liveFrom != rsym->liveTo) {
11653 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11654 aopPut(AOP(IC_RESULT(ic)),"a",0);
11655 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11660 /*-----------------------------------------------------------------*/
11661 /* genBuiltIn - calls the appropriate function to generating code */
11662 /* for a built in function */
11663 /*-----------------------------------------------------------------*/
11664 static void genBuiltIn (iCode *ic)
11666 operand *bi_parms[MAX_BUILTIN_ARGS];
11671 /* get all the arguments for a built in function */
11672 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11674 /* which function is it */
11675 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11676 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11677 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11678 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11679 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11680 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11681 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11682 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11683 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11684 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11685 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11686 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11687 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11688 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11689 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11690 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11691 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11692 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11693 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11694 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11695 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11696 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11697 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11698 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11699 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11700 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11701 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11702 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11703 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11704 } else if (strcmp(bif->name,"MM_Malloc")==0) {
11705 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11706 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11707 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11708 } else if (strcmp(bif->name,"MM_Free")==0) {
11709 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11710 } else if (strcmp(bif->name,"MM_Deref")==0) {
11711 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11712 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11713 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11714 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11715 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11716 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11717 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11718 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11719 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11720 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11721 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11722 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11723 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11724 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11725 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11726 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11727 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11728 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11729 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11730 } else if (strcmp(bif->name,"System_SaveThread")==0) {
11731 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11732 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11733 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11734 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11735 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11736 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11737 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11738 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11739 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11740 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11741 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11742 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11743 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11744 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11745 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11746 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11747 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11748 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11749 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11750 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11751 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11753 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11759 /*-----------------------------------------------------------------*/
11760 /* gen390Code - generate code for Dallas 390 based controllers */
11761 /*-----------------------------------------------------------------*/
11763 gen390Code (iCode * lic)
11768 lineHead = lineCurr = NULL;
11770 if (options.model == MODEL_FLAT24) {
11771 fReturnSizeDS390 = 5;
11772 fReturn = fReturn24;
11774 fReturnSizeDS390 = 4;
11775 fReturn = fReturn16;
11776 options.stack10bit=0;
11780 /* print the allocation information */
11782 printAllocInfo (currFunc, codeOutFile);
11784 /* if debug information required */
11785 if (options.debug && currFunc)
11787 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11789 if (IS_STATIC (currFunc->etype))
11790 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11792 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11795 /* stack pointer name */
11796 if (options.useXstack)
11802 for (ic = lic; ic; ic = ic->next)
11805 if (cln != ic->lineno)
11810 emitcode ("", "C$%s$%d$%d$%d ==.",
11811 FileBaseName (ic->filename), ic->lineno,
11812 ic->level, ic->block);
11815 emitcode (";", "%s %d", ic->filename, ic->lineno);
11818 /* if the result is marked as
11819 spilt and rematerializable or code for
11820 this has already been generated then
11822 if (resultRemat (ic) || ic->generated)
11825 /* depending on the operation */
11845 /* IPOP happens only when trying to restore a
11846 spilt live range, if there is an ifx statement
11847 following this pop then the if statement might
11848 be using some of the registers being popped which
11849 would destory the contents of the register so
11850 we need to check for this condition and handle it */
11852 ic->next->op == IFX &&
11853 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11854 genIfx (ic->next, ic);
11872 genEndFunction (ic);
11892 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11909 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11913 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11920 /* note these two are xlated by algebraic equivalence
11921 during parsing SDCC.y */
11922 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11923 "got '>=' or '<=' shouldn't have come here");
11927 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11939 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11943 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11947 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11971 genRightShift (ic);
11974 case GET_VALUE_AT_ADDRESS:
11975 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11979 if (POINTER_SET (ic))
11980 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12006 if (ic->builtinSEND) genBuiltIn(ic);
12007 else addSet (&_G.sendSet, ic);
12020 /* now we are ready to call the
12021 peep hole optimizer */
12022 if (!options.nopeep)
12023 peepHole (&lineHead);
12025 /* now do the actual printing */
12026 printLine (lineHead, codeOutFile);