1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
82 static char *javaRet[] = { "r0","r1","r2","r3"};
83 static short rbank = -1;
98 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
105 #define MOVA(x) { char *_mova_tmp = strdup(x); \
106 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
108 emitcode("mov","a,%s",_mova_tmp); \
112 #define CLRC emitcode("clr","c")
113 #define SETC emitcode("setb","c")
115 // A scratch register which will be used to hold
116 // result bytes from operands in far space via DPTR2.
117 #define DP2_RESULT_REG "_ap"
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
122 static unsigned char SLMask[] =
123 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
124 0xE0, 0xC0, 0x80, 0x00};
125 static unsigned char SRMask[] =
126 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
127 0x07, 0x03, 0x01, 0x00};
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple */
136 /*-----------------------------------------------------------------*/
138 emitcode (char *inst, char *fmt,...)
141 char lb[INITIAL_INLINEASM];
149 sprintf (lb, "%s\t", inst);
151 sprintf (lb, "%s", inst);
152 tvsprintf (lb + (strlen (lb)), fmt, ap);
155 tvsprintf (lb, fmt, ap);
157 while (isspace (*lbp))
161 lineCurr = (lineCurr ?
162 connectLine (lineCurr, newLineNode (lb)) :
163 (lineHead = newLineNode (lb)));
164 lineCurr->isInline = _G.inLine;
165 lineCurr->isDebug = _G.debugLine;
169 /*-----------------------------------------------------------------*/
170 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
171 /*-----------------------------------------------------------------*/
173 getFreePtr (iCode * ic, asmop ** aopp, bool result)
175 bool r0iu = FALSE, r1iu = FALSE;
176 bool r0ou = FALSE, r1ou = FALSE;
178 /* the logic: if r0 & r1 used in the instruction
179 then we are in trouble otherwise */
181 /* first check if r0 & r1 are used by this
182 instruction, in which case we are in trouble */
183 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
184 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
189 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
190 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
192 /* if no usage of r0 then return it */
195 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
196 (*aopp)->type = AOP_R0;
198 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
201 /* if no usage of r1 then return it */
204 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
205 (*aopp)->type = AOP_R1;
207 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
210 /* now we know they both have usage */
211 /* if r0 not used in this instruction */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 ds390_regWithIdx (R0_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
223 (*aopp)->type = AOP_R0;
225 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
228 /* if r1 not used then */
232 /* push it if not already pushed */
235 emitcode ("push", "%s",
236 ds390_regWithIdx (R1_IDX)->dname);
240 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
241 (*aopp)->type = AOP_R1;
242 return ds390_regWithIdx (R1_IDX);
246 /* I said end of world but not quite end of world yet */
247 /* if this is a result then we can push it on the stack */
250 (*aopp)->type = AOP_STK;
254 /* other wise this is true end of the world */
255 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
256 "getFreePtr should never reach here");
260 /*-----------------------------------------------------------------*/
261 /* newAsmop - creates a new asmOp */
262 /*-----------------------------------------------------------------*/
264 newAsmop (short type)
268 aop = Safe_calloc (1, sizeof (asmop));
273 static int _currentDPS; /* Current processor DPS. */
274 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
275 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
277 /*-----------------------------------------------------------------*/
278 /* genSetDPTR: generate code to select which DPTR is in use (zero */
279 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
280 /* alternate DPTR (DPL1/DPH1/DPX1). */
281 /*-----------------------------------------------------------------*/
286 /* If we are doing lazy evaluation, simply note the desired
287 * change, but don't emit any code yet.
297 emitcode ("mov", "dps,#0");
302 emitcode ("mov", "dps,#1");
306 /*-----------------------------------------------------------------*/
307 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
309 /* Any code that operates on DPTR (NB: not on the individual */
310 /* components, like DPH) *must* call _flushLazyDPS() before using */
311 /* DPTR within a lazy DPS evaluation block. */
313 /* Note that aopPut and aopGet already contain the proper calls to */
314 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
315 /* DPS evaluation block. */
317 /* Also, _flushLazyDPS must be called before any flow control */
318 /* operations that could potentially branch out of the block. */
320 /* Lazy DPS evaluation is simply an optimization (though an */
321 /* important one), so if in doubt, leave it out. */
322 /*-----------------------------------------------------------------*/
324 _startLazyDPSEvaluation (void)
328 #ifdef BETTER_LITERAL_SHIFT
335 /*-----------------------------------------------------------------*/
336 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
337 /* desired one. Call before using DPTR within a lazy DPS evaluation */
339 /*-----------------------------------------------------------------*/
349 if (_desiredDPS != _currentDPS)
353 emitcode ("inc", "dps");
357 emitcode ("dec", "dps");
359 _currentDPS = _desiredDPS;
363 /*-----------------------------------------------------------------*/
364 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
366 /* Forces us back to the safe state (standard DPTR selected). */
367 /*-----------------------------------------------------------------*/
369 _endLazyDPSEvaluation (void)
371 #ifdef BETTER_LITERAL_SHIFT
390 /*-----------------------------------------------------------------*/
391 /* pointerCode - returns the code for a pointer type */
392 /*-----------------------------------------------------------------*/
394 pointerCode (sym_link * etype)
397 return PTR_TYPE (SPEC_OCLS (etype));
401 /*-----------------------------------------------------------------*/
402 /* aopForSym - for a true symbol */
403 /*-----------------------------------------------------------------*/
405 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
408 memmap *space = SPEC_OCLS (sym->etype);
410 /* if already has one */
414 /* assign depending on the storage class */
415 /* if it is on the stack or indirectly addressable */
416 /* space we need to assign either r0 or r1 to it */
417 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
419 sym->aop = aop = newAsmop (0);
420 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
421 aop->size = getSize (sym->type);
423 /* now assign the address of the variable to
424 the pointer register */
425 if (aop->type != AOP_STK)
431 emitcode ("push", "acc");
434 emitcode ("push", "b");
436 emitcode ("mov", "a,_bp");
437 emitcode ("add", "a,#!constbyte",
439 ((char) (sym->stack - _G.nRegsSaved)) :
440 ((char) sym->stack)) & 0xff);
441 emitcode ("mov", "%s,a",
442 aop->aopu.aop_ptr->name);
445 emitcode ("pop", "b");
448 emitcode ("pop", "acc");
451 emitcode ("mov", "%s,#%s",
452 aop->aopu.aop_ptr->name,
454 aop->paged = space->paged;
457 aop->aopu.aop_stk = sym->stack;
461 if (sym->onStack && options.stack10bit)
463 /* It's on the 10 bit stack, which is located in
468 emitcode ("push", "acc");
471 emitcode ("push", "b");
473 emitcode ("mov", "a,_bpx");
474 emitcode ("clr","c");
475 emitcode ("subb", "a,#!constbyte",
477 ((short) (sym->stack - _G.nRegsSaved)) :
478 ((short) sym->stack)) & 0xff);
479 emitcode ("mov","b,a");
480 emitcode ("mov","a,_bpx+1");
481 emitcode ("subb","a,#!constbyte",(-((sym->stack < 0) ?
482 ((short) (sym->stack - _G.nRegsSaved)) :
483 ((short) sym->stack)) >> 8) & 0xff);
485 if (options.model == MODEL_FLAT24)
486 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
488 emitcode ("mov", "dph1,a");
489 emitcode ("mov", "dpl1,b");
491 if (options.model == MODEL_FLAT24)
492 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
493 emitcode ("mov", "dph,a");
494 emitcode ("mov", "dpl,b");
498 emitcode ("pop", "b");
501 emitcode ("pop", "acc");
503 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
504 aop->size = getSize (sym->type);
508 /* if in bit space */
509 if (IN_BITSPACE (space))
511 sym->aop = aop = newAsmop (AOP_CRY);
512 aop->aopu.aop_dir = sym->rname;
513 aop->size = getSize (sym->type);
516 /* if it is in direct space */
517 if (IN_DIRSPACE (space))
519 sym->aop = aop = newAsmop (AOP_DIR);
520 aop->aopu.aop_dir = sym->rname;
521 aop->size = getSize (sym->type);
525 /* special case for a function */
526 if (IS_FUNC (sym->type))
528 sym->aop = aop = newAsmop (AOP_IMMD);
529 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
530 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
531 aop->size = FPTRSIZE;
535 /* only remaining is far space */
536 /* in which case DPTR gets the address */
537 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
542 emitcode ("mov", "dptr,#%s", sym->rname);
547 emitcode ("mov", "dptr,#%s", sym->rname);
549 aop->size = getSize (sym->type);
551 /* if it is in code space */
552 if (IN_CODESPACE (space))
558 /*-----------------------------------------------------------------*/
559 /* aopForRemat - rematerialzes an object */
560 /*-----------------------------------------------------------------*/
562 aopForRemat (symbol * sym)
564 iCode *ic = sym->rematiCode;
565 asmop *aop = newAsmop (AOP_IMMD);
572 val += (int) operandLitValue (IC_RIGHT (ic));
573 else if (ic->op == '-')
574 val -= (int) operandLitValue (IC_RIGHT (ic));
575 else if (IS_CAST_ICODE(ic)) {
576 sym_link *from_type = operandType(IC_RIGHT(ic));
577 aop->aopu.aop_immd.from_cast_remat = 1;
578 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
579 ptr_type = DCL_TYPE(from_type);
580 if (ptr_type == IPOINTER) {
587 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
591 sprintf (buffer, "(%s %c 0x%04x)",
592 OP_SYMBOL (IC_LEFT (ic))->rname,
593 val >= 0 ? '+' : '-',
596 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
598 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
599 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
600 /* set immd2 field if required */
601 if (aop->aopu.aop_immd.from_cast_remat) {
602 tsprintf(buffer,"#!constbyte",ptr_type);
603 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
604 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
610 /*-----------------------------------------------------------------*/
611 /* aopHasRegs - returns true if aop has regs between from-to */
612 /*-----------------------------------------------------------------*/
613 static int aopHasRegs(asmop *aop, int from, int to)
617 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
619 for (; size < aop->size ; size++) {
621 for (reg = from ; reg <= to ; reg++)
622 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
627 /*-----------------------------------------------------------------*/
628 /* regsInCommon - two operands have some registers in common */
629 /*-----------------------------------------------------------------*/
631 regsInCommon (operand * op1, operand * op2)
636 /* if they have registers in common */
637 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
640 sym1 = OP_SYMBOL (op1);
641 sym2 = OP_SYMBOL (op2);
643 if (sym1->nRegs == 0 || sym2->nRegs == 0)
646 for (i = 0; i < sym1->nRegs; i++)
652 for (j = 0; j < sym2->nRegs; j++)
657 if (sym2->regs[j] == sym1->regs[i])
665 /*-----------------------------------------------------------------*/
666 /* operandsEqu - equivalent */
667 /*-----------------------------------------------------------------*/
669 operandsEqu (operand * op1, operand * op2)
673 /* if they not symbols */
674 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
677 sym1 = OP_SYMBOL (op1);
678 sym2 = OP_SYMBOL (op2);
680 /* if both are itemps & one is spilt
681 and the other is not then false */
682 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
683 sym1->isspilt != sym2->isspilt)
686 /* if they are the same */
690 if (strcmp (sym1->rname, sym2->rname) == 0)
694 /* if left is a tmp & right is not */
695 if (IS_ITEMP (op1) &&
698 (sym1->usl.spillLoc == sym2))
701 if (IS_ITEMP (op2) &&
705 (sym2->usl.spillLoc == sym1))
711 /*-----------------------------------------------------------------*/
712 /* sameRegs - two asmops have the same registers */
713 /*-----------------------------------------------------------------*/
715 sameRegs (asmop * aop1, asmop * aop2)
721 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
728 if (aop1->type != AOP_REG ||
729 aop2->type != AOP_REG)
732 if (aop1->size != aop2->size)
735 for (i = 0; i < aop1->size; i++)
736 if (aop1->aopu.aop_reg[i] !=
737 aop2->aopu.aop_reg[i])
743 /*-----------------------------------------------------------------*/
744 /* aopOp - allocates an asmop for an operand : */
745 /*-----------------------------------------------------------------*/
747 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
756 /* if this a literal */
757 if (IS_OP_LITERAL (op))
759 op->aop = aop = newAsmop (AOP_LIT);
760 aop->aopu.aop_lit = op->operand.valOperand;
761 aop->size = getSize (operandType (op));
765 /* if already has a asmop then continue */
769 /* if the underlying symbol has a aop */
770 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
772 op->aop = OP_SYMBOL (op)->aop;
776 /* if this is a true symbol */
777 if (IS_TRUE_SYMOP (op))
779 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
783 /* this is a temporary : this has
789 e) can be a return use only */
791 sym = OP_SYMBOL (op);
794 /* if the type is a conditional */
795 if (sym->regType == REG_CND)
797 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
802 /* if it is spilt then two situations
804 b) has a spill location */
805 if (sym->isspilt || sym->nRegs == 0)
808 /* rematerialize it NOW */
811 sym->aop = op->aop = aop =
813 aop->size = getSize (sym->type);
820 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
821 aop->size = getSize (sym->type);
822 for (i = 0; i < 2; i++)
823 aop->aopu.aop_str[i] = accUse[i];
833 /* a AOP_STR uses DPTR, but DPTR is already in use;
836 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
839 aop = op->aop = sym->aop = newAsmop (AOP_STR);
840 aop->size = getSize (sym->type);
841 for (i = 0; i < (int) fReturnSizeDS390; i++)
842 aop->aopu.aop_str[i] = fReturn[i];
846 /* else spill location */
847 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
848 /* force a new aop if sizes differ */
849 sym->usl.spillLoc->aop = NULL;
851 sym->aop = op->aop = aop =
852 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
853 aop->size = getSize (sym->type);
857 /* must be in a register */
858 sym->aop = op->aop = aop = newAsmop (AOP_REG);
859 aop->size = sym->nRegs;
860 for (i = 0; i < sym->nRegs; i++)
861 aop->aopu.aop_reg[i] = sym->regs[i];
864 /*-----------------------------------------------------------------*/
865 /* freeAsmop - free up the asmop given to an operand */
866 /*----------------------------------------------------------------*/
868 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
885 /* depending on the asmop type only three cases need work AOP_RO
886 , AOP_R1 && AOP_STK */
894 emitcode ("pop", "ar0");
898 bitVectUnSetBit (ic->rUsed, R0_IDX);
906 emitcode ("pop", "ar1");
910 bitVectUnSetBit (ic->rUsed, R1_IDX);
916 int stk = aop->aopu.aop_stk + aop->size;
917 bitVectUnSetBit (ic->rUsed, R0_IDX);
918 bitVectUnSetBit (ic->rUsed, R1_IDX);
920 getFreePtr (ic, &aop, FALSE);
922 if (options.stack10bit)
924 /* I'm not sure what to do here yet... */
927 "*** Warning: probably generating bad code for "
928 "10 bit stack mode.\n");
933 emitcode ("mov", "a,_bp");
934 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
935 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
939 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
944 emitcode ("pop", "acc");
945 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
948 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
951 freeAsmop (op, NULL, ic, TRUE);
954 emitcode ("pop", "ar0");
960 emitcode ("pop", "ar1");
967 /* all other cases just dealloc */
973 OP_SYMBOL (op)->aop = NULL;
974 /* if the symbol has a spill */
976 SPIL_LOC (op)->aop = NULL;
981 /*------------------------------------------------------------------*/
982 /* aopGet - for fetching value of the aop */
984 /* Set canClobberACC if you are sure it is OK to clobber the value */
985 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
986 /* just less efficient. */
987 /*------------------------------------------------------------------*/
999 /* offset is greater than
1001 if (offset > (aop->size - 1) &&
1002 aop->type != AOP_LIT)
1005 /* depending on type */
1011 /* if we need to increment it */
1012 while (offset > aop->coff)
1014 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1018 while (offset < aop->coff)
1020 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1027 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1028 return (dname ? "acc" : "a");
1030 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1031 rs = Safe_calloc (1, strlen (s) + 1);
1038 if (aop->type == AOP_DPTR2)
1044 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1050 while (offset > aop->coff)
1052 emitcode ("inc", "dptr");
1056 while (offset < aop->coff)
1058 emitcode ("lcall", "__decdptr");
1065 emitcode ("clr", "a");
1066 emitcode ("movc", "a,@a+dptr");
1070 emitcode ("movx", "a,@dptr");
1073 if (aop->type == AOP_DPTR2)
1079 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1080 return DP2_RESULT_REG;
1083 return (dname ? "acc" : "a");
1086 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1087 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1089 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1093 tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1096 tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1099 tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1101 default: /* should not need this (just in case) */
1102 sprintf (s, "#(%s >> %d)",
1103 aop->aopu.aop_immd.aop_immd1,
1109 aop->aopu.aop_immd.aop_immd1);
1110 rs = Safe_calloc (1, strlen (s) + 1);
1116 sprintf (s, "(%s + %d)",
1120 sprintf (s, "%s", aop->aopu.aop_dir);
1121 rs = Safe_calloc (1, strlen (s) + 1);
1127 return aop->aopu.aop_reg[offset]->dname;
1129 return aop->aopu.aop_reg[offset]->name;
1132 emitcode ("clr", "a");
1133 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1134 emitcode ("rlc", "a");
1135 return (dname ? "acc" : "a");
1138 if (!offset && dname)
1140 return aop->aopu.aop_str[offset];
1143 return aopLiteral (aop->aopu.aop_lit, offset);
1147 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1151 return aop->aopu.aop_str[offset];
1155 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1156 "aopget got unsupported aop->type");
1159 /*-----------------------------------------------------------------*/
1160 /* aopPut - puts a string for a aop */
1161 /*-----------------------------------------------------------------*/
1163 aopPut (asmop * aop, char *s, int offset)
1167 if (aop->size && offset > (aop->size - 1))
1169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170 "aopPut got offset > aop->size");
1174 /* will assign value to value */
1175 /* depending on where it is ofcourse */
1180 sprintf (d, "(%s + %d)",
1181 aop->aopu.aop_dir, offset);
1183 sprintf (d, "%s", aop->aopu.aop_dir);
1186 emitcode ("mov", "%s,%s", d, s);
1191 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1192 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1195 strcmp (s, "r0") == 0 ||
1196 strcmp (s, "r1") == 0 ||
1197 strcmp (s, "r2") == 0 ||
1198 strcmp (s, "r3") == 0 ||
1199 strcmp (s, "r4") == 0 ||
1200 strcmp (s, "r5") == 0 ||
1201 strcmp (s, "r6") == 0 ||
1202 strcmp (s, "r7") == 0)
1203 emitcode ("mov", "%s,%s",
1204 aop->aopu.aop_reg[offset]->dname, s);
1206 emitcode ("mov", "%s,%s",
1207 aop->aopu.aop_reg[offset]->name, s);
1214 if (aop->type == AOP_DPTR2)
1222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223 "aopPut writting to code space");
1227 while (offset > aop->coff)
1230 emitcode ("inc", "dptr");
1233 while (offset < aop->coff)
1236 emitcode ("lcall", "__decdptr");
1241 /* if not in accumulater */
1244 emitcode ("movx", "@dptr,a");
1246 if (aop->type == AOP_DPTR2)
1254 while (offset > aop->coff)
1257 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1259 while (offset < aop->coff)
1262 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1269 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1275 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1277 else if (strcmp (s, "r0") == 0 ||
1278 strcmp (s, "r1") == 0 ||
1279 strcmp (s, "r2") == 0 ||
1280 strcmp (s, "r3") == 0 ||
1281 strcmp (s, "r4") == 0 ||
1282 strcmp (s, "r5") == 0 ||
1283 strcmp (s, "r6") == 0 ||
1284 strcmp (s, "r7") == 0)
1287 sprintf (buffer, "a%s", s);
1288 emitcode ("mov", "@%s,%s",
1289 aop->aopu.aop_ptr->name, buffer);
1292 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1297 if (strcmp (s, "a") == 0)
1298 emitcode ("push", "acc");
1302 emitcode ("push", "acc");
1304 emitcode ("push", s);
1310 /* if bit variable */
1311 if (!aop->aopu.aop_dir)
1313 emitcode ("clr", "a");
1314 emitcode ("rlc", "a");
1319 emitcode ("clr", "%s", aop->aopu.aop_dir);
1321 emitcode ("setb", "%s", aop->aopu.aop_dir);
1322 else if (!strcmp (s, "c"))
1323 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1326 if (strcmp (s, "a"))
1331 symbol *lbl = newiTempLabel (NULL);
1332 emitcode ("clr", "c");
1333 emitcode ("jz", "!tlabel", lbl->key + 100);
1334 emitcode ("cpl", "c");
1335 emitcode ("", "!tlabeldef", lbl->key + 100);
1336 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1344 if (strcmp (aop->aopu.aop_str[offset], s))
1345 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1350 if (!offset && (strcmp (s, "acc") == 0))
1353 if (strcmp (aop->aopu.aop_str[offset], s))
1354 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1358 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1359 "aopPut got unsupported aop->type");
1366 /*--------------------------------------------------------------------*/
1367 /* reAdjustPreg - points a register back to where it should (coff==0) */
1368 /*--------------------------------------------------------------------*/
1370 reAdjustPreg (asmop * aop)
1372 if ((aop->coff==0) || (aop->size <= 1)) {
1381 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1385 if (aop->type == AOP_DPTR2)
1392 emitcode ("lcall", "__decdptr");
1395 if (aop->type == AOP_DPTR2)
1405 #define AOP(op) op->aop
1406 #define AOP_TYPE(op) AOP(op)->type
1407 #define AOP_SIZE(op) AOP(op)->size
1408 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1409 AOP_TYPE(x) == AOP_R0))
1411 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1412 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1415 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1416 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1417 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1419 /* Workaround for DS80C390 bug: div ab may return bogus results
1420 * if A is accessed in instruction immediately before the div.
1422 * Will be fixed in B4 rev of processor, Dallas claims.
1425 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1426 if (!AOP_NEEDSACC(RIGHT)) \
1428 /* We can load A first, then B, since \
1429 * B (the RIGHT operand) won't clobber A, \
1430 * thus avoiding touching A right before the div. \
1432 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1433 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1435 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1439 /* Just stuff in a nop after loading A. */ \
1440 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1441 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1443 emitcode("nop", "; workaround for DS80C390 div bug."); \
1446 /*-----------------------------------------------------------------*/
1447 /* genNotFloat - generates not for float operations */
1448 /*-----------------------------------------------------------------*/
1450 genNotFloat (operand * op, operand * res)
1456 D (emitcode (";", "genNotFloat ");
1459 /* we will put 127 in the first byte of
1461 aopPut (AOP (res), "#127", 0);
1462 size = AOP_SIZE (op) - 1;
1465 _startLazyDPSEvaluation ();
1466 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1471 emitcode ("orl", "a,%s",
1473 offset++, FALSE, FALSE, FALSE));
1475 _endLazyDPSEvaluation ();
1477 tlbl = newiTempLabel (NULL);
1478 aopPut (res->aop, one, 1);
1479 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1480 aopPut (res->aop, zero, 1);
1481 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1483 size = res->aop->size - 2;
1485 /* put zeros in the rest */
1487 aopPut (res->aop, zero, offset++);
1490 /*-----------------------------------------------------------------*/
1491 /* opIsGptr: returns non-zero if the passed operand is */
1492 /* a generic pointer type. */
1493 /*-----------------------------------------------------------------*/
1495 opIsGptr (operand * op)
1497 sym_link *type = operandType (op);
1499 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1506 /*-----------------------------------------------------------------*/
1507 /* getDataSize - get the operand data size */
1508 /*-----------------------------------------------------------------*/
1510 getDataSize (operand * op)
1513 size = AOP_SIZE (op);
1514 if (size == GPTRSIZE)
1516 sym_link *type = operandType (op);
1517 if (IS_GENPTR (type))
1519 /* generic pointer; arithmetic operations
1520 * should ignore the high byte (pointer type).
1528 /*-----------------------------------------------------------------*/
1529 /* outAcc - output Acc */
1530 /*-----------------------------------------------------------------*/
1532 outAcc (operand * result)
1535 size = getDataSize (result);
1538 aopPut (AOP (result), "a", 0);
1541 /* unsigned or positive */
1544 aopPut (AOP (result), zero, offset++);
1549 /*-----------------------------------------------------------------*/
1550 /* outBitC - output a bit C */
1551 /*-----------------------------------------------------------------*/
1553 outBitC (operand * result)
1555 /* if the result is bit */
1556 if (AOP_TYPE (result) == AOP_CRY)
1558 aopPut (AOP (result), "c", 0);
1562 emitcode ("clr", "a");
1563 emitcode ("rlc", "a");
1568 /*-----------------------------------------------------------------*/
1569 /* toBoolean - emit code for orl a,operator(sizeop) */
1570 /*-----------------------------------------------------------------*/
1572 toBoolean (operand * oper)
1574 int size = AOP_SIZE (oper) - 1;
1578 /* The generic part of a generic pointer should
1579 * not participate in it's truth value.
1581 * i.e. 0x10000000 is zero.
1583 if (opIsGptr (oper))
1585 D (emitcode (";", "toBoolean: generic ptr special case.");
1590 _startLazyDPSEvaluation ();
1591 if (AOP_NEEDSACC (oper) && size)
1594 emitcode ("push", "b");
1595 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1599 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1605 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1609 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1612 _endLazyDPSEvaluation ();
1616 emitcode ("mov", "a,b");
1617 emitcode ("pop", "b");
1622 /*-----------------------------------------------------------------*/
1623 /* genNot - generate code for ! operation */
1624 /*-----------------------------------------------------------------*/
1629 sym_link *optype = operandType (IC_LEFT (ic));
1631 D (emitcode (";", "genNot ");
1634 /* assign asmOps to operand & result */
1635 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1636 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1638 /* if in bit space then a special case */
1639 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1641 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1642 emitcode ("cpl", "c");
1643 outBitC (IC_RESULT (ic));
1647 /* if type float then do float */
1648 if (IS_FLOAT (optype))
1650 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1654 toBoolean (IC_LEFT (ic));
1656 tlbl = newiTempLabel (NULL);
1657 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1658 emitcode ("", "!tlabeldef", tlbl->key + 100);
1659 outBitC (IC_RESULT (ic));
1662 /* release the aops */
1663 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1664 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1668 /*-----------------------------------------------------------------*/
1669 /* genCpl - generate code for complement */
1670 /*-----------------------------------------------------------------*/
1677 D (emitcode (";", "genCpl ");
1681 /* assign asmOps to operand & result */
1682 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1683 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1685 /* if both are in bit space then
1687 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1688 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1691 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1692 emitcode ("cpl", "c");
1693 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1697 size = AOP_SIZE (IC_RESULT (ic));
1698 _startLazyDPSEvaluation ();
1701 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1703 emitcode ("cpl", "a");
1704 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1706 _endLazyDPSEvaluation ();
1710 /* release the aops */
1711 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1712 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1715 /*-----------------------------------------------------------------*/
1716 /* genUminusFloat - unary minus for floating points */
1717 /*-----------------------------------------------------------------*/
1719 genUminusFloat (operand * op, operand * result)
1721 int size, offset = 0;
1723 /* for this we just need to flip the
1724 first it then copy the rest in place */
1725 D (emitcode (";", "genUminusFloat");
1728 _startLazyDPSEvaluation ();
1729 size = AOP_SIZE (op) - 1;
1730 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1733 emitcode ("cpl", "acc.7");
1734 aopPut (AOP (result), "a", 3);
1738 aopPut (AOP (result),
1739 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1743 _endLazyDPSEvaluation ();
1746 /*-----------------------------------------------------------------*/
1747 /* genUminus - unary minus code generation */
1748 /*-----------------------------------------------------------------*/
1750 genUminus (iCode * ic)
1753 sym_link *optype, *rtype;
1755 D (emitcode (";", "genUminus ");
1760 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1761 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1763 /* if both in bit space then special
1765 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1766 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1769 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770 emitcode ("cpl", "c");
1771 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1775 optype = operandType (IC_LEFT (ic));
1776 rtype = operandType (IC_RESULT (ic));
1778 /* if float then do float stuff */
1779 if (IS_FLOAT (optype))
1781 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1785 /* otherwise subtract from zero */
1786 size = AOP_SIZE (IC_LEFT (ic));
1788 _startLazyDPSEvaluation ();
1791 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1792 if (!strcmp (l, "a"))
1796 emitcode ("cpl", "a");
1797 emitcode ("addc", "a,#0");
1803 emitcode ("clr", "a");
1804 emitcode ("subb", "a,%s", l);
1806 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1808 _endLazyDPSEvaluation ();
1810 /* if any remaining bytes in the result */
1811 /* we just need to propagate the sign */
1812 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1814 emitcode ("rlc", "a");
1815 emitcode ("subb", "a,acc");
1817 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1821 /* release the aops */
1822 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1823 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1826 /*-----------------------------------------------------------------*/
1827 /* savermask - saves registers in the mask */
1828 /*-----------------------------------------------------------------*/
1829 static void savermask(bitVect *rs_mask)
1832 if (options.useXstack) {
1833 if (bitVectBitValue (rs_mask, R0_IDX))
1834 emitcode ("mov", "b,r0");
1835 emitcode ("mov", "r0,%s", spname);
1836 for (i = 0; i < ds390_nRegs; i++) {
1837 if (bitVectBitValue (rs_mask, i)) {
1839 emitcode ("mov", "a,b");
1841 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1842 emitcode ("movx", "@r0,a");
1843 emitcode ("inc", "r0");
1846 emitcode ("mov", "%s,r0", spname);
1847 if (bitVectBitValue (rs_mask, R0_IDX))
1848 emitcode ("mov", "r0,b");
1850 for (i = 0; i < ds390_nRegs; i++) {
1851 if (bitVectBitValue (rs_mask, i))
1852 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1857 /*-----------------------------------------------------------------*/
1858 /* saveRegisters - will look for a call and save the registers */
1859 /*-----------------------------------------------------------------*/
1861 saveRegisters (iCode * lic)
1867 for (ic = lic; ic; ic = ic->next)
1868 if (ic->op == CALL || ic->op == PCALL)
1873 fprintf (stderr, "found parameter push with no function call\n");
1877 /* if the registers have been saved already then
1879 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1881 /* special case if DPTR alive across a function call then must save it
1882 even though callee saves */
1883 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1885 rsave = newBitVect(ic->rMask->size);
1886 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1887 if (bitVectBitValue(ic->rMask,i))
1888 rsave = bitVectSetBit(rsave,i);
1891 /* safe the registers in use at this time but skip the
1892 ones for the result */
1893 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1894 ds390_rUmaskForOp (IC_RESULT(ic)));
1900 /*-----------------------------------------------------------------*/
1901 /* usavermask - restore registers with mask */
1902 /*-----------------------------------------------------------------*/
1903 static void unsavermask(bitVect *rs_mask)
1906 if (options.useXstack) {
1907 emitcode ("mov", "r0,%s", spname);
1908 for (i = ds390_nRegs; i >= 0; i--) {
1909 if (bitVectBitValue (rs_mask, i)) {
1910 emitcode ("dec", "r0");
1911 emitcode ("movx", "a,@r0");
1913 emitcode ("mov", "b,a");
1915 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1918 emitcode ("mov", "%s,r0", spname);
1919 if (bitVectBitValue (rs_mask, R0_IDX))
1920 emitcode ("mov", "r0,b");
1922 for (i = ds390_nRegs; i >= 0; i--) {
1923 if (bitVectBitValue (rs_mask, i))
1924 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1929 /*-----------------------------------------------------------------*/
1930 /* unsaveRegisters - pop the pushed registers */
1931 /*-----------------------------------------------------------------*/
1933 unsaveRegisters (iCode * ic)
1937 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1939 rsave = newBitVect(ic->rMask->size);
1940 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1941 if (bitVectBitValue(ic->rMask,i))
1942 rsave = bitVectSetBit(rsave,i);
1945 /* restore the registers in use at this time but skip the
1946 ones for the result */
1947 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1948 ds390_rUmaskForOp (IC_RESULT(ic)));
1954 /*-----------------------------------------------------------------*/
1956 /*-----------------------------------------------------------------*/
1958 pushSide (operand * oper, int size)
1961 _startLazyDPSEvaluation ();
1964 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1965 if (AOP_TYPE (oper) != AOP_REG &&
1966 AOP_TYPE (oper) != AOP_DIR &&
1969 emitcode ("mov", "a,%s", l);
1970 emitcode ("push", "acc");
1973 emitcode ("push", "%s", l);
1975 _endLazyDPSEvaluation ();
1978 /*-----------------------------------------------------------------*/
1979 /* assignResultValue - */
1980 /*-----------------------------------------------------------------*/
1982 assignResultValue (operand * oper)
1985 int size = AOP_SIZE (oper);
1987 _startLazyDPSEvaluation ();
1990 aopPut (AOP (oper), fReturn[offset], offset);
1993 _endLazyDPSEvaluation ();
1997 /*-----------------------------------------------------------------*/
1998 /* genXpush - pushes onto the external stack */
1999 /*-----------------------------------------------------------------*/
2001 genXpush (iCode * ic)
2003 asmop *aop = newAsmop (0);
2005 int size, offset = 0;
2007 D (emitcode (";", "genXpush ");
2010 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2011 r = getFreePtr (ic, &aop, FALSE);
2014 emitcode ("mov", "%s,_spx", r->name);
2016 size = AOP_SIZE (IC_LEFT (ic));
2017 _startLazyDPSEvaluation ();
2021 char *l = aopGet (AOP (IC_LEFT (ic)),
2022 offset++, FALSE, FALSE, TRUE);
2024 emitcode ("movx", "@%s,a", r->name);
2025 emitcode ("inc", "%s", r->name);
2028 _endLazyDPSEvaluation ();
2031 emitcode ("mov", "_spx,%s", r->name);
2033 freeAsmop (NULL, aop, ic, TRUE);
2034 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2037 /*-----------------------------------------------------------------*/
2038 /* genIpush - genrate code for pushing this gets a little complex */
2039 /*-----------------------------------------------------------------*/
2041 genIpush (iCode * ic)
2043 int size, offset = 0;
2046 D (emitcode (";", "genIpush ");
2049 /* if this is not a parm push : ie. it is spill push
2050 and spill push is always done on the local stack */
2054 /* and the item is spilt then do nothing */
2055 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2058 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2059 size = AOP_SIZE (IC_LEFT (ic));
2060 /* push it on the stack */
2061 _startLazyDPSEvaluation ();
2064 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2070 emitcode ("push", "%s", l);
2072 _endLazyDPSEvaluation ();
2076 /* this is a paramter push: in this case we call
2077 the routine to find the call and save those
2078 registers that need to be saved */
2081 /* if use external stack then call the external
2082 stack pushing routine */
2083 if (options.useXstack)
2089 /* then do the push */
2090 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2092 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2093 size = AOP_SIZE (IC_LEFT (ic));
2095 _startLazyDPSEvaluation ();
2098 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2099 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2100 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2103 emitcode ("mov", "a,%s", l);
2104 emitcode ("push", "acc");
2107 emitcode ("push", "%s", l);
2109 _endLazyDPSEvaluation ();
2111 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2114 /*-----------------------------------------------------------------*/
2115 /* genIpop - recover the registers: can happen only for spilling */
2116 /*-----------------------------------------------------------------*/
2118 genIpop (iCode * ic)
2122 D (emitcode (";", "genIpop ");
2126 /* if the temp was not pushed then */
2127 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2130 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2131 size = AOP_SIZE (IC_LEFT (ic));
2132 offset = (size - 1);
2133 _startLazyDPSEvaluation ();
2136 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2137 FALSE, TRUE, TRUE));
2139 _endLazyDPSEvaluation ();
2141 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2144 /*-----------------------------------------------------------------*/
2145 /* unsaveRBank - restores the resgister bank from stack */
2146 /*-----------------------------------------------------------------*/
2148 unsaveRBank (int bank, iCode * ic, bool popPsw)
2154 if (options.useXstack)
2158 /* Assume r0 is available for use. */
2159 r = ds390_regWithIdx (R0_IDX);;
2164 r = getFreePtr (ic, &aop, FALSE);
2166 emitcode ("mov", "%s,_spx", r->name);
2171 if (options.useXstack)
2173 emitcode ("movx", "a,@%s", r->name);
2174 emitcode ("mov", "psw,a");
2175 emitcode ("dec", "%s", r->name);
2179 emitcode ("pop", "psw");
2183 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2185 if (options.useXstack)
2187 emitcode ("movx", "a,@%s", r->name);
2188 emitcode ("mov", "(%s+%d),a",
2189 regs390[i].base, 8 * bank + regs390[i].offset);
2190 emitcode ("dec", "%s", r->name);
2194 emitcode ("pop", "(%s+%d)",
2195 regs390[i].base, 8 * bank + regs390[i].offset);
2198 if (options.useXstack)
2200 emitcode ("mov", "_spx,%s", r->name);
2205 freeAsmop (NULL, aop, ic, TRUE);
2209 /*-----------------------------------------------------------------*/
2210 /* saveRBank - saves an entire register bank on the stack */
2211 /*-----------------------------------------------------------------*/
2213 saveRBank (int bank, iCode * ic, bool pushPsw)
2219 if (options.useXstack)
2223 /* Assume r0 is available for use. */
2224 r = ds390_regWithIdx (R0_IDX);;
2229 r = getFreePtr (ic, &aop, FALSE);
2231 emitcode ("mov", "%s,_spx", r->name);
2234 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2236 if (options.useXstack)
2238 emitcode ("inc", "%s", r->name);
2239 emitcode ("mov", "a,(%s+%d)",
2240 regs390[i].base, 8 * bank + regs390[i].offset);
2241 emitcode ("movx", "@%s,a", r->name);
2244 emitcode ("push", "(%s+%d)",
2245 regs390[i].base, 8 * bank + regs390[i].offset);
2250 if (options.useXstack)
2252 emitcode ("mov", "a,psw");
2253 emitcode ("movx", "@%s,a", r->name);
2254 emitcode ("inc", "%s", r->name);
2255 emitcode ("mov", "_spx,%s", r->name);
2259 emitcode ("push", "psw");
2262 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2267 freeAsmop (NULL, aop, ic, TRUE);
2276 /*-----------------------------------------------------------------*/
2277 /* genCall - generates a call statement */
2278 /*-----------------------------------------------------------------*/
2280 genCall (iCode * ic)
2283 bool restoreBank = FALSE;
2284 bool swapBanks = FALSE;
2286 D (emitcode (";", "genCall "););
2288 /* if we are calling a not _naked function that is not using
2289 the same register bank then we need to save the
2290 destination registers on the stack */
2291 dtype = operandType (IC_LEFT (ic));
2292 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2293 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2294 IFFUNC_ISISR (currFunc->type))
2298 /* This is unexpected; the bank should have been saved in
2301 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2307 /* if caller saves & we have not saved then */
2311 /* if send set is not empty the assign */
2312 /* We've saved all the registers we care about;
2313 * therefore, we may clobber any register not used
2314 * in the calling convention (i.e. anything not in
2321 for (sic = setFirstItem (_G.sendSet); sic;
2322 sic = setNextItem (_G.sendSet))
2324 int size, offset = 0;
2327 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2328 size = AOP_SIZE (IC_LEFT (sic));
2330 _startLazyDPSEvaluation ();
2333 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2334 FALSE, FALSE, TRUE);
2335 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2337 emitcode("mov", "%s,%s", regs390[offset].name, l);
2339 else if (strcmp (l, fReturn[offset]))
2341 emitcode ("mov", "%s,%s",
2347 _endLazyDPSEvaluation ();
2348 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2350 size = AOP_SIZE (IC_LEFT (sic));
2358 emitcode("mov", "%s,%s",
2359 fReturn[size], regs390[size].name);
2363 // we know that dpl(hxb) is the result, so
2364 _startLazyDPSEvaluation ();
2365 size=getSize(operandType(IC_LEFT(sic)));
2367 aopOp (IC_LEFT (sic), sic, FALSE,
2368 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2370 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2374 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2375 FALSE, FALSE, TRUE);
2376 if (strcmp (l, fReturn[offset]))
2378 emitcode ("mov", "%s,%s",
2384 _endLazyDPSEvaluation ();
2386 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2393 emitcode ("mov", "psw,#!constbyte",
2394 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2398 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2399 OP_SYMBOL (IC_LEFT (ic))->rname :
2400 OP_SYMBOL (IC_LEFT (ic))->name));
2404 emitcode ("mov", "psw,#!constbyte",
2405 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2408 /* if we need assign a result value */
2409 if ((IS_ITEMP (IC_RESULT (ic)) &&
2410 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2411 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2412 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2413 IS_TRUE_SYMOP (IC_RESULT (ic)))
2415 if (isOperandInFarSpace (IC_RESULT (ic))
2416 && getSize (operandType (IC_RESULT (ic))) <= 2)
2418 int size = getSize (operandType (IC_RESULT (ic)));
2420 /* Special case for 1 or 2 byte return in far space. */
2424 emitcode ("mov", "b,%s", fReturn[1]);
2427 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2428 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2432 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2434 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2439 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2442 assignResultValue (IC_RESULT (ic));
2444 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2448 /* adjust the stack for parameters if
2450 if (ic->parmBytes) {
2451 if (options.stack10bit) {
2452 emitcode ("clr","c");
2453 emitcode ("mov","a,sp");
2454 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2455 emitcode ("mov","sp,a");
2456 emitcode ("mov","a,esp");
2457 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2458 emitcode ("mov","esp,a");
2461 if (ic->parmBytes > 3) {
2462 emitcode ("mov", "a,%s", spname);
2463 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2464 emitcode ("mov", "%s,a", spname);
2466 for (i = 0; i < ic->parmBytes; i++)
2467 emitcode ("dec", "%s", spname);
2471 /* if we hade saved some registers then unsave them */
2473 unsaveRegisters (ic);
2475 /* if register bank was saved then pop them */
2477 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2480 /*-----------------------------------------------------------------*/
2481 /* genPcall - generates a call by pointer statement */
2482 /*-----------------------------------------------------------------*/
2484 genPcall (iCode * ic)
2487 symbol *rlbl = newiTempLabel (NULL);
2488 bool restoreBank=FALSE;
2490 D (emitcode (";", "genPcall ");
2494 /* if caller saves & we have not saved then */
2498 /* if we are calling a function that is not using
2499 the same register bank then we need to save the
2500 destination registers on the stack */
2501 dtype = operandType (IC_LEFT (ic));
2502 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2503 IFFUNC_ISISR (currFunc->type) &&
2504 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2505 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2509 /* push the return address on to the stack */
2510 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2511 emitcode ("push", "acc");
2512 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2513 emitcode ("push", "acc");
2515 if (options.model == MODEL_FLAT24)
2517 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2518 emitcode ("push", "acc");
2521 /* now push the calling address */
2522 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2524 pushSide (IC_LEFT (ic), FPTRSIZE);
2526 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2528 /* if send set is not empty the assign */
2533 for (sic = setFirstItem (_G.sendSet); sic;
2534 sic = setNextItem (_G.sendSet))
2536 int size, offset = 0;
2538 // we know that dpl(hxb) is the result, so
2539 _startLazyDPSEvaluation ();
2540 size=getSize(operandType(IC_LEFT(sic)));
2542 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2544 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2548 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2549 FALSE, FALSE, TRUE);
2550 if (strcmp (l, fReturn[offset]))
2552 emitcode ("mov", "%s,%s",
2558 _endLazyDPSEvaluation ();
2559 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2564 emitcode ("ret", "");
2565 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2568 /* if we need assign a result value */
2569 if ((IS_ITEMP (IC_RESULT (ic)) &&
2570 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2571 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2572 IS_TRUE_SYMOP (IC_RESULT (ic)))
2576 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2579 assignResultValue (IC_RESULT (ic));
2581 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2584 /* adjust the stack for parameters if
2589 if (ic->parmBytes > 3)
2591 emitcode ("mov", "a,%s", spname);
2592 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2593 emitcode ("mov", "%s,a", spname);
2596 for (i = 0; i < ic->parmBytes; i++)
2597 emitcode ("dec", "%s", spname);
2601 /* if register bank was saved then unsave them */
2603 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2605 /* if we hade saved some registers then
2608 unsaveRegisters (ic);
2612 /*-----------------------------------------------------------------*/
2613 /* resultRemat - result is rematerializable */
2614 /*-----------------------------------------------------------------*/
2616 resultRemat (iCode * ic)
2618 if (SKIP_IC (ic) || ic->op == IFX)
2621 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2623 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2624 if (sym->remat && !POINTER_SET (ic))
2631 #if defined(__BORLANDC__) || defined(_MSC_VER)
2632 #define STRCASECMP stricmp
2634 #define STRCASECMP strcasecmp
2637 /*-----------------------------------------------------------------*/
2638 /* inExcludeList - return 1 if the string is in exclude Reg list */
2639 /*-----------------------------------------------------------------*/
2641 inExcludeList (char *s)
2645 if (options.excludeRegs[i] &&
2646 STRCASECMP (options.excludeRegs[i], "none") == 0)
2649 for (i = 0; options.excludeRegs[i]; i++)
2651 if (options.excludeRegs[i] &&
2652 STRCASECMP (s, options.excludeRegs[i]) == 0)
2658 /*-----------------------------------------------------------------*/
2659 /* genFunction - generated code for function entry */
2660 /*-----------------------------------------------------------------*/
2662 genFunction (iCode * ic)
2666 bool switchedPSW = FALSE;
2668 D (emitcode (";", "genFunction "););
2671 /* create the function header */
2672 emitcode (";", "-----------------------------------------");
2673 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2674 emitcode (";", "-----------------------------------------");
2676 emitcode ("", "%s:", sym->rname);
2677 ftype = operandType (IC_LEFT (ic));
2679 if (IFFUNC_ISNAKED(ftype))
2681 emitcode(";", "naked function: no prologue.");
2685 if (options.stack_probe)
2686 emitcode ("lcall","__stack_probe");
2687 /* if critical function then turn interrupts off */
2688 if (IFFUNC_ISCRITICAL (ftype))
2689 emitcode ("clr", "ea");
2691 /* here we need to generate the equates for the
2692 register bank if required */
2693 if (FUNC_REGBANK (ftype) != rbank)
2697 rbank = FUNC_REGBANK (ftype);
2698 for (i = 0; i < ds390_nRegs; i++)
2700 if (regs390[i].print) {
2701 if (strcmp (regs390[i].base, "0") == 0)
2702 emitcode ("", "%s !equ !constbyte",
2704 8 * rbank + regs390[i].offset);
2706 emitcode ("", "%s !equ %s + !constbyte",
2709 8 * rbank + regs390[i].offset);
2714 /* if this is an interrupt service routine then
2715 save acc, b, dpl, dph */
2716 if (IFFUNC_ISISR (sym->type))
2719 if (!inExcludeList ("acc"))
2720 emitcode ("push", "acc");
2721 if (!inExcludeList ("b"))
2722 emitcode ("push", "b");
2723 if (!inExcludeList ("dpl"))
2724 emitcode ("push", "dpl");
2725 if (!inExcludeList ("dph"))
2726 emitcode ("push", "dph");
2727 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2729 emitcode ("push", "dpx");
2730 /* Make sure we're using standard DPTR */
2731 emitcode ("push", "dps");
2732 emitcode ("mov", "dps,#0");
2733 if (options.stack10bit)
2735 /* This ISR could conceivably use DPTR2. Better save it. */
2736 emitcode ("push", "dpl1");
2737 emitcode ("push", "dph1");
2738 emitcode ("push", "dpx1");
2739 emitcode ("push", DP2_RESULT_REG);
2742 /* if this isr has no bank i.e. is going to
2743 run with bank 0 , then we need to save more
2745 if (!FUNC_REGBANK (sym->type))
2748 /* if this function does not call any other
2749 function then we can be economical and
2750 save only those registers that are used */
2751 if (!IFFUNC_HASFCALL(sym->type))
2755 /* if any registers used */
2758 /* save the registers used */
2759 for (i = 0; i < sym->regsUsed->size; i++)
2761 if (bitVectBitValue (sym->regsUsed, i) ||
2762 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2763 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2770 /* this function has a function call cannot
2771 determines register usage so we will have to push the
2773 saveRBank (0, ic, FALSE);
2778 /* This ISR uses a non-zero bank.
2780 * We assume that the bank is available for our
2783 * However, if this ISR calls a function which uses some
2784 * other bank, we must save that bank entirely.
2786 unsigned long banksToSave = 0;
2788 if (IFFUNC_HASFCALL(sym->type))
2791 #define MAX_REGISTER_BANKS 4
2796 for (i = ic; i; i = i->next)
2798 if (i->op == ENDFUNCTION)
2800 /* we got to the end OK. */
2808 dtype = operandType (IC_LEFT(i));
2810 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2812 /* Mark this bank for saving. */
2813 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2815 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2819 banksToSave |= (1 << FUNC_REGBANK(dtype));
2822 /* And note that we don't need to do it in
2830 /* This is a mess; we have no idea what
2831 * register bank the called function might
2834 * The only thing I can think of to do is
2835 * throw a warning and hope.
2837 werror(W_FUNCPTR_IN_USING_ISR);
2841 if (banksToSave && options.useXstack)
2843 /* Since we aren't passing it an ic,
2844 * saveRBank will assume r0 is available to abuse.
2846 * So switch to our (trashable) bank now, so
2847 * the caller's R0 isn't trashed.
2849 emitcode ("push", "psw");
2850 emitcode ("mov", "psw,#!constbyte",
2851 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2855 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2857 if (banksToSave & (1 << ix))
2859 saveRBank(ix, NULL, FALSE);
2863 // jwk: this needs a closer look
2864 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2869 /* if callee-save to be used for this function
2870 then save the registers being used in this function */
2871 if (IFFUNC_CALLEESAVES(sym->type))
2875 /* if any registers used */
2878 /* save the registers used */
2879 for (i = 0; i < sym->regsUsed->size; i++)
2881 if (bitVectBitValue (sym->regsUsed, i) ||
2882 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2884 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2892 /* set the register bank to the desired value */
2893 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2896 emitcode ("push", "psw");
2897 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2900 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2901 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2902 if (options.stack10bit) {
2903 emitcode ("push","_bpx");
2904 emitcode ("push","_bpx+1");
2905 emitcode ("mov","_bpx,%s",spname);
2906 emitcode ("mov","_bpx+1,esp");
2907 emitcode ("anl","_bpx+1,#3");
2909 if (options.useXstack) {
2910 emitcode ("mov", "r0,%s", spname);
2911 emitcode ("mov", "a,_bp");
2912 emitcode ("movx", "@r0,a");
2913 emitcode ("inc", "%s", spname);
2915 /* set up the stack */
2916 emitcode ("push", "_bp"); /* save the callers stack */
2918 emitcode ("mov", "_bp,%s", spname);
2922 /* adjust the stack for the function */
2925 if (options.stack10bit) {
2926 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2927 assert (sym->recvSize <= 4);
2928 emitcode ("mov","a,sp");
2929 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2930 emitcode ("mov","sp,a");
2931 emitcode ("mov","a,esp");
2932 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2933 emitcode ("mov","esp,a");
2936 werror (W_STACK_OVERFLOW, sym->name);
2938 if (i > 3 && sym->recvSize < 4) {
2940 emitcode ("mov", "a,sp");
2941 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2942 emitcode ("mov", "sp,a");
2946 emitcode ("inc", "sp");
2953 emitcode ("mov", "a,_spx");
2954 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2955 emitcode ("mov", "_spx,a");
2960 /*-----------------------------------------------------------------*/
2961 /* genEndFunction - generates epilogue for functions */
2962 /*-----------------------------------------------------------------*/
2964 genEndFunction (iCode * ic)
2966 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2968 D (emitcode (";", "genEndFunction "););
2970 if (IFFUNC_ISNAKED(sym->type))
2972 emitcode(";", "naked function: no epilogue.");
2976 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2977 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2979 if (options.stack10bit) {
2980 emitcode ("mov", "sp,_bpx", spname);
2981 emitcode ("mov", "esp,_bpx+1", spname);
2983 emitcode ("mov", "%s,_bp", spname);
2987 /* if use external stack but some variables were
2988 added to the local stack then decrement the
2990 if (options.useXstack && sym->stack) {
2991 emitcode ("mov", "a,sp");
2992 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2993 emitcode ("mov", "sp,a");
2997 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2998 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3000 if (options.useXstack) {
3001 emitcode ("mov", "r0,%s", spname);
3002 emitcode ("movx", "a,@r0");
3003 emitcode ("mov", "_bp,a");
3004 emitcode ("dec", "%s", spname);
3006 if (options.stack10bit) {
3007 emitcode ("pop", "_bpx+1");
3008 emitcode ("pop", "_bpx");
3010 emitcode ("pop", "_bp");
3015 /* restore the register bank */
3016 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3018 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3019 || !options.useXstack)
3021 /* Special case of ISR using non-zero bank with useXstack
3024 emitcode ("pop", "psw");
3028 if (IFFUNC_ISISR (sym->type))
3031 /* now we need to restore the registers */
3032 /* if this isr has no bank i.e. is going to
3033 run with bank 0 , then we need to save more
3035 if (!FUNC_REGBANK (sym->type))
3037 /* if this function does not call any other
3038 function then we can be economical and
3039 save only those registers that are used */
3040 if (!IFFUNC_HASFCALL(sym->type))
3044 /* if any registers used */
3047 /* save the registers used */
3048 for (i = sym->regsUsed->size; i >= 0; i--)
3050 if (bitVectBitValue (sym->regsUsed, i) ||
3051 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3052 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3059 /* this function has a function call cannot
3060 determines register usage so we will have to pop the
3062 unsaveRBank (0, ic, FALSE);
3067 /* This ISR uses a non-zero bank.
3069 * Restore any register banks saved by genFunction
3072 // jwk: this needs a closer look
3073 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3076 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3078 if (savedBanks & (1 << ix))
3080 unsaveRBank(ix, NULL, FALSE);
3084 if (options.useXstack)
3086 /* Restore bank AFTER calling unsaveRBank,
3087 * since it can trash r0.
3089 emitcode ("pop", "psw");
3093 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3095 if (options.stack10bit)
3097 emitcode ("pop", DP2_RESULT_REG);
3098 emitcode ("pop", "dpx1");
3099 emitcode ("pop", "dph1");
3100 emitcode ("pop", "dpl1");
3102 emitcode ("pop", "dps");
3103 emitcode ("pop", "dpx");
3105 if (!inExcludeList ("dph"))
3106 emitcode ("pop", "dph");
3107 if (!inExcludeList ("dpl"))
3108 emitcode ("pop", "dpl");
3109 if (!inExcludeList ("b"))
3110 emitcode ("pop", "b");
3111 if (!inExcludeList ("acc"))
3112 emitcode ("pop", "acc");
3114 if (IFFUNC_ISCRITICAL (sym->type))
3115 emitcode ("setb", "ea");
3117 /* if debug then send end of function */
3118 if (options.debug && currFunc) {
3120 emitcode ("", "C$%s$%d$%d$%d ==.",
3121 FileBaseName (ic->filename), currFunc->lastLine,
3122 ic->level, ic->block);
3123 if (IS_STATIC (currFunc->etype))
3124 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3126 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3130 emitcode ("reti", "");
3134 if (IFFUNC_ISCRITICAL (sym->type))
3135 emitcode ("setb", "ea");
3137 if (IFFUNC_CALLEESAVES(sym->type))
3141 /* if any registers used */
3144 /* save the registers used */
3145 for (i = sym->regsUsed->size; i >= 0; i--)
3147 if (bitVectBitValue (sym->regsUsed, i) ||
3148 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3149 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3155 /* if debug then send end of function */
3156 if (options.debug && currFunc)
3159 emitcode ("", "C$%s$%d$%d$%d ==.",
3160 FileBaseName (ic->filename), currFunc->lastLine,
3161 ic->level, ic->block);
3162 if (IS_STATIC (currFunc->etype))
3163 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3165 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3169 emitcode ("ret", "");
3174 /*-----------------------------------------------------------------*/
3175 /* genJavaNativeRet - generate code for return JavaNative */
3176 /*-----------------------------------------------------------------*/
3177 static void genJavaNativeRet(iCode *ic)
3181 aopOp (IC_LEFT (ic), ic, FALSE,
3182 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3183 size = AOP_SIZE (IC_LEFT (ic));
3187 /* it is assigned to GPR0-R3 then push them */
3188 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3189 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3190 for (i = 0 ; i < size ; i++ ) {
3191 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3193 for (i = (size-1) ; i >= 0 ; i--) {
3194 emitcode ("pop","a%s",javaRet[i]);
3197 for (i = 0 ; i < size ; i++)
3198 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3200 for (i = size ; i < 4 ; i++ )
3201 emitcode ("mov","%s,#0",javaRet[i]);
3205 /*-----------------------------------------------------------------*/
3206 /* genRet - generate code for return statement */
3207 /*-----------------------------------------------------------------*/
3211 int size, offset = 0, pushed = 0;
3213 D (emitcode (";", "genRet ");
3216 /* if we have no return value then
3217 just generate the "ret" */
3221 /* if this is a JavaNative function then return
3222 value in different register */
3223 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3224 genJavaNativeRet(ic);
3227 /* we have something to return then
3228 move the return value into place */
3229 aopOp (IC_LEFT (ic), ic, FALSE,
3230 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3231 size = AOP_SIZE (IC_LEFT (ic));
3233 _startLazyDPSEvaluation ();
3237 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3239 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3240 FALSE, TRUE, FALSE);
3241 emitcode ("push", "%s", l);
3246 /* Since A is the last element of fReturn,
3247 * is is OK to clobber it in the aopGet.
3249 l = aopGet (AOP (IC_LEFT (ic)), offset,
3250 FALSE, FALSE, TRUE);
3251 if (strcmp (fReturn[offset], l))
3252 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3255 _endLazyDPSEvaluation ();
3262 if (strcmp (fReturn[pushed], "a"))
3263 emitcode ("pop", fReturn[pushed]);
3265 emitcode ("pop", "acc");
3268 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3271 /* generate a jump to the return label
3272 if the next is not the return statement */
3273 if (!(ic->next && ic->next->op == LABEL &&
3274 IC_LABEL (ic->next) == returnLabel))
3276 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3280 /*-----------------------------------------------------------------*/
3281 /* genLabel - generates a label */
3282 /*-----------------------------------------------------------------*/
3284 genLabel (iCode * ic)
3286 /* special case never generate */
3287 if (IC_LABEL (ic) == entryLabel)
3290 D (emitcode (";", "genLabel ");
3293 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3296 /*-----------------------------------------------------------------*/
3297 /* genGoto - generates a ljmp */
3298 /*-----------------------------------------------------------------*/
3300 genGoto (iCode * ic)
3302 D (emitcode (";", "genGoto ");
3304 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3307 /*-----------------------------------------------------------------*/
3308 /* findLabelBackwards: walks back through the iCode chain looking */
3309 /* for the given label. Returns number of iCode instructions */
3310 /* between that label and given ic. */
3311 /* Returns zero if label not found. */
3312 /*-----------------------------------------------------------------*/
3314 findLabelBackwards (iCode * ic, int key)
3323 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3325 /* printf("findLabelBackwards = %d\n", count); */
3333 /*-----------------------------------------------------------------*/
3334 /* genPlusIncr :- does addition with increment if possible */
3335 /*-----------------------------------------------------------------*/
3337 genPlusIncr (iCode * ic)
3339 unsigned int icount;
3340 unsigned int size = getDataSize (IC_RESULT (ic));
3342 /* will try to generate an increment */
3343 /* if the right side is not a literal
3345 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3348 /* if the literal value of the right hand side
3349 is greater than 4 then it is not worth it */
3350 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3353 /* if increment 16 bits in register */
3355 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3356 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3357 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3365 /* If the next instruction is a goto and the goto target
3366 * is <= 5 instructions previous to this, we can generate
3367 * jumps straight to that target.
3369 if (ic->next && ic->next->op == GOTO
3370 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3373 emitcode (";", "tail increment optimized (range %d)", labelRange);
3374 tlbl = IC_LABEL (ic->next);
3379 tlbl = newiTempLabel (NULL);
3382 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3383 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3384 IS_AOP_PREG (IC_RESULT (ic)))
3385 emitcode ("cjne", "%s,#0,!tlabel"
3386 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3390 emitcode ("clr", "a");
3391 emitcode ("cjne", "a,%s,!tlabel"
3392 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3396 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3399 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3400 IS_AOP_PREG (IC_RESULT (ic)))
3401 emitcode ("cjne", "%s,#0,!tlabel"
3402 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3405 emitcode ("cjne", "a,%s,!tlabel"
3406 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3409 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3413 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3414 IS_AOP_PREG (IC_RESULT (ic)))
3415 emitcode ("cjne", "%s,#0,!tlabel"
3416 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3420 emitcode ("cjne", "a,%s,!tlabel"
3421 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3424 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3429 emitcode ("", "!tlabeldef", tlbl->key + 100);
3434 /* if the sizes are greater than 1 then we cannot */
3435 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3436 AOP_SIZE (IC_LEFT (ic)) > 1)
3439 /* we can if the aops of the left & result match or
3440 if they are in registers and the registers are the
3443 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3444 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3445 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3450 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3451 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3452 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3457 _startLazyDPSEvaluation ();
3460 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3462 _endLazyDPSEvaluation ();
3471 /*-----------------------------------------------------------------*/
3472 /* outBitAcc - output a bit in acc */
3473 /*-----------------------------------------------------------------*/
3475 outBitAcc (operand * result)
3477 symbol *tlbl = newiTempLabel (NULL);
3478 /* if the result is a bit */
3479 if (AOP_TYPE (result) == AOP_CRY)
3481 aopPut (AOP (result), "a", 0);
3485 emitcode ("jz", "!tlabel", tlbl->key + 100);
3486 emitcode ("mov", "a,%s", one);
3487 emitcode ("", "!tlabeldef", tlbl->key + 100);
3492 /*-----------------------------------------------------------------*/
3493 /* genPlusBits - generates code for addition of two bits */
3494 /*-----------------------------------------------------------------*/
3496 genPlusBits (iCode * ic)
3498 D (emitcode (";", "genPlusBits ");
3500 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3502 symbol *lbl = newiTempLabel (NULL);
3503 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3504 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3505 emitcode ("cpl", "c");
3506 emitcode ("", "!tlabeldef", (lbl->key + 100));
3507 outBitC (IC_RESULT (ic));
3511 emitcode ("clr", "a");
3512 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3513 emitcode ("rlc", "a");
3514 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3515 emitcode ("addc", "a,#0");
3516 outAcc (IC_RESULT (ic));
3521 adjustArithmeticResult (iCode * ic)
3523 if (opIsGptr (IC_RESULT (ic)) &&
3524 opIsGptr (IC_LEFT (ic)) &&
3525 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3527 aopPut (AOP (IC_RESULT (ic)),
3528 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3532 if (opIsGptr (IC_RESULT (ic)) &&
3533 opIsGptr (IC_RIGHT (ic)) &&
3534 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3536 aopPut (AOP (IC_RESULT (ic)),
3537 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3541 if (opIsGptr (IC_RESULT (ic)) &&
3542 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3543 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3544 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3545 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3548 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3549 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3553 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3554 // Please don't bring it back without a really good reason.
3555 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3556 // (because all three operands are in far space).
3557 #define AOP_OP_3(ic) \
3558 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3559 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3560 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3561 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3562 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3563 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3565 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3567 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3571 // Macro to aopOp all three operands of an ic. If this cannot be done,
3572 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3573 // will be set TRUE. The caller must then handle the case specially, noting
3574 // that the IC_RESULT operand is not aopOp'd.
3575 #define AOP_OP_3_NOFATAL(ic, rc) \
3576 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3577 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3578 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3579 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3580 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3582 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3587 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3588 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3590 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3591 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3593 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3595 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3599 // aopOp the left & right operands of an ic.
3600 #define AOP_OP_2(ic) \
3601 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3602 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3604 // convienience macro.
3605 #define AOP_SET_LOCALS(ic) \
3606 left = IC_LEFT(ic); \
3607 right = IC_RIGHT(ic); \
3608 result = IC_RESULT(ic);
3611 // Given an integer value of pushedSize bytes on the stack,
3612 // adjust it to be resultSize bytes, either by discarding
3613 // the most significant bytes or by zero-padding.
3615 // On exit from this macro, pushedSize will have been adjusted to
3616 // equal resultSize, and ACC may be trashed.
3617 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3618 /* If the pushed data is bigger than the result, \
3619 * simply discard unused bytes. Icky, but works. \
3621 while (pushedSize > resultSize) \
3623 D (emitcode (";", "discarding unused result byte."););\
3624 emitcode ("pop", "acc"); \
3627 if (pushedSize < resultSize) \
3629 emitcode ("clr", "a"); \
3630 /* Conversly, we haven't pushed enough here. \
3631 * just zero-pad, and all is well. \
3633 while (pushedSize < resultSize) \
3635 emitcode("push", "acc"); \
3639 assert(pushedSize == resultSize);
3641 /*-----------------------------------------------------------------*/
3642 /* genPlus - generates code for addition */
3643 /*-----------------------------------------------------------------*/
3645 genPlus (iCode * ic)
3647 int size, offset = 0;
3648 bool pushResult = FALSE;
3651 D (emitcode (";", "genPlus "););
3653 /* special cases :- */
3654 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3655 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3656 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3657 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3659 while (size--) emitcode ("inc","dptr");
3661 emitcode ("mov","a,dpl");
3662 emitcode ("add","a,#!constbyte",size & 0xff);
3663 emitcode ("mov","dpl,a");
3664 emitcode ("mov","a,dph");
3665 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3666 emitcode ("mov","dph,a");
3667 emitcode ("mov","a,dpx");
3668 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3669 emitcode ("mov","dpx,a");
3671 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3674 if ( IS_SYMOP(IC_LEFT(ic)) &&
3675 OP_SYMBOL(IC_LEFT(ic))->remat &&
3676 isOperandInFarSpace(IC_RIGHT(ic))) {
3677 operand *op = IC_RIGHT(ic);
3678 IC_RIGHT(ic) = IC_LEFT(ic);
3682 AOP_OP_3_NOFATAL (ic, pushResult);
3685 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3690 /* if literal, literal on the right or
3691 if left requires ACC or right is already
3693 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3694 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3695 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3697 operand *t = IC_RIGHT (ic);
3698 IC_RIGHT (ic) = IC_LEFT (ic);
3700 emitcode (";", "Swapped plus args.");
3703 /* if both left & right are in bit
3705 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3706 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3712 /* if left in bit space & right literal */
3713 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3714 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3716 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3717 /* if result in bit space */
3718 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3720 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3721 emitcode ("cpl", "c");
3722 outBitC (IC_RESULT (ic));
3726 size = getDataSize (IC_RESULT (ic));
3727 _startLazyDPSEvaluation ();
3730 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3731 emitcode ("addc", "a,#0");
3732 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3734 _endLazyDPSEvaluation ();
3739 /* if I can do an increment instead
3740 of add then GOOD for ME */
3741 if (genPlusIncr (ic) == TRUE)
3743 emitcode (";", "did genPlusIncr");
3748 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3750 _startLazyDPSEvaluation ();
3753 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3755 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3757 emitcode ("add", "a,%s",
3758 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3760 emitcode ("addc", "a,%s",
3761 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3765 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3767 /* right is going to use ACC or we would have taken the
3770 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3772 D(emitcode(";", "+ AOP_ACC special case."););
3773 emitcode("xch", "a, %s", DP2_RESULT_REG);
3775 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3778 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3781 emitcode("add", "a, %s", DP2_RESULT_REG);
3785 emitcode ("add", "a,%s",
3786 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3791 emitcode ("addc", "a,%s",
3792 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3797 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3801 emitcode ("push", "acc");
3805 _endLazyDPSEvaluation ();
3809 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3811 size = getDataSize (IC_LEFT (ic));
3812 rSize = getDataSize (IC_RESULT (ic));
3814 ADJUST_PUSHED_RESULT(size, rSize);
3816 _startLazyDPSEvaluation ();
3819 emitcode ("pop", "acc");
3820 aopPut (AOP (IC_RESULT (ic)), "a", size);
3822 _endLazyDPSEvaluation ();
3825 adjustArithmeticResult (ic);
3828 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3829 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3830 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3833 /*-----------------------------------------------------------------*/
3834 /* genMinusDec :- does subtraction with deccrement if possible */
3835 /*-----------------------------------------------------------------*/
3837 genMinusDec (iCode * ic)
3839 unsigned int icount;
3840 unsigned int size = getDataSize (IC_RESULT (ic));
3842 /* will try to generate an increment */
3843 /* if the right side is not a literal
3845 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3848 /* if the literal value of the right hand side
3849 is greater than 4 then it is not worth it */
3850 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3853 /* if decrement 16 bits in register */
3854 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3855 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3856 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3864 /* If the next instruction is a goto and the goto target
3865 * is <= 5 instructions previous to this, we can generate
3866 * jumps straight to that target.
3868 if (ic->next && ic->next->op == GOTO
3869 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3872 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3873 tlbl = IC_LABEL (ic->next);
3878 tlbl = newiTempLabel (NULL);
3882 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3883 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3884 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3885 IS_AOP_PREG (IC_RESULT (ic)))
3886 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3887 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3891 emitcode ("mov", "a,#!constbyte",0xff);
3892 emitcode ("cjne", "a,%s,!tlabel"
3893 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3896 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3899 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3900 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3901 IS_AOP_PREG (IC_RESULT (ic)))
3902 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3903 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3907 emitcode ("cjne", "a,%s,!tlabel"
3908 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3911 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3915 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3916 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3917 IS_AOP_PREG (IC_RESULT (ic)))
3918 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3919 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3923 emitcode ("cjne", "a,%s,!tlabel"
3924 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3927 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3931 emitcode ("", "!tlabeldef", tlbl->key + 100);
3936 /* if the sizes are greater than 1 then we cannot */
3937 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3938 AOP_SIZE (IC_LEFT (ic)) > 1)
3941 /* we can if the aops of the left & result match or
3942 if they are in registers and the registers are the
3945 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3946 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3947 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3950 _startLazyDPSEvaluation ();
3953 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3955 _endLazyDPSEvaluation ();
3963 /*-----------------------------------------------------------------*/
3964 /* addSign - complete with sign */
3965 /*-----------------------------------------------------------------*/
3967 addSign (operand * result, int offset, int sign)
3969 int size = (getDataSize (result) - offset);
3972 _startLazyDPSEvaluation();
3975 emitcode ("rlc", "a");
3976 emitcode ("subb", "a,acc");
3979 aopPut (AOP (result), "a", offset++);
3986 aopPut (AOP (result), zero, offset++);
3989 _endLazyDPSEvaluation();
3993 /*-----------------------------------------------------------------*/
3994 /* genMinusBits - generates code for subtraction of two bits */
3995 /*-----------------------------------------------------------------*/
3997 genMinusBits (iCode * ic)
3999 symbol *lbl = newiTempLabel (NULL);
4001 D (emitcode (";", "genMinusBits "););
4003 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4005 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4006 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4007 emitcode ("cpl", "c");
4008 emitcode ("", "!tlabeldef", (lbl->key + 100));
4009 outBitC (IC_RESULT (ic));
4013 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4014 emitcode ("subb", "a,acc");
4015 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4016 emitcode ("inc", "a");
4017 emitcode ("", "!tlabeldef", (lbl->key + 100));
4018 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4019 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4023 /*-----------------------------------------------------------------*/
4024 /* genMinus - generates code for subtraction */
4025 /*-----------------------------------------------------------------*/
4027 genMinus (iCode * ic)
4029 int size, offset = 0;
4031 unsigned long lit = 0L;
4032 bool pushResult = FALSE;
4034 D (emitcode (";", "genMinus "););
4036 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4037 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4038 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4039 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4045 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4047 /* special cases :- */
4048 /* if both left & right are in bit space */
4049 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4050 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4056 /* if I can do an decrement instead
4057 of subtract then GOOD for ME */
4058 if (genMinusDec (ic) == TRUE)
4063 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4065 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4071 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4076 /* if literal, add a,#-lit, else normal subb */
4077 _startLazyDPSEvaluation ();
4080 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4081 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4082 emitcode ("subb", "a,%s",
4083 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4086 /* first add without previous c */
4088 if (!size && lit==-1) {
4089 emitcode ("dec", "a");
4091 emitcode ("add", "a,#!constbyte",
4092 (unsigned int) (lit & 0x0FFL));
4095 emitcode ("addc", "a,#!constbyte",
4096 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4102 emitcode ("push", "acc");
4106 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4110 _endLazyDPSEvaluation ();
4114 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4116 size = getDataSize (IC_LEFT (ic));
4117 rSize = getDataSize (IC_RESULT (ic));
4119 ADJUST_PUSHED_RESULT(size, rSize);
4121 _startLazyDPSEvaluation ();
4124 emitcode ("pop", "acc");
4125 aopPut (AOP (IC_RESULT (ic)), "a", size);
4127 _endLazyDPSEvaluation ();
4130 adjustArithmeticResult (ic);
4133 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4134 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4135 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4139 /*-----------------------------------------------------------------*/
4140 /* genMultbits :- multiplication of bits */
4141 /*-----------------------------------------------------------------*/
4143 genMultbits (operand * left,
4148 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4149 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4150 aopOp(result, ic, TRUE, FALSE);
4155 /*-----------------------------------------------------------------*/
4156 /* genMultOneByte : 8*8=8/16 bit multiplication */
4157 /*-----------------------------------------------------------------*/
4159 genMultOneByte (operand * left,
4164 sym_link *opetype = operandType (result);
4168 /* (if two literals: the value is computed before) */
4169 /* if one literal, literal on the right */
4170 if (AOP_TYPE (left) == AOP_LIT)
4175 emitcode (";", "swapped left and right");
4178 if (SPEC_USIGN(opetype)
4179 // ignore the sign of left and right, what else can we do?
4180 || (SPEC_USIGN(operandType(left)) &&
4181 SPEC_USIGN(operandType(right)))) {
4182 // just an unsigned 8*8=8/16 multiply
4183 //emitcode (";","unsigned");
4184 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4185 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4186 emitcode ("mul", "ab");
4188 _G.accInUse++; _G.bInUse++;
4189 aopOp(result, ic, TRUE, FALSE);
4191 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4193 // this should never happen
4194 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4195 AOP_SIZE(result), __FILE__, lineno);
4199 aopPut (AOP (result), "a", 0);
4200 _G.accInUse--; _G.bInUse--;
4201 if (AOP_SIZE(result)==2)
4203 aopPut (AOP (result), "b", 1);
4208 // we have to do a signed multiply
4210 emitcode (";", "signed");
4211 emitcode ("clr", "F0"); // reset sign flag
4212 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4214 lbl=newiTempLabel(NULL);
4215 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4216 // left side is negative, 8-bit two's complement, this fails for -128
4217 emitcode ("setb", "F0"); // set sign flag
4218 emitcode ("cpl", "a");
4219 emitcode ("inc", "a");
4221 emitcode ("", "!tlabeldef", lbl->key+100);
4224 if (AOP_TYPE(right)==AOP_LIT) {
4225 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4226 /* AND literal negative */
4227 if ((int) val < 0) {
4228 emitcode ("cpl", "F0"); // complement sign flag
4229 emitcode ("mov", "b,#!constbyte", -val);
4231 emitcode ("mov", "b,#!constbyte", val);
4234 lbl=newiTempLabel(NULL);
4235 emitcode ("mov", "b,a");
4236 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4237 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4238 // right side is negative, 8-bit two's complement
4239 emitcode ("cpl", "F0"); // complement sign flag
4240 emitcode ("cpl", "a");
4241 emitcode ("inc", "a");
4242 emitcode ("", "!tlabeldef", lbl->key+100);
4244 emitcode ("mul", "ab");
4246 _G.accInUse++;_G.bInUse++;
4247 aopOp(result, ic, TRUE, FALSE);
4249 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4251 // this should never happen
4252 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4253 AOP_SIZE(result), __FILE__, lineno);
4257 lbl=newiTempLabel(NULL);
4258 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4259 // only ONE op was negative, we have to do a 8/16-bit two's complement
4260 emitcode ("cpl", "a"); // lsb
4261 if (AOP_SIZE(result)==1) {
4262 emitcode ("inc", "a");
4264 emitcode ("add", "a,#1");
4265 emitcode ("xch", "a,b");
4266 emitcode ("cpl", "a"); // msb
4267 emitcode ("addc", "a,#0");
4268 emitcode ("xch", "a,b");
4271 emitcode ("", "!tlabeldef", lbl->key+100);
4272 aopPut (AOP (result), "a", 0);
4273 _G.accInUse--;_G.bInUse--;
4274 if (AOP_SIZE(result)==2) {
4275 aopPut (AOP (result), "b", 1);
4279 /*-----------------------------------------------------------------*/
4280 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4281 /*-----------------------------------------------------------------*/
4282 static void genMultTwoByte (operand *left, operand *right,
4283 operand *result, iCode *ic)
4285 sym_link *retype = getSpec(operandType(right));
4286 sym_link *letype = getSpec(operandType(left));
4287 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4290 if (AOP_TYPE (left) == AOP_LIT) {
4295 /* save EA bit in F1 */
4296 lbl = newiTempLabel(NULL);
4297 emitcode ("setb","F1");
4298 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4299 emitcode ("clr","F1");
4300 emitcode("","!tlabeldef",lbl->key+100);
4302 /* load up MB with right */
4304 emitcode("clr","F0");
4305 if (AOP_TYPE(right) == AOP_LIT) {
4306 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4308 emitcode("setb","F0");
4311 emitcode ("mov","mb,#!constbyte",val & 0xff);
4312 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4314 lbl = newiTempLabel(NULL);
4315 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4316 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4317 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4318 emitcode ("xch", "a,b");
4319 emitcode ("cpl","a");
4320 emitcode ("add", "a,#1");
4321 emitcode ("xch", "a,b");
4322 emitcode ("cpl", "a"); // msb
4323 emitcode ("addc", "a,#0");
4324 emitcode ("setb","F0");
4325 emitcode ("","!tlabeldef",lbl->key+100);
4326 emitcode ("mov","mb,b");
4327 emitcode ("mov","mb,a");
4330 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4331 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4333 /* load up MA with left */
4335 lbl = newiTempLabel(NULL);
4336 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4337 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4338 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4339 emitcode ("xch", "a,b");
4340 emitcode ("cpl","a");
4341 emitcode ("add", "a,#1");
4342 emitcode ("xch", "a,b");
4343 emitcode ("cpl", "a"); // msb
4344 emitcode ("addc","a,#0");
4345 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4346 emitcode ("setb","F0");
4347 emitcode ("","!tlabeldef",lbl->key+100);
4348 emitcode ("mov","ma,b");
4349 emitcode ("mov","ma,a");
4351 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4352 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4354 /* wait for multiplication to finish */
4355 lbl = newiTempLabel(NULL);
4356 emitcode("","!tlabeldef", lbl->key+100);
4357 emitcode("mov","a,mcnt1");
4358 emitcode("anl","a,#!constbyte",0x80);
4359 emitcode("jnz","!tlabel",lbl->key+100);
4361 freeAsmop (left, NULL, ic, TRUE);
4362 freeAsmop (right, NULL, ic,TRUE);
4363 aopOp(result, ic, TRUE, FALSE);
4365 /* if unsigned then simple */
4367 emitcode ("mov","a,ma");
4368 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4369 emitcode ("mov","a,ma");
4370 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4371 aopPut(AOP(result),"ma",1);
4372 aopPut(AOP(result),"ma",0);
4374 emitcode("push","ma");
4375 emitcode("push","ma");
4376 emitcode("push","ma");
4378 /* negate result if needed */
4379 lbl = newiTempLabel(NULL);
4380 emitcode("jnb","F0,!tlabel",lbl->key+100);
4381 emitcode("cpl","a");
4382 emitcode("add","a,#1");
4383 emitcode("","!tlabeldef", lbl->key+100);
4384 if (AOP_TYPE(result) == AOP_ACC)
4386 D(emitcode(";", "ACC special case."););
4387 /* We know result is the only live aop, and
4388 * it's obviously not a DPTR2, so AP is available.
4390 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4394 aopPut(AOP(result),"a",0);
4397 emitcode("pop","acc");
4398 lbl = newiTempLabel(NULL);
4399 emitcode("jnb","F0,!tlabel",lbl->key+100);
4400 emitcode("cpl","a");
4401 emitcode("addc","a,#0");
4402 emitcode("","!tlabeldef", lbl->key+100);
4403 aopPut(AOP(result),"a",1);
4404 emitcode("pop","acc");
4405 if (AOP_SIZE(result) >= 3) {
4406 lbl = newiTempLabel(NULL);
4407 emitcode("jnb","F0,!tlabel",lbl->key+100);
4408 emitcode("cpl","a");
4409 emitcode("addc","a,#0");
4410 emitcode("","!tlabeldef", lbl->key+100);
4411 aopPut(AOP(result),"a",2);
4413 emitcode("pop","acc");
4414 if (AOP_SIZE(result) >= 4) {
4415 lbl = newiTempLabel(NULL);
4416 emitcode("jnb","F0,!tlabel",lbl->key+100);
4417 emitcode("cpl","a");
4418 emitcode("addc","a,#0");
4419 emitcode("","!tlabeldef", lbl->key+100);
4420 aopPut(AOP(result),"a",3);
4422 if (AOP_TYPE(result) == AOP_ACC)
4424 /* We stashed the result away above. */
4425 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4429 freeAsmop (result, NULL, ic, TRUE);
4431 /* restore EA bit in F1 */
4432 lbl = newiTempLabel(NULL);
4433 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4434 emitcode ("setb","EA");
4435 emitcode("","!tlabeldef",lbl->key+100);
4439 /*-----------------------------------------------------------------*/
4440 /* genMult - generates code for multiplication */
4441 /*-----------------------------------------------------------------*/
4443 genMult (iCode * ic)
4445 operand *left = IC_LEFT (ic);
4446 operand *right = IC_RIGHT (ic);
4447 operand *result = IC_RESULT (ic);
4449 D (emitcode (";", "genMult "););
4451 /* assign the amsops */
4454 /* special cases first */
4456 if (AOP_TYPE (left) == AOP_CRY &&
4457 AOP_TYPE (right) == AOP_CRY)
4459 genMultbits (left, right, result, ic);
4463 /* if both are of size == 1 */
4464 if (AOP_SIZE (left) == 1 &&
4465 AOP_SIZE (right) == 1)
4467 genMultOneByte (left, right, result, ic);
4471 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4472 /* use the ds390 ARITHMETIC accel UNIT */
4473 genMultTwoByte (left, right, result, ic);
4476 /* should have been converted to function call */
4480 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4481 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4482 freeAsmop (result, NULL, ic, TRUE);
4485 /*-----------------------------------------------------------------*/
4486 /* genDivbits :- division of bits */
4487 /*-----------------------------------------------------------------*/
4489 genDivbits (operand * left,
4497 /* the result must be bit */
4498 LOAD_AB_FOR_DIV (left, right, l);
4499 emitcode ("div", "ab");
4500 emitcode ("rrc", "a");
4501 aopOp(result, ic, TRUE, FALSE);
4503 aopPut (AOP (result), "c", 0);
4506 /*-----------------------------------------------------------------*/
4507 /* genDivOneByte : 8 bit division */
4508 /*-----------------------------------------------------------------*/
4510 genDivOneByte (operand * left,
4515 sym_link *opetype = operandType (result);
4521 /* signed or unsigned */
4522 if (SPEC_USIGN (opetype))
4524 /* unsigned is easy */
4525 LOAD_AB_FOR_DIV (left, right, l);
4526 emitcode ("div", "ab");
4529 aopOp(result, ic, TRUE, FALSE);
4530 aopPut (AOP (result), "a", 0);
4533 size = AOP_SIZE (result) - 1;
4537 aopPut (AOP (result), zero, offset++);
4542 /* signed is a little bit more difficult */
4544 /* save the signs of the operands */
4545 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4547 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4548 emitcode ("push", "acc"); /* save it on the stack */
4550 /* now sign adjust for both left & right */
4551 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4553 lbl = newiTempLabel (NULL);
4554 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4555 emitcode ("cpl", "a");
4556 emitcode ("inc", "a");
4557 emitcode ("", "!tlabeldef", (lbl->key + 100));
4558 emitcode ("mov", "b,a");
4560 /* sign adjust left side */
4561 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4564 lbl = newiTempLabel (NULL);
4565 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4566 emitcode ("cpl", "a");
4567 emitcode ("inc", "a");
4568 emitcode ("", "!tlabeldef", (lbl->key + 100));
4570 /* now the division */
4571 emitcode ("nop", "; workaround for DS80C390 div bug.");
4572 emitcode ("div", "ab");
4573 /* we are interested in the lower order
4575 emitcode ("mov", "b,a");
4576 lbl = newiTempLabel (NULL);
4577 emitcode ("pop", "acc");
4578 /* if there was an over flow we don't
4579 adjust the sign of the result */
4580 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4581 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4583 emitcode ("clr", "a");
4584 emitcode ("subb", "a,b");
4585 emitcode ("mov", "b,a");
4586 emitcode ("", "!tlabeldef", (lbl->key + 100));
4588 /* now we are done */
4589 _G.accInUse++; _G.bInUse++;
4590 aopOp(result, ic, TRUE, FALSE);
4592 aopPut (AOP (result), "b", 0);
4594 size = AOP_SIZE (result) - 1;
4598 emitcode ("mov", "c,b.7");
4599 emitcode ("subb", "a,acc");
4603 aopPut (AOP (result), "a", offset++);
4605 _G.accInUse--; _G.bInUse--;
4609 /*-----------------------------------------------------------------*/
4610 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4611 /*-----------------------------------------------------------------*/
4612 static void genDivTwoByte (operand *left, operand *right,
4613 operand *result, iCode *ic)
4615 sym_link *retype = getSpec(operandType(right));
4616 sym_link *letype = getSpec(operandType(left));
4617 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4620 /* save EA bit in F1 */
4621 lbl = newiTempLabel(NULL);
4622 emitcode ("setb","F1");
4623 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4624 emitcode ("clr","F1");
4625 emitcode("","!tlabeldef",lbl->key+100);
4627 /* load up MA with left */
4629 emitcode("clr","F0");
4630 lbl = newiTempLabel(NULL);
4631 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4632 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4633 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4634 emitcode ("xch", "a,b");
4635 emitcode ("cpl","a");
4636 emitcode ("add", "a,#1");
4637 emitcode ("xch", "a,b");
4638 emitcode ("cpl", "a"); // msb
4639 emitcode ("addc","a,#0");
4640 emitcode ("setb","F0");
4641 emitcode ("","!tlabeldef",lbl->key+100);
4642 emitcode ("mov","ma,b");
4643 emitcode ("mov","ma,a");
4645 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4646 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4649 /* load up MB with right */
4651 if (AOP_TYPE(right) == AOP_LIT) {
4652 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4654 lbl = newiTempLabel(NULL);
4655 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4656 emitcode("setb","F0");
4657 emitcode ("","!tlabeldef",lbl->key+100);
4660 emitcode ("mov","mb,#!constbyte",val & 0xff);
4661 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4663 lbl = newiTempLabel(NULL);
4664 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4665 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4666 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4667 emitcode ("xch", "a,b");
4668 emitcode ("cpl","a");
4669 emitcode ("add", "a,#1");
4670 emitcode ("xch", "a,b");
4671 emitcode ("cpl", "a"); // msb
4672 emitcode ("addc", "a,#0");
4673 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4674 emitcode ("setb","F0");
4675 emitcode ("","!tlabeldef",lbl->key+100);
4676 emitcode ("mov","mb,b");
4677 emitcode ("mov","mb,a");
4680 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4681 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4684 /* wait for multiplication to finish */
4685 lbl = newiTempLabel(NULL);
4686 emitcode("","!tlabeldef", lbl->key+100);
4687 emitcode("mov","a,mcnt1");
4688 emitcode("anl","a,#!constbyte",0x80);
4689 emitcode("jnz","!tlabel",lbl->key+100);
4691 freeAsmop (left, NULL, ic, TRUE);
4692 freeAsmop (right, NULL, ic,TRUE);
4693 aopOp(result, ic, TRUE, FALSE);
4695 /* if unsigned then simple */
4697 aopPut(AOP(result),"ma",1);
4698 aopPut(AOP(result),"ma",0);
4700 emitcode("push","ma");
4702 /* negate result if needed */
4703 lbl = newiTempLabel(NULL);
4704 emitcode("jnb","F0,!tlabel",lbl->key+100);
4705 emitcode("cpl","a");
4706 emitcode("add","a,#1");
4707 emitcode("","!tlabeldef", lbl->key+100);
4708 aopPut(AOP(result),"a",0);
4709 emitcode("pop","acc");
4710 lbl = newiTempLabel(NULL);
4711 emitcode("jnb","F0,!tlabel",lbl->key+100);
4712 emitcode("cpl","a");
4713 emitcode("addc","a,#0");
4714 emitcode("","!tlabeldef", lbl->key+100);
4715 aopPut(AOP(result),"a",1);
4717 freeAsmop (result, NULL, ic, TRUE);
4718 /* restore EA bit in F1 */
4719 lbl = newiTempLabel(NULL);
4720 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4721 emitcode ("setb","EA");
4722 emitcode("","!tlabeldef",lbl->key+100);
4726 /*-----------------------------------------------------------------*/
4727 /* genDiv - generates code for division */
4728 /*-----------------------------------------------------------------*/
4732 operand *left = IC_LEFT (ic);
4733 operand *right = IC_RIGHT (ic);
4734 operand *result = IC_RESULT (ic);
4736 D (emitcode (";", "genDiv "););
4738 /* assign the amsops */
4741 /* special cases first */
4743 if (AOP_TYPE (left) == AOP_CRY &&
4744 AOP_TYPE (right) == AOP_CRY)
4746 genDivbits (left, right, result, ic);
4750 /* if both are of size == 1 */
4751 if (AOP_SIZE (left) == 1 &&
4752 AOP_SIZE (right) == 1)
4754 genDivOneByte (left, right, result, ic);
4758 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4759 /* use the ds390 ARITHMETIC accel UNIT */
4760 genDivTwoByte (left, right, result, ic);
4763 /* should have been converted to function call */
4766 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4767 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4768 freeAsmop (result, NULL, ic, TRUE);
4771 /*-----------------------------------------------------------------*/
4772 /* genModbits :- modulus of bits */
4773 /*-----------------------------------------------------------------*/
4775 genModbits (operand * left,
4783 /* the result must be bit */
4784 LOAD_AB_FOR_DIV (left, right, l);
4785 emitcode ("div", "ab");
4786 emitcode ("mov", "a,b");
4787 emitcode ("rrc", "a");
4788 aopOp(result, ic, TRUE, FALSE);
4789 aopPut (AOP (result), "c", 0);
4792 /*-----------------------------------------------------------------*/
4793 /* genModOneByte : 8 bit modulus */
4794 /*-----------------------------------------------------------------*/
4796 genModOneByte (operand * left,
4801 sym_link *opetype = operandType (result);
4805 /* signed or unsigned */
4806 if (SPEC_USIGN (opetype))
4808 /* unsigned is easy */
4809 LOAD_AB_FOR_DIV (left, right, l);
4810 emitcode ("div", "ab");
4811 aopOp(result, ic, TRUE, FALSE);
4812 aopPut (AOP (result), "b", 0);
4816 /* signed is a little bit more difficult */
4818 /* save the signs of the operands */
4819 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4822 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4823 emitcode ("push", "acc"); /* save it on the stack */
4825 /* now sign adjust for both left & right */
4826 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4829 lbl = newiTempLabel (NULL);
4830 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4831 emitcode ("cpl", "a");
4832 emitcode ("inc", "a");
4833 emitcode ("", "!tlabeldef", (lbl->key + 100));
4834 emitcode ("mov", "b,a");
4836 /* sign adjust left side */
4837 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4840 lbl = newiTempLabel (NULL);
4841 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4842 emitcode ("cpl", "a");
4843 emitcode ("inc", "a");
4844 emitcode ("", "!tlabeldef", (lbl->key + 100));
4846 /* now the multiplication */
4847 emitcode ("nop", "; workaround for DS80C390 div bug.");
4848 emitcode ("div", "ab");
4849 /* we are interested in the lower order
4851 lbl = newiTempLabel (NULL);
4852 emitcode ("pop", "acc");
4853 /* if there was an over flow we don't
4854 adjust the sign of the result */
4855 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4856 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4858 emitcode ("clr", "a");
4859 emitcode ("subb", "a,b");
4860 emitcode ("mov", "b,a");
4861 emitcode ("", "!tlabeldef", (lbl->key + 100));
4864 /* now we are done */
4865 aopOp(result, ic, TRUE, FALSE);
4866 aopPut (AOP (result), "b", 0);
4871 /*-----------------------------------------------------------------*/
4872 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4873 /*-----------------------------------------------------------------*/
4874 static void genModTwoByte (operand *left, operand *right,
4875 operand *result, iCode *ic)
4877 sym_link *retype = getSpec(operandType(right));
4878 sym_link *letype = getSpec(operandType(left));
4879 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4882 /* load up MA with left */
4883 /* save EA bit in F1 */
4884 lbl = newiTempLabel(NULL);
4885 emitcode ("setb","F1");
4886 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4887 emitcode ("clr","F1");
4888 emitcode("","!tlabeldef",lbl->key+100);
4891 lbl = newiTempLabel(NULL);
4892 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4893 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4894 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4895 emitcode ("xch", "a,b");
4896 emitcode ("cpl","a");
4897 emitcode ("add", "a,#1");
4898 emitcode ("xch", "a,b");
4899 emitcode ("cpl", "a"); // msb
4900 emitcode ("addc","a,#0");
4901 emitcode ("","!tlabeldef",lbl->key+100);
4902 emitcode ("mov","ma,b");
4903 emitcode ("mov","ma,a");
4905 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4906 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4909 /* load up MB with right */
4911 if (AOP_TYPE(right) == AOP_LIT) {
4912 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4916 emitcode ("mov","mb,#!constbyte",val & 0xff);
4917 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4919 lbl = newiTempLabel(NULL);
4920 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4921 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4922 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4923 emitcode ("xch", "a,b");
4924 emitcode ("cpl","a");
4925 emitcode ("add", "a,#1");
4926 emitcode ("xch", "a,b");
4927 emitcode ("cpl", "a"); // msb
4928 emitcode ("addc", "a,#0");
4929 emitcode ("","!tlabeldef",lbl->key+100);
4930 emitcode ("mov","mb,b");
4931 emitcode ("mov","mb,a");
4934 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4935 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4938 /* wait for multiplication to finish */
4939 lbl = newiTempLabel(NULL);
4940 emitcode("","!tlabeldef", lbl->key+100);
4941 emitcode("mov","a,mcnt1");
4942 emitcode("anl","a,#!constbyte",0x80);
4943 emitcode("jnz","!tlabel",lbl->key+100);
4945 freeAsmop (left, NULL, ic, TRUE);
4946 freeAsmop (right, NULL, ic,TRUE);
4947 aopOp(result, ic, TRUE, FALSE);
4949 aopPut(AOP(result),"mb",1);
4950 aopPut(AOP(result),"mb",0);
4951 freeAsmop (result, NULL, ic, TRUE);
4953 /* restore EA bit in F1 */
4954 lbl = newiTempLabel(NULL);
4955 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4956 emitcode ("setb","EA");
4957 emitcode("","!tlabeldef",lbl->key+100);
4961 /*-----------------------------------------------------------------*/
4962 /* genMod - generates code for division */
4963 /*-----------------------------------------------------------------*/
4967 operand *left = IC_LEFT (ic);
4968 operand *right = IC_RIGHT (ic);
4969 operand *result = IC_RESULT (ic);
4971 D (emitcode (";", "genMod "); );
4973 /* assign the amsops */
4976 /* special cases first */
4978 if (AOP_TYPE (left) == AOP_CRY &&
4979 AOP_TYPE (right) == AOP_CRY)
4981 genModbits (left, right, result, ic);
4985 /* if both are of size == 1 */
4986 if (AOP_SIZE (left) == 1 &&
4987 AOP_SIZE (right) == 1)
4989 genModOneByte (left, right, result, ic);
4993 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4994 /* use the ds390 ARITHMETIC accel UNIT */
4995 genModTwoByte (left, right, result, ic);
4999 /* should have been converted to function call */
5003 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5004 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5005 freeAsmop (result, NULL, ic, TRUE);
5008 /*-----------------------------------------------------------------*/
5009 /* genIfxJump :- will create a jump depending on the ifx */
5010 /*-----------------------------------------------------------------*/
5012 genIfxJump (iCode * ic, char *jval)
5015 symbol *tlbl = newiTempLabel (NULL);
5018 D (emitcode (";", "genIfxJump ");
5021 /* if true label then we jump if condition
5025 jlbl = IC_TRUE (ic);
5026 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5027 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5031 /* false label is present */
5032 jlbl = IC_FALSE (ic);
5033 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5034 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5036 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5037 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5039 emitcode (inst, "!tlabel", tlbl->key + 100);
5040 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5041 emitcode ("", "!tlabeldef", tlbl->key + 100);
5043 /* mark the icode as generated */
5047 /*-----------------------------------------------------------------*/
5048 /* genCmp :- greater or less than comparison */
5049 /*-----------------------------------------------------------------*/
5051 genCmp (operand * left, operand * right,
5052 iCode * ic, iCode * ifx, int sign)
5054 int size, offset = 0;
5055 unsigned long lit = 0L;
5058 D (emitcode (";", "genCmp");
5061 result = IC_RESULT (ic);
5063 /* if left & right are bit variables */
5064 if (AOP_TYPE (left) == AOP_CRY &&
5065 AOP_TYPE (right) == AOP_CRY)
5067 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5068 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5072 /* subtract right from left if at the
5073 end the carry flag is set then we know that
5074 left is greater than right */
5075 size = max (AOP_SIZE (left), AOP_SIZE (right));
5077 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5078 if ((size == 1) && !sign &&
5079 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5081 symbol *lbl = newiTempLabel (NULL);
5082 emitcode ("cjne", "%s,%s,!tlabel",
5083 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5084 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5086 emitcode ("", "!tlabeldef", lbl->key + 100);
5090 if (AOP_TYPE (right) == AOP_LIT)
5092 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5093 /* optimize if(x < 0) or if(x >= 0) */
5102 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5104 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5105 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5107 aopOp (result, ic, FALSE, FALSE);
5109 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5111 freeAsmop (result, NULL, ic, TRUE);
5112 genIfxJump (ifx, "acc.7");
5117 emitcode ("rlc", "a");
5119 goto release_freedLR;
5127 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5128 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5129 //emitcode (";", "genCmp #2");
5130 if (sign && (size == 0))
5132 //emitcode (";", "genCmp #3");
5133 emitcode ("xrl", "a,#!constbyte",0x80);
5134 if (AOP_TYPE (right) == AOP_LIT)
5136 unsigned long lit = (unsigned long)
5137 floatFromVal (AOP (right)->aopu.aop_lit);
5138 //emitcode (";", "genCmp #3.1");
5139 emitcode ("subb", "a,#!constbyte",
5140 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5144 //emitcode (";", "genCmp #3.2");
5145 if (AOP_NEEDSACC (right))
5147 emitcode ("push", "acc");
5149 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5150 FALSE, FALSE, FALSE));
5151 emitcode ("xrl", "b,#!constbyte",0x80);
5152 if (AOP_NEEDSACC (right))
5154 emitcode ("pop", "acc");
5156 emitcode ("subb", "a,b");
5163 //emitcode (";", "genCmp #4");
5164 if (AOP_NEEDSACC (right))
5167 //emitcode (";", "genCmp #4.1");
5168 emitcode ("xch", "a, b");
5169 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5170 emitcode ("xch", "a, b");
5175 //emitcode (";", "genCmp #4.2");
5176 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5179 emitcode ("subb", "a,%s", s);
5186 /* Don't need the left & right operands any more; do need the result. */
5187 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5188 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5190 aopOp (result, ic, FALSE, FALSE);
5194 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5200 /* if the result is used in the next
5201 ifx conditional branch then generate
5202 code a little differently */
5205 genIfxJump (ifx, "c");
5211 /* leave the result in acc */
5213 freeAsmop (result, NULL, ic, TRUE);
5216 /*-----------------------------------------------------------------*/
5217 /* genCmpGt :- greater than comparison */
5218 /*-----------------------------------------------------------------*/
5220 genCmpGt (iCode * ic, iCode * ifx)
5222 operand *left, *right;
5223 sym_link *letype, *retype;
5226 D (emitcode (";", "genCmpGt ");
5229 left = IC_LEFT (ic);
5230 right = IC_RIGHT (ic);
5232 letype = getSpec (operandType (left));
5233 retype = getSpec (operandType (right));
5234 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5236 /* assign the left & right amsops */
5239 genCmp (right, left, ic, ifx, sign);
5242 /*-----------------------------------------------------------------*/
5243 /* genCmpLt - less than comparisons */
5244 /*-----------------------------------------------------------------*/
5246 genCmpLt (iCode * ic, iCode * ifx)
5248 operand *left, *right;
5249 sym_link *letype, *retype;
5252 D (emitcode (";", "genCmpLt "););
5254 left = IC_LEFT (ic);
5255 right = IC_RIGHT (ic);
5257 letype = getSpec (operandType (left));
5258 retype = getSpec (operandType (right));
5259 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5261 /* assign the left & right amsops */
5264 genCmp (left, right, ic, ifx, sign);
5267 /*-----------------------------------------------------------------*/
5268 /* gencjneshort - compare and jump if not equal */
5269 /*-----------------------------------------------------------------*/
5271 gencjneshort (operand * left, operand * right, symbol * lbl)
5273 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5275 unsigned long lit = 0L;
5277 D (emitcode (";", "gencjneshort");
5280 /* if the left side is a literal or
5281 if the right is in a pointer register and left
5283 if ((AOP_TYPE (left) == AOP_LIT) ||
5284 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5291 if (AOP_TYPE (right) == AOP_LIT)
5292 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5294 if (opIsGptr (left) || opIsGptr (right))
5296 /* We are comparing a generic pointer to something.
5297 * Exclude the generic type byte from the comparison.
5300 D (emitcode (";", "cjneshort: generic ptr special case.");
5305 /* if the right side is a literal then anything goes */
5306 if (AOP_TYPE (right) == AOP_LIT &&
5307 AOP_TYPE (left) != AOP_DIR)
5311 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5313 emitcode ("cjne", "a,%s,!tlabel",
5314 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5320 /* if the right side is in a register or in direct space or
5321 if the left is a pointer register & right is not */
5322 else if (AOP_TYPE (right) == AOP_REG ||
5323 AOP_TYPE (right) == AOP_DIR ||
5324 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5325 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5329 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5330 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5331 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5332 emitcode ("jnz", "!tlabel", lbl->key + 100);
5334 emitcode ("cjne", "a,%s,!tlabel",
5335 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5342 /* right is a pointer reg need both a & b */
5345 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5346 if (strcmp (l, "b"))
5347 emitcode ("mov", "b,%s", l);
5348 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5349 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5355 /*-----------------------------------------------------------------*/
5356 /* gencjne - compare and jump if not equal */
5357 /*-----------------------------------------------------------------*/
5359 gencjne (operand * left, operand * right, symbol * lbl)
5361 symbol *tlbl = newiTempLabel (NULL);
5363 D (emitcode (";", "gencjne");
5366 gencjneshort (left, right, lbl);
5368 emitcode ("mov", "a,%s", one);
5369 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5370 emitcode ("", "!tlabeldef", lbl->key + 100);
5371 emitcode ("clr", "a");
5372 emitcode ("", "!tlabeldef", tlbl->key + 100);
5375 /*-----------------------------------------------------------------*/
5376 /* genCmpEq - generates code for equal to */
5377 /*-----------------------------------------------------------------*/
5379 genCmpEq (iCode * ic, iCode * ifx)
5381 operand *left, *right, *result;
5383 D (emitcode (";", "genCmpEq ");
5387 AOP_SET_LOCALS (ic);
5389 /* if literal, literal on the right or
5390 if the right is in a pointer register and left
5392 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5393 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5395 operand *t = IC_RIGHT (ic);
5396 IC_RIGHT (ic) = IC_LEFT (ic);
5400 if (ifx && /* !AOP_SIZE(result) */
5401 OP_SYMBOL (result) &&
5402 OP_SYMBOL (result)->regType == REG_CND)
5405 /* if they are both bit variables */
5406 if (AOP_TYPE (left) == AOP_CRY &&
5407 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5409 if (AOP_TYPE (right) == AOP_LIT)
5411 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5414 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5415 emitcode ("cpl", "c");
5419 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5423 emitcode ("clr", "c");
5425 /* AOP_TYPE(right) == AOP_CRY */
5429 symbol *lbl = newiTempLabel (NULL);
5430 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5431 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5432 emitcode ("cpl", "c");
5433 emitcode ("", "!tlabeldef", (lbl->key + 100));
5435 /* if true label then we jump if condition
5437 tlbl = newiTempLabel (NULL);
5440 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5441 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5445 emitcode ("jc", "!tlabel", tlbl->key + 100);
5446 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5448 emitcode ("", "!tlabeldef", tlbl->key + 100);
5452 tlbl = newiTempLabel (NULL);
5453 gencjneshort (left, right, tlbl);
5456 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5457 emitcode ("", "!tlabeldef", tlbl->key + 100);
5461 symbol *lbl = newiTempLabel (NULL);
5462 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5463 emitcode ("", "!tlabeldef", tlbl->key + 100);
5464 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5465 emitcode ("", "!tlabeldef", lbl->key + 100);
5468 /* mark the icode as generated */
5471 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5472 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476 /* if they are both bit variables */
5477 if (AOP_TYPE (left) == AOP_CRY &&
5478 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5480 if (AOP_TYPE (right) == AOP_LIT)
5482 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5485 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5486 emitcode ("cpl", "c");
5490 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5494 emitcode ("clr", "c");
5496 /* AOP_TYPE(right) == AOP_CRY */
5500 symbol *lbl = newiTempLabel (NULL);
5501 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5502 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5503 emitcode ("cpl", "c");
5504 emitcode ("", "!tlabeldef", (lbl->key + 100));
5507 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5510 aopOp (result, ic, TRUE, FALSE);
5513 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5520 genIfxJump (ifx, "c");
5523 /* if the result is used in an arithmetic operation
5524 then put the result in place */
5529 gencjne (left, right, newiTempLabel (NULL));
5531 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5532 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5534 aopOp (result, ic, TRUE, FALSE);
5536 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5538 aopPut (AOP (result), "a", 0);
5543 genIfxJump (ifx, "a");
5546 /* if the result is used in an arithmetic operation
5547 then put the result in place */
5548 if (AOP_TYPE (result) != AOP_CRY)
5550 /* leave the result in acc */
5554 freeAsmop (result, NULL, ic, TRUE);
5557 /*-----------------------------------------------------------------*/
5558 /* ifxForOp - returns the icode containing the ifx for operand */
5559 /*-----------------------------------------------------------------*/
5561 ifxForOp (operand * op, iCode * ic)
5563 /* if true symbol then needs to be assigned */
5564 if (IS_TRUE_SYMOP (op))
5567 /* if this has register type condition and
5568 the next instruction is ifx with the same operand
5569 and live to of the operand is upto the ifx only then */
5571 ic->next->op == IFX &&
5572 IC_COND (ic->next)->key == op->key &&
5573 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5578 /*-----------------------------------------------------------------*/
5579 /* hasInc - operand is incremented before any other use */
5580 /*-----------------------------------------------------------------*/
5582 hasInc (operand *op, iCode *ic)
5584 sym_link *type = operandType(op);
5585 sym_link *retype = getSpec (type);
5586 iCode *lic = ic->next;
5589 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5590 if (!IS_SYMOP(op)) return NULL;
5592 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5593 isize = getSize(type->next);
5595 /* if operand of the form op = op + <sizeof *op> */
5596 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5597 isOperandEqual(IC_RESULT(lic),op) &&
5598 isOperandLiteral(IC_RIGHT(lic)) &&
5599 operandLitValue(IC_RIGHT(lic)) == isize) {
5602 /* if the operand used or deffed */
5603 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5606 /* if GOTO or IFX */
5607 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5613 /*-----------------------------------------------------------------*/
5614 /* genAndOp - for && operation */
5615 /*-----------------------------------------------------------------*/
5617 genAndOp (iCode * ic)
5619 operand *left, *right, *result;
5622 D (emitcode (";", "genAndOp "););
5624 /* note here that && operations that are in an
5625 if statement are taken away by backPatchLabels
5626 only those used in arthmetic operations remain */
5628 AOP_SET_LOCALS (ic);
5630 /* if both are bit variables */
5631 if (AOP_TYPE (left) == AOP_CRY &&
5632 AOP_TYPE (right) == AOP_CRY)
5634 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5635 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5636 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5637 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5639 aopOp (result,ic,FALSE, FALSE);
5644 tlbl = newiTempLabel (NULL);
5646 emitcode ("jz", "!tlabel", tlbl->key + 100);
5648 emitcode ("", "!tlabeldef", tlbl->key + 100);
5649 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5650 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5652 aopOp (result,ic,FALSE, FALSE);
5655 freeAsmop (result, NULL, ic, TRUE);
5659 /*-----------------------------------------------------------------*/
5660 /* genOrOp - for || operation */
5661 /*-----------------------------------------------------------------*/
5663 genOrOp (iCode * ic)
5665 operand *left, *right, *result;
5668 D (emitcode (";", "genOrOp "););
5670 /* note here that || operations that are in an
5671 if statement are taken away by backPatchLabels
5672 only those used in arthmetic operations remain */
5674 AOP_SET_LOCALS (ic);
5676 /* if both are bit variables */
5677 if (AOP_TYPE (left) == AOP_CRY &&
5678 AOP_TYPE (right) == AOP_CRY)
5680 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5681 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5682 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5683 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5685 aopOp (result,ic,FALSE, FALSE);
5691 tlbl = newiTempLabel (NULL);
5693 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5695 emitcode ("", "!tlabeldef", tlbl->key + 100);
5696 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5697 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5699 aopOp (result,ic,FALSE, FALSE);
5704 freeAsmop (result, NULL, ic, TRUE);
5707 /*-----------------------------------------------------------------*/
5708 /* isLiteralBit - test if lit == 2^n */
5709 /*-----------------------------------------------------------------*/
5711 isLiteralBit (unsigned long lit)
5713 unsigned long pw[32] =
5714 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5715 0x100L, 0x200L, 0x400L, 0x800L,
5716 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5717 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5718 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5719 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5720 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5723 for (idx = 0; idx < 32; idx++)
5729 /*-----------------------------------------------------------------*/
5730 /* continueIfTrue - */
5731 /*-----------------------------------------------------------------*/
5733 continueIfTrue (iCode * ic)
5736 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5740 /*-----------------------------------------------------------------*/
5742 /*-----------------------------------------------------------------*/
5744 jumpIfTrue (iCode * ic)
5747 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5751 /*-----------------------------------------------------------------*/
5752 /* jmpTrueOrFalse - */
5753 /*-----------------------------------------------------------------*/
5755 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5757 // ugly but optimized by peephole
5760 symbol *nlbl = newiTempLabel (NULL);
5761 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5762 emitcode ("", "!tlabeldef", tlbl->key + 100);
5763 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5764 emitcode ("", "!tlabeldef", nlbl->key + 100);
5768 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5769 emitcode ("", "!tlabeldef", tlbl->key + 100);
5774 // Generate code to perform a bit-wise logic operation
5775 // on two operands in far space (assumed to already have been
5776 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5777 // in far space. This requires pushing the result on the stack
5778 // then popping it into the result.
5780 genFarFarLogicOp(iCode *ic, char *logicOp)
5782 int size, resultSize, compSize;
5786 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5787 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5788 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5790 _startLazyDPSEvaluation();
5791 for (size = compSize; (size--); offset++)
5793 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5794 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5795 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5797 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5798 emitcode ("push", "acc");
5800 _endLazyDPSEvaluation();
5802 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5803 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5804 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5806 resultSize = AOP_SIZE(IC_RESULT(ic));
5808 ADJUST_PUSHED_RESULT(compSize, resultSize);
5810 _startLazyDPSEvaluation();
5813 emitcode ("pop", "acc");
5814 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5816 _endLazyDPSEvaluation();
5817 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5821 /*-----------------------------------------------------------------*/
5822 /* genAnd - code for and */
5823 /*-----------------------------------------------------------------*/
5825 genAnd (iCode * ic, iCode * ifx)
5827 operand *left, *right, *result;
5828 int size, offset = 0;
5829 unsigned long lit = 0L;
5834 D (emitcode (";", "genAnd "););
5836 AOP_OP_3_NOFATAL (ic, pushResult);
5837 AOP_SET_LOCALS (ic);
5841 genFarFarLogicOp(ic, "anl");
5846 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5848 AOP_TYPE (left), AOP_TYPE (right));
5849 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5851 AOP_SIZE (left), AOP_SIZE (right));
5854 /* if left is a literal & right is not then exchange them */
5855 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5856 #ifdef LOGIC_OPS_BROKEN
5857 || AOP_NEEDSACC (left)
5861 operand *tmp = right;
5866 /* if result = right then exchange them */
5867 if (sameRegs (AOP (result), AOP (right)))
5869 operand *tmp = right;
5874 /* if right is bit then exchange them */
5875 if (AOP_TYPE (right) == AOP_CRY &&
5876 AOP_TYPE (left) != AOP_CRY)
5878 operand *tmp = right;
5882 if (AOP_TYPE (right) == AOP_LIT)
5883 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5885 size = AOP_SIZE (result);
5888 // result = bit & yy;
5889 if (AOP_TYPE (left) == AOP_CRY)
5891 // c = bit & literal;
5892 if (AOP_TYPE (right) == AOP_LIT)
5896 if (size && sameRegs (AOP (result), AOP (left)))
5899 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5904 if (size && (AOP_TYPE (result) == AOP_CRY))
5906 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5909 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5914 emitcode ("clr", "c");
5919 if (AOP_TYPE (right) == AOP_CRY)
5922 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5923 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5928 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5930 emitcode ("rrc", "a");
5931 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5939 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5940 genIfxJump (ifx, "c");
5944 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5945 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5946 if ((AOP_TYPE (right) == AOP_LIT) &&
5947 (AOP_TYPE (result) == AOP_CRY) &&
5948 (AOP_TYPE (left) != AOP_CRY))
5950 int posbit = isLiteralBit (lit);
5955 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5958 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5964 sprintf (buffer, "acc.%d", posbit & 0x07);
5965 genIfxJump (ifx, buffer);
5972 symbol *tlbl = newiTempLabel (NULL);
5973 int sizel = AOP_SIZE (left);
5975 emitcode ("setb", "c");
5978 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5980 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5982 if ((posbit = isLiteralBit (bytelit)) != 0)
5983 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5986 if (bytelit != 0x0FFL)
5987 emitcode ("anl", "a,%s",
5988 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5989 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5994 // bit = left & literal
5997 emitcode ("clr", "c");
5998 emitcode ("", "!tlabeldef", tlbl->key + 100);
6000 // if(left & literal)
6004 jmpTrueOrFalse (ifx, tlbl);
6012 /* if left is same as result */
6013 if (sameRegs (AOP (result), AOP (left)))
6015 for (; size--; offset++)
6017 if (AOP_TYPE (right) == AOP_LIT)
6019 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6021 else if (bytelit == 0)
6022 aopPut (AOP (result), zero, offset);
6023 else if (IS_AOP_PREG (result))
6025 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6026 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6027 aopPut (AOP (result), "a", offset);
6030 emitcode ("anl", "%s,%s",
6031 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6032 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6036 if (AOP_TYPE (left) == AOP_ACC)
6037 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6040 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6041 if (IS_AOP_PREG (result))
6043 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6044 aopPut (AOP (result), "a", offset);
6048 emitcode ("anl", "%s,a",
6049 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6056 // left & result in different registers
6057 if (AOP_TYPE (result) == AOP_CRY)
6060 // if(size), result in bit
6061 // if(!size && ifx), conditional oper: if(left & right)
6062 symbol *tlbl = newiTempLabel (NULL);
6063 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6065 emitcode ("setb", "c");
6068 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6069 emitcode ("anl", "a,%s",
6070 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6072 if (AOP_TYPE(left)==AOP_ACC) {
6073 emitcode("mov", "b,a");
6074 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6075 emitcode("anl", "a,b");
6077 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6078 emitcode ("anl", "a,%s",
6079 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6082 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6088 emitcode ("", "!tlabeldef", tlbl->key + 100);
6092 jmpTrueOrFalse (ifx, tlbl);
6096 for (; (size--); offset++)
6099 // result = left & right
6100 if (AOP_TYPE (right) == AOP_LIT)
6102 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6104 aopPut (AOP (result),
6105 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6109 else if (bytelit == 0)
6111 aopPut (AOP (result), zero, offset);
6114 D (emitcode (";", "better literal AND."););
6115 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6116 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6117 FALSE, FALSE, FALSE));
6122 // faster than result <- left, anl result,right
6123 // and better if result is SFR
6124 if (AOP_TYPE (left) == AOP_ACC)
6126 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6127 FALSE, FALSE, FALSE));
6131 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6132 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6134 emitcode("mov", "b,a");
6138 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6139 emitcode ("anl", "a,%s", rOp);
6142 aopPut (AOP (result), "a", offset);
6148 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6149 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6150 freeAsmop (result, NULL, ic, TRUE);
6154 /*-----------------------------------------------------------------*/
6155 /* genOr - code for or */
6156 /*-----------------------------------------------------------------*/
6158 genOr (iCode * ic, iCode * ifx)
6160 operand *left, *right, *result;
6161 int size, offset = 0;
6162 unsigned long lit = 0L;
6165 D (emitcode (";", "genOr "););
6167 AOP_OP_3_NOFATAL (ic, pushResult);
6168 AOP_SET_LOCALS (ic);
6172 genFarFarLogicOp(ic, "orl");
6178 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6180 AOP_TYPE (left), AOP_TYPE (right));
6181 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6183 AOP_SIZE (left), AOP_SIZE (right));
6186 /* if left is a literal & right is not then exchange them */
6187 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6188 #ifdef LOGIC_OPS_BROKEN
6189 || AOP_NEEDSACC (left) // I think this is a net loss now.
6193 operand *tmp = right;
6198 /* if result = right then exchange them */
6199 if (sameRegs (AOP (result), AOP (right)))
6201 operand *tmp = right;
6206 /* if right is bit then exchange them */
6207 if (AOP_TYPE (right) == AOP_CRY &&
6208 AOP_TYPE (left) != AOP_CRY)
6210 operand *tmp = right;
6214 if (AOP_TYPE (right) == AOP_LIT)
6215 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6217 size = AOP_SIZE (result);
6221 if (AOP_TYPE (left) == AOP_CRY)
6223 if (AOP_TYPE (right) == AOP_LIT)
6225 // c = bit & literal;
6228 // lit != 0 => result = 1
6229 if (AOP_TYPE (result) == AOP_CRY)
6232 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6234 continueIfTrue (ifx);
6237 emitcode ("setb", "c");
6241 // lit == 0 => result = left
6242 if (size && sameRegs (AOP (result), AOP (left)))
6244 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6249 if (AOP_TYPE (right) == AOP_CRY)
6252 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6253 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6258 symbol *tlbl = newiTempLabel (NULL);
6259 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6260 emitcode ("setb", "c");
6261 emitcode ("jb", "%s,!tlabel",
6262 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6264 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6265 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6267 jmpTrueOrFalse (ifx, tlbl);
6273 emitcode ("", "!tlabeldef", tlbl->key + 100);
6282 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6283 genIfxJump (ifx, "c");
6287 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6288 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6289 if ((AOP_TYPE (right) == AOP_LIT) &&
6290 (AOP_TYPE (result) == AOP_CRY) &&
6291 (AOP_TYPE (left) != AOP_CRY))
6297 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6299 continueIfTrue (ifx);
6304 // lit = 0, result = boolean(left)
6306 emitcode ("setb", "c");
6310 symbol *tlbl = newiTempLabel (NULL);
6311 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6313 emitcode ("", "!tlabeldef", tlbl->key + 100);
6317 genIfxJump (ifx, "a");
6325 /* if left is same as result */
6326 if (sameRegs (AOP (result), AOP (left)))
6328 for (; size--; offset++)
6330 if (AOP_TYPE (right) == AOP_LIT)
6332 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6338 if (IS_AOP_PREG (left))
6340 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6341 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6342 aopPut (AOP (result), "a", offset);
6346 emitcode ("orl", "%s,%s",
6347 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6348 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6354 if (AOP_TYPE (left) == AOP_ACC)
6356 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6360 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6361 if (IS_AOP_PREG (left))
6363 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6364 aopPut (AOP (result), "a", offset);
6368 emitcode ("orl", "%s,a",
6369 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6377 // left & result in different registers
6378 if (AOP_TYPE (result) == AOP_CRY)
6381 // if(size), result in bit
6382 // if(!size && ifx), conditional oper: if(left | right)
6383 symbol *tlbl = newiTempLabel (NULL);
6384 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6386 emitcode ("setb", "c");
6389 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6390 emitcode ("orl", "a,%s",
6391 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6393 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6394 emitcode ("orl", "a,%s",
6395 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6397 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6403 emitcode ("", "!tlabeldef", tlbl->key + 100);
6407 jmpTrueOrFalse (ifx, tlbl);
6411 _startLazyDPSEvaluation();
6412 for (; (size--); offset++)
6415 // result = left & right
6416 if (AOP_TYPE (right) == AOP_LIT)
6418 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6420 aopPut (AOP (result),
6421 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6425 D (emitcode (";", "better literal OR."););
6426 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6427 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6428 FALSE, FALSE, FALSE));
6433 // faster than result <- left, anl result,right
6434 // and better if result is SFR
6435 if (AOP_TYPE (left) == AOP_ACC)
6437 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6438 FALSE, FALSE, FALSE));
6442 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6444 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6446 emitcode("mov", "b,a");
6450 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6451 emitcode ("orl", "a,%s", rOp);
6454 aopPut (AOP (result), "a", offset);
6456 _endLazyDPSEvaluation();
6461 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463 freeAsmop (result, NULL, ic, TRUE);
6466 /*-----------------------------------------------------------------*/
6467 /* genXor - code for xclusive or */
6468 /*-----------------------------------------------------------------*/
6470 genXor (iCode * ic, iCode * ifx)
6472 operand *left, *right, *result;
6473 int size, offset = 0;
6474 unsigned long lit = 0L;
6477 D (emitcode (";", "genXor "););
6479 AOP_OP_3_NOFATAL (ic, pushResult);
6480 AOP_SET_LOCALS (ic);
6484 genFarFarLogicOp(ic, "xrl");
6489 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6491 AOP_TYPE (left), AOP_TYPE (right));
6492 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6494 AOP_SIZE (left), AOP_SIZE (right));
6497 /* if left is a literal & right is not ||
6498 if left needs acc & right does not */
6499 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6500 #ifdef LOGIC_OPS_BROKEN
6501 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6505 operand *tmp = right;
6510 /* if result = right then exchange them */
6511 if (sameRegs (AOP (result), AOP (right)))
6513 operand *tmp = right;
6518 /* if right is bit then exchange them */
6519 if (AOP_TYPE (right) == AOP_CRY &&
6520 AOP_TYPE (left) != AOP_CRY)
6522 operand *tmp = right;
6526 if (AOP_TYPE (right) == AOP_LIT)
6527 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6529 size = AOP_SIZE (result);
6533 if (AOP_TYPE (left) == AOP_CRY)
6535 if (AOP_TYPE (right) == AOP_LIT)
6537 // c = bit & literal;
6540 // lit>>1 != 0 => result = 1
6541 if (AOP_TYPE (result) == AOP_CRY)
6544 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6546 continueIfTrue (ifx);
6549 emitcode ("setb", "c");
6556 // lit == 0, result = left
6557 if (size && sameRegs (AOP (result), AOP (left)))
6559 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6563 // lit == 1, result = not(left)
6564 if (size && sameRegs (AOP (result), AOP (left)))
6566 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6571 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6572 emitcode ("cpl", "c");
6581 symbol *tlbl = newiTempLabel (NULL);
6582 if (AOP_TYPE (right) == AOP_CRY)
6585 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6589 int sizer = AOP_SIZE (right);
6591 // if val>>1 != 0, result = 1
6592 emitcode ("setb", "c");
6595 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6597 // test the msb of the lsb
6598 emitcode ("anl", "a,#!constbyte",0xfe);
6599 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6603 emitcode ("rrc", "a");
6605 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6606 emitcode ("cpl", "c");
6607 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6614 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6615 genIfxJump (ifx, "c");
6619 if (sameRegs (AOP (result), AOP (left)))
6621 /* if left is same as result */
6622 for (; size--; offset++)
6624 if (AOP_TYPE (right) == AOP_LIT)
6626 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6628 else if (IS_AOP_PREG (left))
6630 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6631 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6632 aopPut (AOP (result), "a", offset);
6635 emitcode ("xrl", "%s,%s",
6636 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6637 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6641 if (AOP_TYPE (left) == AOP_ACC)
6642 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6645 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6646 if (IS_AOP_PREG (left))
6648 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6649 aopPut (AOP (result), "a", offset);
6652 emitcode ("xrl", "%s,a",
6653 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6660 // left & result in different registers
6661 if (AOP_TYPE (result) == AOP_CRY)
6664 // if(size), result in bit
6665 // if(!size && ifx), conditional oper: if(left ^ right)
6666 symbol *tlbl = newiTempLabel (NULL);
6667 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6670 emitcode ("setb", "c");
6673 if ((AOP_TYPE (right) == AOP_LIT) &&
6674 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6676 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6680 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6681 emitcode ("xrl", "a,%s",
6682 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6684 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6685 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6687 emitcode("mov", "b,a");
6691 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6692 emitcode ("xrl", "a,%s", rOp);
6695 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6701 emitcode ("", "!tlabeldef", tlbl->key + 100);
6705 jmpTrueOrFalse (ifx, tlbl);
6709 for (; (size--); offset++)
6712 // result = left & right
6713 if (AOP_TYPE (right) == AOP_LIT)
6715 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6717 aopPut (AOP (result),
6718 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6722 D (emitcode (";", "better literal XOR."););
6723 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6724 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6725 FALSE, FALSE, FALSE));
6729 // faster than result <- left, anl result,right
6730 // and better if result is SFR
6731 if (AOP_TYPE (left) == AOP_ACC)
6733 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6734 FALSE, FALSE, FALSE));
6738 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6739 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6741 emitcode("mov", "b,a");
6745 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6746 emitcode ("xrl", "a,%s", rOp);
6749 aopPut (AOP (result), "a", offset);
6756 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6757 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6758 freeAsmop (result, NULL, ic, TRUE);
6761 /*-----------------------------------------------------------------*/
6762 /* genInline - write the inline code out */
6763 /*-----------------------------------------------------------------*/
6765 genInline (iCode * ic)
6767 char *buffer, *bp, *bp1;
6769 D (emitcode (";", "genInline ");
6772 _G.inLine += (!options.asmpeep);
6774 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6775 strcpy (buffer, IC_INLINE (ic));
6777 /* emit each line as a code */
6802 /* emitcode("",buffer); */
6803 _G.inLine -= (!options.asmpeep);
6806 /*-----------------------------------------------------------------*/
6807 /* genRRC - rotate right with carry */
6808 /*-----------------------------------------------------------------*/
6812 operand *left, *result;
6813 int size, offset = 0;
6816 D (emitcode (";", "genRRC ");
6819 /* rotate right with carry */
6820 left = IC_LEFT (ic);
6821 result = IC_RESULT (ic);
6822 aopOp (left, ic, FALSE, FALSE);
6823 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6825 /* move it to the result */
6826 size = AOP_SIZE (result);
6830 _startLazyDPSEvaluation ();
6833 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6835 emitcode ("rrc", "a");
6836 if (AOP_SIZE (result) > 1)
6837 aopPut (AOP (result), "a", offset--);
6839 _endLazyDPSEvaluation ();
6841 /* now we need to put the carry into the
6842 highest order byte of the result */
6843 if (AOP_SIZE (result) > 1)
6845 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6848 emitcode ("mov", "acc.7,c");
6849 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6850 freeAsmop (left, NULL, ic, TRUE);
6851 freeAsmop (result, NULL, ic, TRUE);
6854 /*-----------------------------------------------------------------*/
6855 /* genRLC - generate code for rotate left with carry */
6856 /*-----------------------------------------------------------------*/
6860 operand *left, *result;
6861 int size, offset = 0;
6864 D (emitcode (";", "genRLC ");
6867 /* rotate right with carry */
6868 left = IC_LEFT (ic);
6869 result = IC_RESULT (ic);
6870 aopOp (left, ic, FALSE, FALSE);
6871 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6873 /* move it to the result */
6874 size = AOP_SIZE (result);
6878 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6880 emitcode ("add", "a,acc");
6881 if (AOP_SIZE (result) > 1)
6883 aopPut (AOP (result), "a", offset++);
6886 _startLazyDPSEvaluation ();
6889 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6891 emitcode ("rlc", "a");
6892 if (AOP_SIZE (result) > 1)
6893 aopPut (AOP (result), "a", offset++);
6895 _endLazyDPSEvaluation ();
6897 /* now we need to put the carry into the
6898 highest order byte of the result */
6899 if (AOP_SIZE (result) > 1)
6901 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6904 emitcode ("mov", "acc.0,c");
6905 aopPut (AOP (result), "a", 0);
6906 freeAsmop (left, NULL, ic, TRUE);
6907 freeAsmop (result, NULL, ic, TRUE);
6910 /*-----------------------------------------------------------------*/
6911 /* genGetHbit - generates code get highest order bit */
6912 /*-----------------------------------------------------------------*/
6914 genGetHbit (iCode * ic)
6916 operand *left, *result;
6917 left = IC_LEFT (ic);
6918 result = IC_RESULT (ic);
6919 aopOp (left, ic, FALSE, FALSE);
6920 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6922 D (emitcode (";", "genGetHbit ");
6925 /* get the highest order byte into a */
6926 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6927 if (AOP_TYPE (result) == AOP_CRY)
6929 emitcode ("rlc", "a");
6934 emitcode ("rl", "a");
6935 emitcode ("anl", "a,#1");
6940 freeAsmop (left, NULL, ic, TRUE);
6941 freeAsmop (result, NULL, ic, TRUE);
6944 /*-----------------------------------------------------------------*/
6945 /* AccRol - rotate left accumulator by known count */
6946 /*-----------------------------------------------------------------*/
6948 AccRol (int shCount)
6950 shCount &= 0x0007; // shCount : 0..7
6957 emitcode ("rl", "a");
6960 emitcode ("rl", "a");
6961 emitcode ("rl", "a");
6964 emitcode ("swap", "a");
6965 emitcode ("rr", "a");
6968 emitcode ("swap", "a");
6971 emitcode ("swap", "a");
6972 emitcode ("rl", "a");
6975 emitcode ("rr", "a");
6976 emitcode ("rr", "a");
6979 emitcode ("rr", "a");
6984 /*-----------------------------------------------------------------*/
6985 /* AccLsh - left shift accumulator by known count */
6986 /*-----------------------------------------------------------------*/
6988 AccLsh (int shCount)
6993 emitcode ("add", "a,acc");
6994 else if (shCount == 2)
6996 emitcode ("add", "a,acc");
6997 emitcode ("add", "a,acc");
7001 /* rotate left accumulator */
7003 /* and kill the lower order bits */
7004 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7009 /*-----------------------------------------------------------------*/
7010 /* AccRsh - right shift accumulator by known count */
7011 /*-----------------------------------------------------------------*/
7013 AccRsh (int shCount)
7020 emitcode ("rrc", "a");
7024 /* rotate right accumulator */
7025 AccRol (8 - shCount);
7026 /* and kill the higher order bits */
7027 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7032 #ifdef BETTER_LITERAL_SHIFT
7033 /*-----------------------------------------------------------------*/
7034 /* AccSRsh - signed right shift accumulator by known count */
7035 /*-----------------------------------------------------------------*/
7037 AccSRsh (int shCount)
7044 emitcode ("mov", "c,acc.7");
7045 emitcode ("rrc", "a");
7047 else if (shCount == 2)
7049 emitcode ("mov", "c,acc.7");
7050 emitcode ("rrc", "a");
7051 emitcode ("mov", "c,acc.7");
7052 emitcode ("rrc", "a");
7056 tlbl = newiTempLabel (NULL);
7057 /* rotate right accumulator */
7058 AccRol (8 - shCount);
7059 /* and kill the higher order bits */
7060 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7061 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7062 emitcode ("orl", "a,#!constbyte",
7063 (unsigned char) ~SRMask[shCount]);
7064 emitcode ("", "!tlabeldef", tlbl->key + 100);
7070 #ifdef BETTER_LITERAL_SHIFT
7071 /*-----------------------------------------------------------------*/
7072 /* shiftR1Left2Result - shift right one byte from left to result */
7073 /*-----------------------------------------------------------------*/
7075 shiftR1Left2Result (operand * left, int offl,
7076 operand * result, int offr,
7077 int shCount, int sign)
7079 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7080 /* shift right accumulator */
7085 aopPut (AOP (result), "a", offr);
7089 #ifdef BETTER_LITERAL_SHIFT
7090 /*-----------------------------------------------------------------*/
7091 /* shiftL1Left2Result - shift left one byte from left to result */
7092 /*-----------------------------------------------------------------*/
7094 shiftL1Left2Result (operand * left, int offl,
7095 operand * result, int offr, int shCount)
7097 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7098 /* shift left accumulator */
7100 aopPut (AOP (result), "a", offr);
7104 #ifdef BETTER_LITERAL_SHIFT
7105 /*-----------------------------------------------------------------*/
7106 /* movLeft2Result - move byte from left to result */
7107 /*-----------------------------------------------------------------*/
7109 movLeft2Result (operand * left, int offl,
7110 operand * result, int offr, int sign)
7113 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7115 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7117 if (*l == '@' && (IS_AOP_PREG (result)))
7119 emitcode ("mov", "a,%s", l);
7120 aopPut (AOP (result), "a", offr);
7126 aopPut (AOP (result), l, offr);
7130 /* MSB sign in acc.7 ! */
7131 if (getDataSize (left) == offl + 1)
7133 emitcode ("mov", "a,%s", l);
7134 aopPut (AOP (result), "a", offr);
7142 #ifdef BETTER_LITERAL_SHIFT
7143 /*-----------------------------------------------------------------*/
7144 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7145 /*-----------------------------------------------------------------*/
7149 emitcode ("rrc", "a");
7150 emitcode ("xch", "a,%s", x);
7151 emitcode ("rrc", "a");
7152 emitcode ("xch", "a,%s", x);
7156 #ifdef BETTER_LITERAL_SHIFT
7158 /*-----------------------------------------------------------------*/
7159 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7160 /*-----------------------------------------------------------------*/
7164 emitcode ("xch", "a,%s", x);
7165 emitcode ("rlc", "a");
7166 emitcode ("xch", "a,%s", x);
7167 emitcode ("rlc", "a");
7171 #ifdef BETTER_LITERAL_SHIFT
7172 /*-----------------------------------------------------------------*/
7173 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7174 /*-----------------------------------------------------------------*/
7178 emitcode ("xch", "a,%s", x);
7179 emitcode ("add", "a,acc");
7180 emitcode ("xch", "a,%s", x);
7181 emitcode ("rlc", "a");
7185 #ifdef BETTER_LITERAL_SHIFT
7186 /*-----------------------------------------------------------------*/
7187 /* AccAXLsh - left shift a:x by known count (0..7) */
7188 /*-----------------------------------------------------------------*/
7190 AccAXLsh (char *x, int shCount)
7205 case 5: // AAAAABBB:CCCCCDDD
7207 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7209 emitcode ("anl", "a,#!constbyte",
7210 SLMask[shCount]); // BBB00000:CCCCCDDD
7212 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7214 AccRol (shCount); // DDDCCCCC:BBB00000
7216 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7218 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7220 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7222 emitcode ("anl", "a,#!constbyte",
7223 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7225 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7227 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7230 case 6: // AAAAAABB:CCCCCCDD
7231 emitcode ("anl", "a,#!constbyte",
7232 SRMask[shCount]); // 000000BB:CCCCCCDD
7233 emitcode ("mov", "c,acc.0"); // c = B
7234 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7236 AccAXRrl1 (x); // BCCCCCCD:D000000B
7237 AccAXRrl1 (x); // BBCCCCCC:DD000000
7239 emitcode("rrc","a");
7240 emitcode("xch","a,%s", x);
7241 emitcode("rrc","a");
7242 emitcode("mov","c,acc.0"); //<< get correct bit
7243 emitcode("xch","a,%s", x);
7245 emitcode("rrc","a");
7246 emitcode("xch","a,%s", x);
7247 emitcode("rrc","a");
7248 emitcode("xch","a,%s", x);
7251 case 7: // a:x <<= 7
7253 emitcode ("anl", "a,#!constbyte",
7254 SRMask[shCount]); // 0000000B:CCCCCCCD
7256 emitcode ("mov", "c,acc.0"); // c = B
7258 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7260 AccAXRrl1 (x); // BCCCCCCC:D0000000
7269 #ifdef BETTER_LITERAL_SHIFT
7271 /*-----------------------------------------------------------------*/
7272 /* AccAXRsh - right shift a:x known count (0..7) */
7273 /*-----------------------------------------------------------------*/
7275 AccAXRsh (char *x, int shCount)
7283 AccAXRrl1 (x); // 0->a:x
7288 AccAXRrl1 (x); // 0->a:x
7291 AccAXRrl1 (x); // 0->a:x
7296 case 5: // AAAAABBB:CCCCCDDD = a:x
7298 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7300 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7302 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7304 emitcode ("anl", "a,#!constbyte",
7305 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7307 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7309 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7311 emitcode ("anl", "a,#!constbyte",
7312 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7314 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7316 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7318 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7321 case 6: // AABBBBBB:CCDDDDDD
7323 emitcode ("mov", "c,acc.7");
7324 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7326 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7328 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7330 emitcode ("anl", "a,#!constbyte",
7331 SRMask[shCount]); // 000000AA:BBBBBBCC
7334 case 7: // ABBBBBBB:CDDDDDDD
7336 emitcode ("mov", "c,acc.7"); // c = A
7338 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7340 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7342 emitcode ("anl", "a,#!constbyte",
7343 SRMask[shCount]); // 0000000A:BBBBBBBC
7352 #ifdef BETTER_LITERAL_SHIFT
7353 /*-----------------------------------------------------------------*/
7354 /* AccAXRshS - right shift signed a:x known count (0..7) */
7355 /*-----------------------------------------------------------------*/
7357 AccAXRshS (char *x, int shCount)
7365 emitcode ("mov", "c,acc.7");
7366 AccAXRrl1 (x); // s->a:x
7370 emitcode ("mov", "c,acc.7");
7371 AccAXRrl1 (x); // s->a:x
7373 emitcode ("mov", "c,acc.7");
7374 AccAXRrl1 (x); // s->a:x
7379 case 5: // AAAAABBB:CCCCCDDD = a:x
7381 tlbl = newiTempLabel (NULL);
7382 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7384 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7386 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7388 emitcode ("anl", "a,#!constbyte",
7389 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7391 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7393 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7395 emitcode ("anl", "a,#!constbyte",
7396 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7398 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7400 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7402 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7404 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7405 emitcode ("orl", "a,#!constbyte",
7406 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7408 emitcode ("", "!tlabeldef", tlbl->key + 100);
7409 break; // SSSSAAAA:BBBCCCCC
7411 case 6: // AABBBBBB:CCDDDDDD
7413 tlbl = newiTempLabel (NULL);
7414 emitcode ("mov", "c,acc.7");
7415 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7417 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7419 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7421 emitcode ("anl", "a,#!constbyte",
7422 SRMask[shCount]); // 000000AA:BBBBBBCC
7424 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7425 emitcode ("orl", "a,#!constbyte",
7426 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7428 emitcode ("", "!tlabeldef", tlbl->key + 100);
7430 case 7: // ABBBBBBB:CDDDDDDD
7432 tlbl = newiTempLabel (NULL);
7433 emitcode ("mov", "c,acc.7"); // c = A
7435 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7437 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7439 emitcode ("anl", "a,#!constbyte",
7440 SRMask[shCount]); // 0000000A:BBBBBBBC
7442 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7443 emitcode ("orl", "a,#!constbyte",
7444 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7446 emitcode ("", "!tlabeldef", tlbl->key + 100);
7454 #ifdef BETTER_LITERAL_SHIFT
7456 _loadLeftIntoAx(char **lsb,
7462 // Get the initial value from left into a pair of registers.
7463 // MSB must be in A, LSB can be any register.
7465 // If the result is held in registers, it is an optimization
7466 // if the LSB can be held in the register which will hold the,
7467 // result LSB since this saves us from having to copy it into
7468 // the result following AccAXLsh.
7470 // If the result is addressed indirectly, this is not a gain.
7471 if (AOP_NEEDSACC(result))
7475 _startLazyDPSEvaluation();
7476 if (AOP_TYPE(left) == AOP_DPTR2)
7479 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7480 // get LSB in DP2_RESULT_REG.
7481 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7482 assert(!strcmp(leftByte, DP2_RESULT_REG));
7486 // get LSB into DP2_RESULT_REG
7487 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7488 if (strcmp(leftByte, DP2_RESULT_REG))
7491 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7494 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7495 assert(strcmp(leftByte, DP2_RESULT_REG));
7498 _endLazyDPSEvaluation();
7499 *lsb = DP2_RESULT_REG;
7503 if (sameRegs (AOP (result), AOP (left)) &&
7504 ((offl + MSB16) == offr))
7506 /* don't crash result[offr] */
7507 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7508 emitcode ("xch", "a,%s",
7509 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7513 movLeft2Result (left, offl, result, offr, 0);
7514 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7516 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7517 assert(strcmp(*lsb,"a"));
7522 _storeAxResults(char *lsb,
7526 _startLazyDPSEvaluation();
7527 if (AOP_NEEDSACC(result))
7529 /* We have to explicitly update the result LSB.
7531 emitcode("xch","a,%s", lsb);
7532 aopPut(AOP(result), "a", offr);
7533 emitcode("mov","a,%s", lsb);
7535 if (getDataSize (result) > 1)
7537 aopPut (AOP (result), "a", offr + MSB16);
7539 _endLazyDPSEvaluation();
7542 /*-----------------------------------------------------------------*/
7543 /* shiftL2Left2Result - shift left two bytes from left to result */
7544 /*-----------------------------------------------------------------*/
7546 shiftL2Left2Result (operand * left, int offl,
7547 operand * result, int offr, int shCount)
7551 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7553 AccAXLsh (lsb, shCount);
7555 _storeAxResults(lsb, result, offr);
7559 #ifdef BETTER_LITERAL_SHIFT
7560 /*-----------------------------------------------------------------*/
7561 /* shiftR2Left2Result - shift right two bytes from left to result */
7562 /*-----------------------------------------------------------------*/
7564 shiftR2Left2Result (operand * left, int offl,
7565 operand * result, int offr,
7566 int shCount, int sign)
7570 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7572 /* a:x >> shCount (x = lsb(result)) */
7575 AccAXRshS(lsb, shCount);
7579 AccAXRsh(lsb, shCount);
7582 _storeAxResults(lsb, result, offr);
7588 /*-----------------------------------------------------------------*/
7589 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7590 /*-----------------------------------------------------------------*/
7592 shiftLLeftOrResult (operand * left, int offl,
7593 operand * result, int offr, int shCount)
7595 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7596 /* shift left accumulator */
7598 /* or with result */
7599 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7600 /* back to result */
7601 aopPut (AOP (result), "a", offr);
7607 /*-----------------------------------------------------------------*/
7608 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7609 /*-----------------------------------------------------------------*/
7611 shiftRLeftOrResult (operand * left, int offl,
7612 operand * result, int offr, int shCount)
7614 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7615 /* shift right accumulator */
7617 /* or with result */
7618 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7619 /* back to result */
7620 aopPut (AOP (result), "a", offr);
7624 #ifdef BETTER_LITERAL_SHIFT
7625 /*-----------------------------------------------------------------*/
7626 /* genlshOne - left shift a one byte quantity by known count */
7627 /*-----------------------------------------------------------------*/
7629 genlshOne (operand * result, operand * left, int shCount)
7631 D (emitcode (";", "genlshOne "););
7632 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7636 #ifdef BETTER_LITERAL_SHIFT
7637 /*-----------------------------------------------------------------*/
7638 /* genlshTwo - left shift two bytes by known amount != 0 */
7639 /*-----------------------------------------------------------------*/
7641 genlshTwo (operand * result, operand * left, int shCount)
7645 D (emitcode (";", "genlshTwo "););
7647 size = getDataSize (result);
7649 /* if shCount >= 8 */
7654 _startLazyDPSEvaluation();
7660 _endLazyDPSEvaluation();
7661 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7662 aopPut (AOP (result), zero, LSB);
7666 movLeft2Result (left, LSB, result, MSB16, 0);
7667 aopPut (AOP (result), zero, LSB);
7668 _endLazyDPSEvaluation();
7673 aopPut (AOP (result), zero, LSB);
7674 _endLazyDPSEvaluation();
7678 /* 1 <= shCount <= 7 */
7683 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7687 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7695 /*-----------------------------------------------------------------*/
7696 /* shiftLLong - shift left one long from left to result */
7697 /* offl = LSB or MSB16 */
7698 /*-----------------------------------------------------------------*/
7700 shiftLLong (operand * left, operand * result, int offr)
7703 int size = AOP_SIZE (result);
7705 if (size >= LSB + offr)
7707 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7709 emitcode ("add", "a,acc");
7710 if (sameRegs (AOP (left), AOP (result)) &&
7711 size >= MSB16 + offr && offr != LSB)
7712 emitcode ("xch", "a,%s",
7713 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7715 aopPut (AOP (result), "a", LSB + offr);
7718 if (size >= MSB16 + offr)
7720 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7722 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7725 emitcode ("rlc", "a");
7726 if (sameRegs (AOP (left), AOP (result)) &&
7727 size >= MSB24 + offr && offr != LSB)
7728 emitcode ("xch", "a,%s",
7729 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7731 aopPut (AOP (result), "a", MSB16 + offr);
7734 if (size >= MSB24 + offr)
7736 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7738 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7741 emitcode ("rlc", "a");
7742 if (sameRegs (AOP (left), AOP (result)) &&
7743 size >= MSB32 + offr && offr != LSB)
7744 emitcode ("xch", "a,%s",
7745 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7747 aopPut (AOP (result), "a", MSB24 + offr);
7750 if (size > MSB32 + offr)
7752 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7754 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7757 emitcode ("rlc", "a");
7758 aopPut (AOP (result), "a", MSB32 + offr);
7761 aopPut (AOP (result), zero, LSB);
7767 /*-----------------------------------------------------------------*/
7768 /* genlshFour - shift four byte by a known amount != 0 */
7769 /*-----------------------------------------------------------------*/
7771 genlshFour (operand * result, operand * left, int shCount)
7775 D (emitcode (";", "genlshFour ");
7778 size = AOP_SIZE (result);
7780 /* if shifting more that 3 bytes */
7785 /* lowest order of left goes to the highest
7786 order of the destination */
7787 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7789 movLeft2Result (left, LSB, result, MSB32, 0);
7790 aopPut (AOP (result), zero, LSB);
7791 aopPut (AOP (result), zero, MSB16);
7792 aopPut (AOP (result), zero, MSB24);
7796 /* more than two bytes */
7797 else if (shCount >= 16)
7799 /* lower order two bytes goes to higher order two bytes */
7801 /* if some more remaining */
7803 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7806 movLeft2Result (left, MSB16, result, MSB32, 0);
7807 movLeft2Result (left, LSB, result, MSB24, 0);
7809 aopPut (AOP (result), zero, MSB16);
7810 aopPut (AOP (result), zero, LSB);
7814 /* if more than 1 byte */
7815 else if (shCount >= 8)
7817 /* lower order three bytes goes to higher order three bytes */
7822 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7824 movLeft2Result (left, LSB, result, MSB16, 0);
7830 movLeft2Result (left, MSB24, result, MSB32, 0);
7831 movLeft2Result (left, MSB16, result, MSB24, 0);
7832 movLeft2Result (left, LSB, result, MSB16, 0);
7833 aopPut (AOP (result), zero, LSB);
7835 else if (shCount == 1)
7836 shiftLLong (left, result, MSB16);
7839 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7840 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7841 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7842 aopPut (AOP (result), zero, LSB);
7847 /* 1 <= shCount <= 7 */
7848 else if (shCount <= 2)
7850 shiftLLong (left, result, LSB);
7852 shiftLLong (result, result, LSB);
7854 /* 3 <= shCount <= 7, optimize */
7857 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7858 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7859 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7864 #ifdef BETTER_LITERAL_SHIFT
7865 /*-----------------------------------------------------------------*/
7866 /* genLeftShiftLiteral - left shifting by known count */
7867 /*-----------------------------------------------------------------*/
7869 genLeftShiftLiteral (operand * left,
7874 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7877 size = getSize (operandType (result));
7879 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7881 /* We only handle certain easy cases so far. */
7883 && (shCount < (size * 8))
7887 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7891 freeAsmop (right, NULL, ic, TRUE);
7893 aopOp(left, ic, FALSE, FALSE);
7894 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7897 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7899 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7900 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7902 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7905 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7907 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7908 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7910 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7916 emitcode ("; shift left ", "result %d, left %d", size,
7920 /* I suppose that the left size >= result size */
7923 _startLazyDPSEvaluation();
7926 movLeft2Result (left, size, result, size, 0);
7928 _endLazyDPSEvaluation();
7930 else if (shCount >= (size * 8))
7932 _startLazyDPSEvaluation();
7935 aopPut (AOP (result), zero, size);
7937 _endLazyDPSEvaluation();
7944 genlshOne (result, left, shCount);
7948 genlshTwo (result, left, shCount);
7952 genlshFour (result, left, shCount);
7956 fprintf(stderr, "*** ack! mystery literal shift!\n");
7960 freeAsmop (left, NULL, ic, TRUE);
7961 freeAsmop (result, NULL, ic, TRUE);
7966 /*-----------------------------------------------------------------*/
7967 /* genLeftShift - generates code for left shifting */
7968 /*-----------------------------------------------------------------*/
7970 genLeftShift (iCode * ic)
7972 operand *left, *right, *result;
7975 symbol *tlbl, *tlbl1;
7977 D (emitcode (";", "genLeftShift "););
7979 right = IC_RIGHT (ic);
7980 left = IC_LEFT (ic);
7981 result = IC_RESULT (ic);
7983 aopOp (right, ic, FALSE, FALSE);
7986 #ifdef BETTER_LITERAL_SHIFT
7987 /* if the shift count is known then do it
7988 as efficiently as possible */
7989 if (AOP_TYPE (right) == AOP_LIT)
7991 if (genLeftShiftLiteral (left, right, result, ic))
7998 /* shift count is unknown then we have to form
7999 a loop get the loop count in B : Note: we take
8000 only the lower order byte since shifting
8001 more that 32 bits make no sense anyway, ( the
8002 largest size of an object can be only 32 bits ) */
8004 if (AOP_TYPE (right) == AOP_LIT)
8006 /* Really should be handled by genLeftShiftLiteral,
8007 * but since I'm too lazy to fix that today, at least we can make
8008 * some small improvement.
8010 emitcode("mov", "b,#!constbyte",
8011 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8015 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8016 emitcode ("inc", "b");
8018 freeAsmop (right, NULL, ic, TRUE);
8019 aopOp (left, ic, FALSE, FALSE);
8020 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8022 /* now move the left to the result if they are not the
8024 if (!sameRegs (AOP (left), AOP (result)) &&
8025 AOP_SIZE (result) > 1)
8028 size = AOP_SIZE (result);
8030 _startLazyDPSEvaluation ();
8033 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8034 if (*l == '@' && (IS_AOP_PREG (result)))
8037 emitcode ("mov", "a,%s", l);
8038 aopPut (AOP (result), "a", offset);
8041 aopPut (AOP (result), l, offset);
8044 _endLazyDPSEvaluation ();
8047 tlbl = newiTempLabel (NULL);
8048 size = AOP_SIZE (result);
8050 tlbl1 = newiTempLabel (NULL);
8052 /* if it is only one byte then */
8055 symbol *tlbl1 = newiTempLabel (NULL);
8057 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8059 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8060 emitcode ("", "!tlabeldef", tlbl->key + 100);
8061 emitcode ("add", "a,acc");
8062 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8063 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8064 aopPut (AOP (result), "a", 0);
8068 reAdjustPreg (AOP (result));
8070 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8071 emitcode ("", "!tlabeldef", tlbl->key + 100);
8072 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8074 emitcode ("add", "a,acc");
8075 aopPut (AOP (result), "a", offset++);
8076 _startLazyDPSEvaluation ();
8079 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8081 emitcode ("rlc", "a");
8082 aopPut (AOP (result), "a", offset++);
8084 _endLazyDPSEvaluation ();
8085 reAdjustPreg (AOP (result));
8087 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8088 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8090 freeAsmop (left, NULL, ic, TRUE);
8091 freeAsmop (result, NULL, ic, TRUE);
8094 #ifdef BETTER_LITERAL_SHIFT
8095 /*-----------------------------------------------------------------*/
8096 /* genrshOne - right shift a one byte quantity by known count */
8097 /*-----------------------------------------------------------------*/
8099 genrshOne (operand * result, operand * left,
8100 int shCount, int sign)
8102 D (emitcode (";", "genrshOne"););
8103 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8107 #ifdef BETTER_LITERAL_SHIFT
8108 /*-----------------------------------------------------------------*/
8109 /* genrshTwo - right shift two bytes by known amount != 0 */
8110 /*-----------------------------------------------------------------*/
8112 genrshTwo (operand * result, operand * left,
8113 int shCount, int sign)
8115 D (emitcode (";", "genrshTwo"););
8117 /* if shCount >= 8 */
8121 _startLazyDPSEvaluation();
8124 shiftR1Left2Result (left, MSB16, result, LSB,
8129 movLeft2Result (left, MSB16, result, LSB, sign);
8131 addSign (result, MSB16, sign);
8132 _endLazyDPSEvaluation();
8135 /* 1 <= shCount <= 7 */
8138 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8145 /*-----------------------------------------------------------------*/
8146 /* shiftRLong - shift right one long from left to result */
8147 /* offl = LSB or MSB16 */
8148 /*-----------------------------------------------------------------*/
8150 shiftRLong (operand * left, int offl,
8151 operand * result, int sign)
8153 int isSameRegs=sameRegs(AOP(left),AOP(result));
8155 if (isSameRegs && offl>1) {
8156 // we are in big trouble, but this shouldn't happen
8157 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8160 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8165 emitcode ("rlc", "a");
8166 emitcode ("subb", "a,acc");
8167 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8169 aopPut (AOP(result), zero, MSB32);
8174 emitcode ("clr", "c");
8176 emitcode ("mov", "c,acc.7");
8179 emitcode ("rrc", "a");
8181 if (isSameRegs && offl==MSB16) {
8182 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8184 aopPut (AOP (result), "a", MSB32);
8185 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8188 emitcode ("rrc", "a");
8189 if (isSameRegs && offl==1) {
8190 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8192 aopPut (AOP (result), "a", MSB24);
8193 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8195 emitcode ("rrc", "a");
8196 aopPut (AOP (result), "a", MSB16 - offl);
8200 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8201 emitcode ("rrc", "a");
8202 aopPut (AOP (result), "a", LSB);
8209 /*-----------------------------------------------------------------*/
8210 /* genrshFour - shift four byte by a known amount != 0 */
8211 /*-----------------------------------------------------------------*/
8213 genrshFour (operand * result, operand * left,
8214 int shCount, int sign)
8216 D (emitcode (";", "genrshFour");
8219 /* if shifting more that 3 bytes */
8224 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8226 movLeft2Result (left, MSB32, result, LSB, sign);
8227 addSign (result, MSB16, sign);
8229 else if (shCount >= 16)
8233 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8236 movLeft2Result (left, MSB24, result, LSB, 0);
8237 movLeft2Result (left, MSB32, result, MSB16, sign);
8239 addSign (result, MSB24, sign);
8241 else if (shCount >= 8)
8245 shiftRLong (left, MSB16, result, sign);
8246 else if (shCount == 0)
8248 movLeft2Result (left, MSB16, result, LSB, 0);
8249 movLeft2Result (left, MSB24, result, MSB16, 0);
8250 movLeft2Result (left, MSB32, result, MSB24, sign);
8251 addSign (result, MSB32, sign);
8255 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8256 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8257 /* the last shift is signed */
8258 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8259 addSign (result, MSB32, sign);
8263 { /* 1 <= shCount <= 7 */
8266 shiftRLong (left, LSB, result, sign);
8268 shiftRLong (result, LSB, result, sign);
8272 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8273 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8274 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8280 #ifdef BETTER_LITERAL_SHIFT
8281 /*-----------------------------------------------------------------*/
8282 /* genRightShiftLiteral - right shifting by known count */
8283 /*-----------------------------------------------------------------*/
8285 genRightShiftLiteral (operand * left,
8291 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8294 size = getSize (operandType (result));
8296 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8298 /* We only handle certain easy cases so far. */
8300 && (shCount < (size * 8))
8304 D(emitcode (";", "genRightShiftLiteral wimping out"););
8308 freeAsmop (right, NULL, ic, TRUE);
8310 aopOp (left, ic, FALSE, FALSE);
8311 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8314 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8318 /* test the LEFT size !!! */
8320 /* I suppose that the left size >= result size */
8323 size = getDataSize (result);
8324 _startLazyDPSEvaluation();
8327 movLeft2Result (left, size, result, size, 0);
8329 _endLazyDPSEvaluation();
8331 else if (shCount >= (size * 8))
8335 /* get sign in acc.7 */
8336 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8338 addSign (result, LSB, sign);
8345 genrshOne (result, left, shCount, sign);
8349 genrshTwo (result, left, shCount, sign);
8353 genrshFour (result, left, shCount, sign);
8360 freeAsmop (left, NULL, ic, TRUE);
8361 freeAsmop (result, NULL, ic, TRUE);
8367 /*-----------------------------------------------------------------*/
8368 /* genSignedRightShift - right shift of signed number */
8369 /*-----------------------------------------------------------------*/
8371 genSignedRightShift (iCode * ic)
8373 operand *right, *left, *result;
8376 symbol *tlbl, *tlbl1;
8378 D (emitcode (";", "genSignedRightShift "););
8380 /* we do it the hard way put the shift count in b
8381 and loop thru preserving the sign */
8383 right = IC_RIGHT (ic);
8384 left = IC_LEFT (ic);
8385 result = IC_RESULT (ic);
8387 aopOp (right, ic, FALSE, FALSE);
8389 #ifdef BETTER_LITERAL_SHIFT
8390 if (AOP_TYPE (right) == AOP_LIT)
8392 if (genRightShiftLiteral (left, right, result, ic, 1))
8398 /* shift count is unknown then we have to form
8399 a loop get the loop count in B : Note: we take
8400 only the lower order byte since shifting
8401 more that 32 bits make no sense anyway, ( the
8402 largest size of an object can be only 32 bits ) */
8404 if (AOP_TYPE (right) == AOP_LIT)
8406 /* Really should be handled by genRightShiftLiteral,
8407 * but since I'm too lazy to fix that today, at least we can make
8408 * some small improvement.
8410 emitcode("mov", "b,#!constbyte",
8411 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8415 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8416 emitcode ("inc", "b");
8418 freeAsmop (right, NULL, ic, TRUE);
8419 aopOp (left, ic, FALSE, FALSE);
8420 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8422 /* now move the left to the result if they are not the
8424 if (!sameRegs (AOP (left), AOP (result)) &&
8425 AOP_SIZE (result) > 1)
8428 size = AOP_SIZE (result);
8430 _startLazyDPSEvaluation ();
8433 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8434 if (*l == '@' && IS_AOP_PREG (result))
8437 emitcode ("mov", "a,%s", l);
8438 aopPut (AOP (result), "a", offset);
8441 aopPut (AOP (result), l, offset);
8444 _endLazyDPSEvaluation ();
8447 /* mov the highest order bit to OVR */
8448 tlbl = newiTempLabel (NULL);
8449 tlbl1 = newiTempLabel (NULL);
8451 size = AOP_SIZE (result);
8453 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8454 emitcode ("rlc", "a");
8455 emitcode ("mov", "ov,c");
8456 /* if it is only one byte then */
8459 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8461 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8462 emitcode ("", "!tlabeldef", tlbl->key + 100);
8463 emitcode ("mov", "c,ov");
8464 emitcode ("rrc", "a");
8465 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8466 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8467 aopPut (AOP (result), "a", 0);
8471 reAdjustPreg (AOP (result));
8472 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8473 emitcode ("", "!tlabeldef", tlbl->key + 100);
8474 emitcode ("mov", "c,ov");
8475 _startLazyDPSEvaluation ();
8478 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8480 emitcode ("rrc", "a");
8481 aopPut (AOP (result), "a", offset--);
8483 _endLazyDPSEvaluation ();
8484 reAdjustPreg (AOP (result));
8485 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8486 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8489 freeAsmop (left, NULL, ic, TRUE);
8490 freeAsmop (result, NULL, ic, TRUE);
8493 /*-----------------------------------------------------------------*/
8494 /* genRightShift - generate code for right shifting */
8495 /*-----------------------------------------------------------------*/
8497 genRightShift (iCode * ic)
8499 operand *right, *left, *result;
8503 symbol *tlbl, *tlbl1;
8505 D (emitcode (";", "genRightShift "););
8507 /* if signed then we do it the hard way preserve the
8508 sign bit moving it inwards */
8509 retype = getSpec (operandType (IC_RESULT (ic)));
8511 if (!SPEC_USIGN (retype))
8513 genSignedRightShift (ic);
8517 /* signed & unsigned types are treated the same : i.e. the
8518 signed is NOT propagated inwards : quoting from the
8519 ANSI - standard : "for E1 >> E2, is equivalent to division
8520 by 2**E2 if unsigned or if it has a non-negative value,
8521 otherwise the result is implementation defined ", MY definition
8522 is that the sign does not get propagated */
8524 right = IC_RIGHT (ic);
8525 left = IC_LEFT (ic);
8526 result = IC_RESULT (ic);
8528 aopOp (right, ic, FALSE, FALSE);
8530 #ifdef BETTER_LITERAL_SHIFT
8531 /* if the shift count is known then do it
8532 as efficiently as possible */
8533 if (AOP_TYPE (right) == AOP_LIT)
8535 if (genRightShiftLiteral (left, right, result, ic, 0))
8542 /* shift count is unknown then we have to form
8543 a loop get the loop count in B : Note: we take
8544 only the lower order byte since shifting
8545 more that 32 bits make no sense anyway, ( the
8546 largest size of an object can be only 32 bits ) */
8548 if (AOP_TYPE (right) == AOP_LIT)
8550 /* Really should be handled by genRightShiftLiteral,
8551 * but since I'm too lazy to fix that today, at least we can make
8552 * some small improvement.
8554 emitcode("mov", "b,#!constbyte",
8555 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8559 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8560 emitcode ("inc", "b");
8562 freeAsmop (right, NULL, ic, TRUE);
8563 aopOp (left, ic, FALSE, FALSE);
8564 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8566 /* now move the left to the result if they are not the
8568 if (!sameRegs (AOP (left), AOP (result)) &&
8569 AOP_SIZE (result) > 1)
8572 size = AOP_SIZE (result);
8574 _startLazyDPSEvaluation ();
8577 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8578 if (*l == '@' && IS_AOP_PREG (result))
8581 emitcode ("mov", "a,%s", l);
8582 aopPut (AOP (result), "a", offset);
8585 aopPut (AOP (result), l, offset);
8588 _endLazyDPSEvaluation ();
8591 tlbl = newiTempLabel (NULL);
8592 tlbl1 = newiTempLabel (NULL);
8593 size = AOP_SIZE (result);
8596 /* if it is only one byte then */
8599 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8601 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8602 emitcode ("", "!tlabeldef", tlbl->key + 100);
8604 emitcode ("rrc", "a");
8605 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8606 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8607 aopPut (AOP (result), "a", 0);
8611 reAdjustPreg (AOP (result));
8612 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8613 emitcode ("", "!tlabeldef", tlbl->key + 100);
8615 _startLazyDPSEvaluation ();
8618 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8620 emitcode ("rrc", "a");
8621 aopPut (AOP (result), "a", offset--);
8623 _endLazyDPSEvaluation ();
8624 reAdjustPreg (AOP (result));
8626 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8627 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8630 freeAsmop (left, NULL, ic, TRUE);
8631 freeAsmop (result, NULL, ic, TRUE);
8634 /*-----------------------------------------------------------------*/
8635 /* genUnpackBits - generates code for unpacking bits */
8636 /*-----------------------------------------------------------------*/
8638 genUnpackBits (operand * result, char *rname, int ptype)
8645 D (emitcode (";", "genUnpackBits ");
8648 etype = getSpec (operandType (result));
8650 /* read the first byte */
8656 emitcode ("mov", "a,@%s", rname);
8660 emitcode ("movx", "a,@%s", rname);
8664 emitcode ("movx", "a,@dptr");
8668 emitcode ("clr", "a");
8669 emitcode ("movc", "a,@a+dptr");
8673 emitcode ("lcall", "__gptrget");
8677 /* if we have bitdisplacement then it fits */
8678 /* into this byte completely or if length is */
8679 /* less than a byte */
8680 if ((shCnt = SPEC_BSTR (etype)) ||
8681 (SPEC_BLEN (etype) <= 8))
8684 /* shift right acc */
8687 emitcode ("anl", "a,#!constbyte",
8688 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8689 aopPut (AOP (result), "a", offset);
8693 /* bit field did not fit in a byte */
8694 rlen = SPEC_BLEN (etype) - 8;
8695 aopPut (AOP (result), "a", offset++);
8704 emitcode ("inc", "%s", rname);
8705 emitcode ("mov", "a,@%s", rname);
8709 emitcode ("inc", "%s", rname);
8710 emitcode ("movx", "a,@%s", rname);
8714 emitcode ("inc", "dptr");
8715 emitcode ("movx", "a,@dptr");
8719 emitcode ("clr", "a");
8720 emitcode ("inc", "dptr");
8721 emitcode ("movc", "a,@a+dptr");
8725 emitcode ("inc", "dptr");
8726 emitcode ("lcall", "__gptrget");
8731 /* if we are done */
8735 aopPut (AOP (result), "a", offset++);
8741 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8742 aopPut (AOP (result), "a", offset);
8749 /*-----------------------------------------------------------------*/
8750 /* genDataPointerGet - generates code when ptr offset is known */
8751 /*-----------------------------------------------------------------*/
8753 genDataPointerGet (operand * left,
8759 int size, offset = 0;
8760 aopOp (result, ic, TRUE, FALSE);
8762 /* get the string representation of the name */
8763 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8764 size = AOP_SIZE (result);
8765 _startLazyDPSEvaluation ();
8769 sprintf (buffer, "(%s + %d)", l + 1, offset);
8771 sprintf (buffer, "%s", l + 1);
8772 aopPut (AOP (result), buffer, offset++);
8774 _endLazyDPSEvaluation ();
8776 freeAsmop (left, NULL, ic, TRUE);
8777 freeAsmop (result, NULL, ic, TRUE);
8780 /*-----------------------------------------------------------------*/
8781 /* genNearPointerGet - emitcode for near pointer fetch */
8782 /*-----------------------------------------------------------------*/
8784 genNearPointerGet (operand * left,
8792 sym_link *rtype, *retype, *letype;
8793 sym_link *ltype = operandType (left);
8796 rtype = operandType (result);
8797 retype = getSpec (rtype);
8798 letype = getSpec (ltype);
8800 aopOp (left, ic, FALSE, FALSE);
8802 /* if left is rematerialisable and
8803 result is not bit variable type and
8804 the left is pointer to data space i.e
8805 lower 128 bytes of space */
8806 if (AOP_TYPE (left) == AOP_IMMD &&
8807 !IS_BITVAR (retype) &&
8808 !IS_BITVAR (letype) &&
8809 DCL_TYPE (ltype) == POINTER)
8811 genDataPointerGet (left, result, ic);
8815 /* if the value is already in a pointer register
8816 then don't need anything more */
8817 if (!AOP_INPREG (AOP (left)))
8819 /* otherwise get a free pointer register */
8821 preg = getFreePtr (ic, &aop, FALSE);
8822 emitcode ("mov", "%s,%s",
8824 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8828 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8830 freeAsmop (left, NULL, ic, TRUE);
8831 aopOp (result, ic, FALSE, FALSE);
8833 /* if bitfield then unpack the bits */
8834 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8835 genUnpackBits (result, rname, POINTER);
8838 /* we have can just get the values */
8839 int size = AOP_SIZE (result);
8844 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8847 emitcode ("mov", "a,@%s", rname);
8848 aopPut (AOP (result), "a", offset);
8852 sprintf (buffer, "@%s", rname);
8853 aopPut (AOP (result), buffer, offset);
8857 emitcode ("inc", "%s", rname);
8861 /* now some housekeeping stuff */
8864 /* we had to allocate for this iCode */
8865 if (pi) { /* post increment present */
8866 aopPut(AOP ( left ),rname,0);
8868 freeAsmop (NULL, aop, ic, TRUE);
8872 /* we did not allocate which means left
8873 already in a pointer register, then
8874 if size > 0 && this could be used again
8875 we have to point it back to where it
8877 if (AOP_SIZE (result) > 1 &&
8878 !OP_SYMBOL (left)->remat &&
8879 (OP_SYMBOL (left)->liveTo > ic->seq ||
8883 int size = AOP_SIZE (result) - 1;
8885 emitcode ("dec", "%s", rname);
8890 freeAsmop (result, NULL, ic, TRUE);
8891 if (pi) pi->generated = 1;
8894 /*-----------------------------------------------------------------*/
8895 /* genPagedPointerGet - emitcode for paged pointer fetch */
8896 /*-----------------------------------------------------------------*/
8898 genPagedPointerGet (operand * left,
8906 sym_link *rtype, *retype, *letype;
8908 rtype = operandType (result);
8909 retype = getSpec (rtype);
8910 letype = getSpec (operandType (left));
8911 aopOp (left, ic, FALSE, FALSE);
8913 /* if the value is already in a pointer register
8914 then don't need anything more */
8915 if (!AOP_INPREG (AOP (left)))
8917 /* otherwise get a free pointer register */
8919 preg = getFreePtr (ic, &aop, FALSE);
8920 emitcode ("mov", "%s,%s",
8922 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8926 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8928 freeAsmop (left, NULL, ic, TRUE);
8929 aopOp (result, ic, FALSE, FALSE);
8931 /* if bitfield then unpack the bits */
8932 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8933 genUnpackBits (result, rname, PPOINTER);
8936 /* we have can just get the values */
8937 int size = AOP_SIZE (result);
8943 emitcode ("movx", "a,@%s", rname);
8944 aopPut (AOP (result), "a", offset);
8949 emitcode ("inc", "%s", rname);
8953 /* now some housekeeping stuff */
8956 /* we had to allocate for this iCode */
8957 if (pi) aopPut ( AOP (left), rname, 0);
8958 freeAsmop (NULL, aop, ic, TRUE);
8962 /* we did not allocate which means left
8963 already in a pointer register, then
8964 if size > 0 && this could be used again
8965 we have to point it back to where it
8967 if (AOP_SIZE (result) > 1 &&
8968 !OP_SYMBOL (left)->remat &&
8969 (OP_SYMBOL (left)->liveTo > ic->seq ||
8973 int size = AOP_SIZE (result) - 1;
8975 emitcode ("dec", "%s", rname);
8980 freeAsmop (result, NULL, ic, TRUE);
8981 if (pi) pi->generated = 1;
8984 /*-----------------------------------------------------------------*/
8985 /* genFarPointerGet - gget value from far space */
8986 /*-----------------------------------------------------------------*/
8988 genFarPointerGet (operand * left,
8989 operand * result, iCode * ic, iCode *pi)
8991 int size, offset, dopi=1;
8992 sym_link *retype = getSpec (operandType (result));
8993 sym_link *letype = getSpec (operandType (left));
8994 D (emitcode (";", "genFarPointerGet");
8997 aopOp (left, ic, FALSE, FALSE);
8999 /* if the operand is already in dptr
9000 then we do nothing else we move the value to dptr */
9001 if (AOP_TYPE (left) != AOP_STR)
9003 /* if this is remateriazable */
9004 if (AOP_TYPE (left) == AOP_IMMD)
9006 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9010 /* we need to get it byte by byte */
9011 _startLazyDPSEvaluation ();
9012 if (AOP_TYPE (left) != AOP_DPTR)
9014 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9015 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9016 if (options.model == MODEL_FLAT24)
9017 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9021 /* We need to generate a load to DPTR indirect through DPTR. */
9022 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9024 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9025 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9026 if (options.model == MODEL_FLAT24)
9027 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9028 emitcode ("pop", "dph");
9029 emitcode ("pop", "dpl");
9032 _endLazyDPSEvaluation ();
9035 /* so dptr know contains the address */
9036 aopOp (result, ic, FALSE, TRUE);
9038 /* if bit then unpack */
9039 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9040 genUnpackBits (result, "dptr", FPOINTER);
9043 size = AOP_SIZE (result);
9046 _startLazyDPSEvaluation ();
9053 emitcode ("movx", "a,@dptr");
9054 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9055 emitcode ("inc", "dptr");
9057 aopPut (AOP (result), "a", offset++);
9059 _endLazyDPSEvaluation ();
9061 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9062 aopPut ( AOP (left), "dpl", 0);
9063 aopPut ( AOP (left), "dph", 1);
9064 if (options.model == MODEL_FLAT24)
9065 aopPut ( AOP (left), "dpx", 2);
9067 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9068 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9070 size = AOP_SIZE (result) - 1;
9071 while (size--) emitcode ("lcall","__decdptr");
9074 freeAsmop (left, NULL, ic, TRUE);
9075 freeAsmop (result, NULL, ic, TRUE);
9078 /*-----------------------------------------------------------------*/
9079 /* emitcodePointerGet - gget value from code space */
9080 /*-----------------------------------------------------------------*/
9082 emitcodePointerGet (operand * left,
9083 operand * result, iCode * ic, iCode *pi)
9085 int size, offset, dopi=1;
9086 sym_link *retype = getSpec (operandType (result));
9088 aopOp (left, ic, FALSE, FALSE);
9090 /* if the operand is already in dptr
9091 then we do nothing else we move the value to dptr */
9092 if (AOP_TYPE (left) != AOP_STR)
9094 /* if this is remateriazable */
9095 if (AOP_TYPE (left) == AOP_IMMD)
9097 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9100 { /* we need to get it byte by byte */
9101 _startLazyDPSEvaluation ();
9102 if (AOP_TYPE (left) != AOP_DPTR)
9104 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9105 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9106 if (options.model == MODEL_FLAT24)
9107 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9111 /* We need to generate a load to DPTR indirect through DPTR. */
9112 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9114 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9115 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9116 if (options.model == MODEL_FLAT24)
9117 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9118 emitcode ("pop", "dph");
9119 emitcode ("pop", "dpl");
9122 _endLazyDPSEvaluation ();
9125 /* so dptr know contains the address */
9126 aopOp (result, ic, FALSE, TRUE);
9128 /* if bit then unpack */
9129 if (IS_BITVAR (retype))
9130 genUnpackBits (result, "dptr", CPOINTER);
9133 size = AOP_SIZE (result);
9136 _startLazyDPSEvaluation ();
9142 emitcode ("clr", "a");
9143 emitcode ("movc", "a,@a+dptr");
9144 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9145 emitcode ("inc", "dptr");
9146 aopPut (AOP (result), "a", offset++);
9148 _endLazyDPSEvaluation ();
9150 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9151 aopPut ( AOP (left), "dpl", 0);
9152 aopPut ( AOP (left), "dph", 1);
9153 if (options.model == MODEL_FLAT24)
9154 aopPut ( AOP (left), "dpx", 2);
9156 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9157 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9159 size = AOP_SIZE (result) - 1;
9160 while (size--) emitcode ("lcall","__decdptr");
9163 freeAsmop (left, NULL, ic, TRUE);
9164 freeAsmop (result, NULL, ic, TRUE);
9167 /*-----------------------------------------------------------------*/
9168 /* genGenPointerGet - gget value from generic pointer space */
9169 /*-----------------------------------------------------------------*/
9171 genGenPointerGet (operand * left,
9172 operand * result, iCode * ic, iCode * pi)
9175 sym_link *retype = getSpec (operandType (result));
9176 sym_link *letype = getSpec (operandType (left));
9178 D (emitcode (";", "genGenPointerGet "); );
9180 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9182 /* if the operand is already in dptr
9183 then we do nothing else we move the value to dptr */
9184 if (AOP_TYPE (left) != AOP_STR)
9186 /* if this is remateriazable */
9187 if (AOP_TYPE (left) == AOP_IMMD)
9189 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9190 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9191 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9193 emitcode ("mov", "b,#%d", pointerCode (retype));
9196 { /* we need to get it byte by byte */
9197 _startLazyDPSEvaluation ();
9198 if (AOP(left)->type==AOP_DPTR2) {
9200 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9203 emitcode ("mov", "dpl,%s", l);
9204 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9207 emitcode ("mov", "dph,%s", l);
9208 if (options.model == MODEL_FLAT24) {
9209 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9212 emitcode ("mov", "dpx,%s", l);
9213 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9215 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9218 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9219 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9220 if (options.model == MODEL_FLAT24) {
9221 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9222 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9224 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9227 _endLazyDPSEvaluation ();
9230 /* so dptr know contains the address */
9231 aopOp (result, ic, FALSE, TRUE);
9233 /* if bit then unpack */
9234 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9235 genUnpackBits (result, "dptr", GPOINTER);
9238 size = AOP_SIZE (result);
9243 emitcode ("lcall", "__gptrget");
9244 aopPut (AOP (result), "a", offset++);
9245 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9246 emitcode ("inc", "dptr");
9250 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9251 aopPut ( AOP (left), "dpl", 0);
9252 aopPut ( AOP (left), "dph", 1);
9253 if (options.model == MODEL_FLAT24) {
9254 aopPut ( AOP (left), "dpx", 2);
9255 aopPut ( AOP (left), "b", 3);
9256 } else aopPut ( AOP (left), "b", 2);
9258 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9259 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9261 size = AOP_SIZE (result) - 1;
9262 while (size--) emitcode ("lcall","__decdptr");
9265 freeAsmop (left, NULL, ic, TRUE);
9266 freeAsmop (result, NULL, ic, TRUE);
9269 /*-----------------------------------------------------------------*/
9270 /* genPointerGet - generate code for pointer get */
9271 /*-----------------------------------------------------------------*/
9273 genPointerGet (iCode * ic, iCode *pi)
9275 operand *left, *result;
9276 sym_link *type, *etype;
9279 D (emitcode (";", "genPointerGet ");
9282 left = IC_LEFT (ic);
9283 result = IC_RESULT (ic);
9285 /* depending on the type of pointer we need to
9286 move it to the correct pointer register */
9287 type = operandType (left);
9288 etype = getSpec (type);
9289 /* if left is of type of pointer then it is simple */
9290 if (IS_PTR (type) && !IS_FUNC (type->next))
9291 p_type = DCL_TYPE (type);
9294 /* we have to go by the storage class */
9295 p_type = PTR_TYPE (SPEC_OCLS (etype));
9297 /* special case when cast remat */
9298 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9299 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9300 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9301 type = type = operandType (left);
9302 p_type = DCL_TYPE (type);
9304 /* now that we have the pointer type we assign
9305 the pointer values */
9311 genNearPointerGet (left, result, ic, pi);
9315 genPagedPointerGet (left, result, ic, pi);
9319 genFarPointerGet (left, result, ic, pi);
9323 emitcodePointerGet (left, result, ic, pi);
9327 genGenPointerGet (left, result, ic, pi);
9333 /*-----------------------------------------------------------------*/
9334 /* genPackBits - generates code for packed bit storage */
9335 /*-----------------------------------------------------------------*/
9337 genPackBits (sym_link * etype,
9339 char *rname, int p_type)
9347 blen = SPEC_BLEN (etype);
9348 bstr = SPEC_BSTR (etype);
9350 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9353 /* if the bit lenth is less than or */
9354 /* it exactly fits a byte then */
9355 if (SPEC_BLEN (etype) <= 8)
9357 shCount = SPEC_BSTR (etype);
9359 /* shift left acc */
9362 if (SPEC_BLEN (etype) < 8)
9363 { /* if smaller than a byte */
9369 emitcode ("mov", "b,a");
9370 emitcode ("mov", "a,@%s", rname);
9374 emitcode ("mov", "b,a");
9375 emitcode ("movx", "a,@dptr");
9379 emitcode ("push", "b");
9380 emitcode ("push", "acc");
9381 emitcode ("lcall", "__gptrget");
9382 emitcode ("pop", "b");
9386 emitcode ("anl", "a,#!constbyte", (unsigned char)
9387 ((unsigned char) (0xFF << (blen + bstr)) |
9388 (unsigned char) (0xFF >> (8 - bstr))));
9389 emitcode ("orl", "a,b");
9390 if (p_type == GPOINTER)
9391 emitcode ("pop", "b");
9398 emitcode ("mov", "@%s,a", rname);
9402 emitcode ("movx", "@dptr,a");
9406 emitcode ("lcall", "__gptrput");
9411 if (SPEC_BLEN (etype) <= 8)
9414 emitcode ("inc", "%s", rname);
9415 rLen = SPEC_BLEN (etype);
9417 /* now generate for lengths greater than one byte */
9421 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9433 emitcode ("mov", "@%s,a", rname);
9436 emitcode ("mov", "@%s,%s", rname, l);
9441 emitcode ("movx", "@dptr,a");
9446 emitcode ("lcall", "__gptrput");
9449 emitcode ("inc", "%s", rname);
9454 /* last last was not complete */
9457 /* save the byte & read byte */
9461 emitcode ("mov", "b,a");
9462 emitcode ("mov", "a,@%s", rname);
9466 emitcode ("mov", "b,a");
9467 emitcode ("movx", "a,@dptr");
9471 emitcode ("push", "b");
9472 emitcode ("push", "acc");
9473 emitcode ("lcall", "__gptrget");
9474 emitcode ("pop", "b");
9478 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9479 emitcode ("orl", "a,b");
9482 if (p_type == GPOINTER)
9483 emitcode ("pop", "b");
9489 emitcode ("mov", "@%s,a", rname);
9493 emitcode ("movx", "@dptr,a");
9497 emitcode ("lcall", "__gptrput");
9501 /*-----------------------------------------------------------------*/
9502 /* genDataPointerSet - remat pointer to data space */
9503 /*-----------------------------------------------------------------*/
9505 genDataPointerSet (operand * right,
9509 int size, offset = 0;
9510 char *l, buffer[256];
9512 aopOp (right, ic, FALSE, FALSE);
9514 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9515 size = AOP_SIZE (right);
9519 sprintf (buffer, "(%s + %d)", l + 1, offset);
9521 sprintf (buffer, "%s", l + 1);
9522 emitcode ("mov", "%s,%s", buffer,
9523 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9526 freeAsmop (right, NULL, ic, TRUE);
9527 freeAsmop (result, NULL, ic, TRUE);
9530 /*-----------------------------------------------------------------*/
9531 /* genNearPointerSet - emitcode for near pointer put */
9532 /*-----------------------------------------------------------------*/
9534 genNearPointerSet (operand * right,
9542 sym_link *retype, *letype;
9543 sym_link *ptype = operandType (result);
9545 retype = getSpec (operandType (right));
9546 letype = getSpec (ptype);
9548 aopOp (result, ic, FALSE, FALSE);
9550 /* if the result is rematerializable &
9551 in data space & not a bit variable */
9552 if (AOP_TYPE (result) == AOP_IMMD &&
9553 DCL_TYPE (ptype) == POINTER &&
9554 !IS_BITVAR (retype) &&
9555 !IS_BITVAR (letype))
9557 genDataPointerSet (right, result, ic);
9561 /* if the value is already in a pointer register
9562 then don't need anything more */
9563 if (!AOP_INPREG (AOP (result)))
9565 /* otherwise get a free pointer register */
9567 preg = getFreePtr (ic, &aop, FALSE);
9568 emitcode ("mov", "%s,%s",
9570 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9574 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9576 aopOp (right, ic, FALSE, FALSE);
9578 /* if bitfield then unpack the bits */
9579 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9580 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9583 /* we have can just get the values */
9584 int size = AOP_SIZE (right);
9589 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9593 emitcode ("mov", "@%s,a", rname);
9596 emitcode ("mov", "@%s,%s", rname, l);
9598 emitcode ("inc", "%s", rname);
9603 /* now some housekeeping stuff */
9606 /* we had to allocate for this iCode */
9607 if (pi) aopPut (AOP (result),rname,0);
9608 freeAsmop (NULL, aop, ic, TRUE);
9612 /* we did not allocate which means left
9613 already in a pointer register, then
9614 if size > 0 && this could be used again
9615 we have to point it back to where it
9617 if (AOP_SIZE (right) > 1 &&
9618 !OP_SYMBOL (result)->remat &&
9619 (OP_SYMBOL (result)->liveTo > ic->seq ||
9623 int size = AOP_SIZE (right) - 1;
9625 emitcode ("dec", "%s", rname);
9630 if (pi) pi->generated = 1;
9631 freeAsmop (result, NULL, ic, TRUE);
9632 freeAsmop (right, NULL, ic, TRUE);
9637 /*-----------------------------------------------------------------*/
9638 /* genPagedPointerSet - emitcode for Paged pointer put */
9639 /*-----------------------------------------------------------------*/
9641 genPagedPointerSet (operand * right,
9649 sym_link *retype, *letype;
9651 retype = getSpec (operandType (right));
9652 letype = getSpec (operandType (result));
9654 aopOp (result, ic, FALSE, FALSE);
9656 /* if the value is already in a pointer register
9657 then don't need anything more */
9658 if (!AOP_INPREG (AOP (result)))
9660 /* otherwise get a free pointer register */
9662 preg = getFreePtr (ic, &aop, FALSE);
9663 emitcode ("mov", "%s,%s",
9665 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9669 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9671 aopOp (right, ic, FALSE, FALSE);
9673 /* if bitfield then unpack the bits */
9674 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9675 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9678 /* we have can just get the values */
9679 int size = AOP_SIZE (right);
9684 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9687 emitcode ("movx", "@%s,a", rname);
9690 emitcode ("inc", "%s", rname);
9696 /* now some housekeeping stuff */
9699 if (pi) aopPut (AOP (result),rname,0);
9700 /* we had to allocate for this iCode */
9701 freeAsmop (NULL, aop, ic, TRUE);
9705 /* we did not allocate which means left
9706 already in a pointer register, then
9707 if size > 0 && this could be used again
9708 we have to point it back to where it
9710 if (AOP_SIZE (right) > 1 &&
9711 !OP_SYMBOL (result)->remat &&
9712 (OP_SYMBOL (result)->liveTo > ic->seq ||
9716 int size = AOP_SIZE (right) - 1;
9718 emitcode ("dec", "%s", rname);
9723 if (pi) pi->generated = 1;
9724 freeAsmop (result, NULL, ic, TRUE);
9725 freeAsmop (right, NULL, ic, TRUE);
9730 /*-----------------------------------------------------------------*/
9731 /* genFarPointerSet - set value from far space */
9732 /*-----------------------------------------------------------------*/
9734 genFarPointerSet (operand * right,
9735 operand * result, iCode * ic, iCode *pi)
9737 int size, offset, dopi=1;
9738 sym_link *retype = getSpec (operandType (right));
9739 sym_link *letype = getSpec (operandType (result));
9741 aopOp (result, ic, FALSE, FALSE);
9743 /* if the operand is already in dptr
9744 then we do nothing else we move the value to dptr */
9745 if (AOP_TYPE (result) != AOP_STR)
9747 /* if this is remateriazable */
9748 if (AOP_TYPE (result) == AOP_IMMD)
9749 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9752 /* we need to get it byte by byte */
9753 _startLazyDPSEvaluation ();
9754 if (AOP_TYPE (result) != AOP_DPTR)
9756 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9757 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9758 if (options.model == MODEL_FLAT24)
9759 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9763 /* We need to generate a load to DPTR indirect through DPTR. */
9764 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9766 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9767 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9768 if (options.model == MODEL_FLAT24)
9769 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9770 emitcode ("pop", "dph");
9771 emitcode ("pop", "dpl");
9774 _endLazyDPSEvaluation ();
9777 /* so dptr know contains the address */
9778 aopOp (right, ic, FALSE, TRUE);
9780 /* if bit then unpack */
9781 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9782 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9785 size = AOP_SIZE (right);
9788 _startLazyDPSEvaluation ();
9791 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9797 emitcode ("movx", "@dptr,a");
9798 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9799 emitcode ("inc", "dptr");
9801 _endLazyDPSEvaluation ();
9804 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9805 aopPut (AOP(result),"dpl",0);
9806 aopPut (AOP(result),"dph",1);
9807 if (options.model == MODEL_FLAT24)
9808 aopPut (AOP(result),"dpx",2);
9810 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9811 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9813 size = AOP_SIZE (right) - 1;
9814 while (size--) emitcode ("lcall","__decdptr");
9816 freeAsmop (result, NULL, ic, TRUE);
9817 freeAsmop (right, NULL, ic, TRUE);
9820 /*-----------------------------------------------------------------*/
9821 /* genGenPointerSet - set value from generic pointer space */
9822 /*-----------------------------------------------------------------*/
9824 genGenPointerSet (operand * right,
9825 operand * result, iCode * ic, iCode *pi)
9828 sym_link *retype = getSpec (operandType (right));
9829 sym_link *letype = getSpec (operandType (result));
9831 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9833 /* if the operand is already in dptr
9834 then we do nothing else we move the value to dptr */
9835 if (AOP_TYPE (result) != AOP_STR)
9837 _startLazyDPSEvaluation ();
9838 /* if this is remateriazable */
9839 if (AOP_TYPE (result) == AOP_IMMD)
9841 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9842 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9843 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9845 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9848 { /* we need to get it byte by byte */
9849 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9850 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9851 if (options.model == MODEL_FLAT24) {
9852 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9853 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9855 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9858 _endLazyDPSEvaluation ();
9860 /* so dptr know contains the address */
9861 aopOp (right, ic, FALSE, TRUE);
9863 /* if bit then unpack */
9864 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9865 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9868 size = AOP_SIZE (right);
9871 _startLazyDPSEvaluation ();
9874 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9880 emitcode ("lcall", "__gptrput");
9881 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9882 emitcode ("inc", "dptr");
9884 _endLazyDPSEvaluation ();
9887 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9888 aopPut (AOP(result),"dpl",0);
9889 aopPut (AOP(result),"dph",1);
9890 if (options.model == MODEL_FLAT24) {
9891 aopPut (AOP(result),"dpx",2);
9892 aopPut (AOP(result),"b",3);
9894 aopPut (AOP(result),"b",2);
9897 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9898 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9900 size = AOP_SIZE (right) - 1;
9901 while (size--) emitcode ("lcall","__decdptr");
9903 freeAsmop (result, NULL, ic, TRUE);
9904 freeAsmop (right, NULL, ic, TRUE);
9907 /*-----------------------------------------------------------------*/
9908 /* genPointerSet - stores the value into a pointer location */
9909 /*-----------------------------------------------------------------*/
9911 genPointerSet (iCode * ic, iCode *pi)
9913 operand *right, *result;
9914 sym_link *type, *etype;
9917 D (emitcode (";", "genPointerSet ");
9920 right = IC_RIGHT (ic);
9921 result = IC_RESULT (ic);
9923 /* depending on the type of pointer we need to
9924 move it to the correct pointer register */
9925 type = operandType (result);
9926 etype = getSpec (type);
9927 /* if left is of type of pointer then it is simple */
9928 if (IS_PTR (type) && !IS_FUNC (type->next))
9930 p_type = DCL_TYPE (type);
9934 /* we have to go by the storage class */
9935 p_type = PTR_TYPE (SPEC_OCLS (etype));
9937 /* special case when cast remat */
9938 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9939 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9940 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9941 type = type = operandType (result);
9942 p_type = DCL_TYPE (type);
9945 /* now that we have the pointer type we assign
9946 the pointer values */
9952 genNearPointerSet (right, result, ic, pi);
9956 genPagedPointerSet (right, result, ic, pi);
9960 genFarPointerSet (right, result, ic, pi);
9964 genGenPointerSet (right, result, ic, pi);
9970 /*-----------------------------------------------------------------*/
9971 /* genIfx - generate code for Ifx statement */
9972 /*-----------------------------------------------------------------*/
9974 genIfx (iCode * ic, iCode * popIc)
9976 operand *cond = IC_COND (ic);
9979 D (emitcode (";", "genIfx "););
9981 aopOp (cond, ic, FALSE, FALSE);
9983 /* get the value into acc */
9984 if (AOP_TYPE (cond) != AOP_CRY)
9988 /* the result is now in the accumulator */
9989 freeAsmop (cond, NULL, ic, TRUE);
9991 /* if there was something to be popped then do it */
9995 /* if the condition is a bit variable */
9996 if (isbit && IS_ITEMP (cond) &&
9998 genIfxJump (ic, SPIL_LOC (cond)->rname);
9999 else if (isbit && !IS_ITEMP (cond))
10000 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10002 genIfxJump (ic, "a");
10007 /*-----------------------------------------------------------------*/
10008 /* genAddrOf - generates code for address of */
10009 /*-----------------------------------------------------------------*/
10011 genAddrOf (iCode * ic)
10013 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10016 D (emitcode (";", "genAddrOf ");
10019 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10021 /* if the operand is on the stack then we
10022 need to get the stack offset of this
10024 if (sym->onStack) {
10026 /* if 10 bit stack */
10027 if (options.stack10bit) {
10029 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10030 /* if it has an offset then we need to compute it */
10031 emitcode ("subb", "a,#!constbyte",
10032 -((sym->stack < 0) ?
10033 ((short) (sym->stack - _G.nRegsSaved)) :
10034 ((short) sym->stack)) & 0xff);
10035 emitcode ("mov","b,a");
10036 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10037 ((short) (sym->stack - _G.nRegsSaved)) :
10038 ((short) sym->stack)) >> 8) & 0xff);
10040 emitcode ("mov", "a,_bpx");
10041 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10042 ((char) (sym->stack - _G.nRegsSaved)) :
10043 ((char) sym->stack )) & 0xff);
10044 emitcode ("mov", "b,a");
10045 emitcode ("mov", "a,_bpx+1");
10046 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10047 ((short) (sym->stack - _G.nRegsSaved)) :
10048 ((short) sym->stack )) >> 8) & 0xff);
10049 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10050 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10051 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10053 /* we can just move _bp */
10054 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10055 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10056 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10059 /* if it has an offset then we need to compute it */
10061 emitcode ("mov", "a,_bp");
10062 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10063 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10065 /* we can just move _bp */
10066 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10068 /* fill the result with zero */
10069 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10072 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10074 "*** warning: pointer to stack var truncated.\n");
10079 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10085 /* object not on stack then we need the name */
10086 size = AOP_SIZE (IC_RESULT (ic));
10091 char s[SDCC_NAME_MAX];
10095 tsprintf(s,"!his",sym->rname);
10098 tsprintf(s,"!hihis",sym->rname);
10101 tsprintf(s,"!hihihis",sym->rname);
10103 default: /* should not need this (just in case) */
10104 sprintf (s, "#(%s >> %d)",
10109 sprintf (s, "#%s", sym->rname);
10110 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10114 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10118 /*-----------------------------------------------------------------*/
10119 /* genArrayInit - generates code for address of */
10120 /*-----------------------------------------------------------------*/
10122 genArrayInit (iCode * ic)
10124 literalList *iLoop;
10126 int elementSize = 0, eIndex;
10127 unsigned val, lastVal;
10129 operand *left=IC_LEFT(ic);
10131 D (emitcode (";", "genArrayInit "););
10133 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10135 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10137 // Load immediate value into DPTR.
10138 emitcode("mov", "dptr, %s",
10139 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10141 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10144 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10145 "Unexpected operand to genArrayInit.\n");
10148 // a regression because of SDCCcse.c:1.52
10149 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10150 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10151 if (options.model == MODEL_FLAT24)
10152 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10156 type = operandType(IC_LEFT(ic));
10158 if (type && type->next)
10160 elementSize = getSize(type->next);
10164 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10165 "can't determine element size in genArrayInit.\n");
10169 iLoop = IC_ARRAYILIST(ic);
10174 bool firstpass = TRUE;
10176 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10177 iLoop->count, (int)iLoop->literalValue, elementSize);
10183 symbol *tlbl = NULL;
10185 count = ix > 256 ? 256 : ix;
10189 tlbl = newiTempLabel (NULL);
10190 if (firstpass || (count & 0xff))
10192 emitcode("mov", "b, #!constbyte", count & 0xff);
10195 emitcode ("", "!tlabeldef", tlbl->key + 100);
10200 for (eIndex = 0; eIndex < elementSize; eIndex++)
10202 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10203 if (val != lastVal)
10205 emitcode("mov", "a, #!constbyte", val);
10209 emitcode("movx", "@dptr, a");
10210 emitcode("inc", "dptr");
10215 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10221 iLoop = iLoop->next;
10224 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10227 /*-----------------------------------------------------------------*/
10228 /* genFarFarAssign - assignment when both are in far space */
10229 /*-----------------------------------------------------------------*/
10231 genFarFarAssign (operand * result, operand * right, iCode * ic)
10233 int size = AOP_SIZE (right);
10235 symbol *rSym = NULL;
10239 /* quick & easy case. */
10240 D(emitcode(";","genFarFarAssign (1 byte case)"););
10241 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10242 freeAsmop (right, NULL, ic, FALSE);
10243 /* now assign DPTR to result */
10245 aopOp(result, ic, FALSE, FALSE);
10247 aopPut(AOP(result), "a", 0);
10248 freeAsmop(result, NULL, ic, FALSE);
10252 /* See if we've got an underlying symbol to abuse. */
10253 if (IS_SYMOP(result) && OP_SYMBOL(result))
10255 if (IS_TRUE_SYMOP(result))
10257 rSym = OP_SYMBOL(result);
10259 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10261 rSym = OP_SYMBOL(result)->usl.spillLoc;
10265 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10267 /* We can use the '390 auto-toggle feature to good effect here. */
10269 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10270 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10271 emitcode ("mov", "dptr,#%s", rSym->rname);
10272 /* DP2 = result, DP1 = right, DP1 is current. */
10275 emitcode("movx", "a,@dptr");
10276 emitcode("movx", "@dptr,a");
10279 emitcode("inc", "dptr");
10280 emitcode("inc", "dptr");
10283 emitcode("mov", "dps,#0");
10284 freeAsmop (right, NULL, ic, FALSE);
10286 some alternative code for processors without auto-toggle
10287 no time to test now, so later well put in...kpb
10288 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10289 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10290 emitcode ("mov", "dptr,#%s", rSym->rname);
10291 /* DP2 = result, DP1 = right, DP1 is current. */
10295 emitcode("movx", "a,@dptr");
10297 emitcode("inc", "dptr");
10298 emitcode("inc", "dps");
10299 emitcode("movx", "@dptr,a");
10301 emitcode("inc", "dptr");
10302 emitcode("inc", "dps");
10304 emitcode("mov", "dps,#0");
10305 freeAsmop (right, NULL, ic, FALSE);
10310 D (emitcode (";", "genFarFarAssign"););
10311 aopOp (result, ic, TRUE, TRUE);
10313 _startLazyDPSEvaluation ();
10317 aopPut (AOP (result),
10318 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10321 _endLazyDPSEvaluation ();
10322 freeAsmop (result, NULL, ic, FALSE);
10323 freeAsmop (right, NULL, ic, FALSE);
10327 /*-----------------------------------------------------------------*/
10328 /* genAssign - generate code for assignment */
10329 /*-----------------------------------------------------------------*/
10331 genAssign (iCode * ic)
10333 operand *result, *right;
10335 unsigned long lit = 0L;
10337 D (emitcode (";", "genAssign ");
10340 result = IC_RESULT (ic);
10341 right = IC_RIGHT (ic);
10343 /* if they are the same */
10344 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10347 aopOp (right, ic, FALSE, FALSE);
10349 emitcode (";", "genAssign: resultIsFar = %s",
10350 isOperandInFarSpace (result) ?
10353 /* special case both in far space */
10354 if ((AOP_TYPE (right) == AOP_DPTR ||
10355 AOP_TYPE (right) == AOP_DPTR2) &&
10356 /* IS_TRUE_SYMOP(result) && */
10357 isOperandInFarSpace (result))
10359 genFarFarAssign (result, right, ic);
10363 aopOp (result, ic, TRUE, FALSE);
10365 /* if they are the same registers */
10366 if (sameRegs (AOP (right), AOP (result)))
10369 /* if the result is a bit */
10370 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10372 /* if the right size is a literal then
10373 we know what the value is */
10374 if (AOP_TYPE (right) == AOP_LIT)
10376 if (((int) operandLitValue (right)))
10377 aopPut (AOP (result), one, 0);
10379 aopPut (AOP (result), zero, 0);
10383 /* the right is also a bit variable */
10384 if (AOP_TYPE (right) == AOP_CRY)
10386 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10387 aopPut (AOP (result), "c", 0);
10391 /* we need to or */
10393 aopPut (AOP (result), "a", 0);
10397 /* bit variables done */
10399 size = AOP_SIZE (result);
10401 if (AOP_TYPE (right) == AOP_LIT)
10402 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10405 (AOP_TYPE (result) != AOP_REG) &&
10406 (AOP_TYPE (right) == AOP_LIT) &&
10407 !IS_FLOAT (operandType (right)))
10409 _startLazyDPSEvaluation ();
10410 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10412 aopPut (AOP (result),
10413 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10418 /* And now fill the rest with zeros. */
10421 emitcode ("clr", "a");
10425 aopPut (AOP (result), "a", offset++);
10427 _endLazyDPSEvaluation ();
10431 _startLazyDPSEvaluation ();
10434 aopPut (AOP (result),
10435 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10439 _endLazyDPSEvaluation ();
10443 freeAsmop (right, NULL, ic, FALSE);
10444 freeAsmop (result, NULL, ic, TRUE);
10447 /*-----------------------------------------------------------------*/
10448 /* genJumpTab - generates code for jump table */
10449 /*-----------------------------------------------------------------*/
10451 genJumpTab (iCode * ic)
10456 D (emitcode (";", "genJumpTab ");
10459 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10460 /* get the condition into accumulator */
10461 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10463 /* multiply by four! */
10464 emitcode ("add", "a,acc");
10465 emitcode ("add", "a,acc");
10466 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10468 jtab = newiTempLabel (NULL);
10469 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10470 emitcode ("jmp", "@a+dptr");
10471 emitcode ("", "!tlabeldef", jtab->key + 100);
10472 /* now generate the jump labels */
10473 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10474 jtab = setNextItem (IC_JTLABELS (ic)))
10475 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10479 /*-----------------------------------------------------------------*/
10480 /* genCast - gen code for casting */
10481 /*-----------------------------------------------------------------*/
10483 genCast (iCode * ic)
10485 operand *result = IC_RESULT (ic);
10486 sym_link *ctype = operandType (IC_LEFT (ic));
10487 sym_link *rtype = operandType (IC_RIGHT (ic));
10488 operand *right = IC_RIGHT (ic);
10491 D (emitcode (";", "genCast ");
10494 /* if they are equivalent then do nothing */
10495 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10498 aopOp (right, ic, FALSE, FALSE);
10499 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10501 /* if the result is a bit */
10502 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10503 if (IS_BITVAR(OP_SYMBOL(result)->type))
10505 /* if the right size is a literal then
10506 we know what the value is */
10507 if (AOP_TYPE (right) == AOP_LIT)
10509 if (((int) operandLitValue (right)))
10510 aopPut (AOP (result), one, 0);
10512 aopPut (AOP (result), zero, 0);
10517 /* the right is also a bit variable */
10518 if (AOP_TYPE (right) == AOP_CRY)
10520 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10521 aopPut (AOP (result), "c", 0);
10525 /* we need to or */
10527 aopPut (AOP (result), "a", 0);
10531 /* if they are the same size : or less */
10532 if (AOP_SIZE (result) <= AOP_SIZE (right))
10535 /* if they are in the same place */
10536 if (sameRegs (AOP (right), AOP (result)))
10539 /* if they in different places then copy */
10540 size = AOP_SIZE (result);
10542 _startLazyDPSEvaluation ();
10545 aopPut (AOP (result),
10546 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10550 _endLazyDPSEvaluation ();
10555 /* if the result is of type pointer */
10556 if (IS_PTR (ctype))
10560 sym_link *type = operandType (right);
10562 /* pointer to generic pointer */
10563 if (IS_GENPTR (ctype))
10569 p_type = DCL_TYPE (type);
10573 #if OLD_CAST_BEHAVIOR
10574 /* KV: we are converting a non-pointer type to
10575 * a generic pointer. This (ifdef'd out) code
10576 * says that the resulting generic pointer
10577 * should have the same class as the storage
10578 * location of the non-pointer variable.
10580 * For example, converting an int (which happens
10581 * to be stored in DATA space) to a pointer results
10582 * in a DATA generic pointer; if the original int
10583 * in XDATA space, so will be the resulting pointer.
10585 * I don't like that behavior, and thus this change:
10586 * all such conversions will be forced to XDATA and
10587 * throw a warning. If you want some non-XDATA
10588 * type, or you want to suppress the warning, you
10589 * must go through an intermediate cast, like so:
10591 * char _generic *gp = (char _xdata *)(intVar);
10593 sym_link *etype = getSpec (type);
10595 /* we have to go by the storage class */
10596 if (SPEC_OCLS (etype) != generic)
10598 p_type = PTR_TYPE (SPEC_OCLS (etype));
10603 /* Converting unknown class (i.e. register variable)
10604 * to generic pointer. This is not good, but
10605 * we'll make a guess (and throw a warning).
10608 werror (W_INT_TO_GEN_PTR_CAST);
10612 /* the first two bytes are known */
10613 size = GPTRSIZE - 1;
10615 _startLazyDPSEvaluation ();
10618 aopPut (AOP (result),
10619 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10623 _endLazyDPSEvaluation ();
10625 /* the last byte depending on type */
10643 /* this should never happen */
10644 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10645 "got unknown pointer type");
10648 aopPut (AOP (result), l, GPTRSIZE - 1);
10652 /* just copy the pointers */
10653 size = AOP_SIZE (result);
10655 _startLazyDPSEvaluation ();
10658 aopPut (AOP (result),
10659 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10663 _endLazyDPSEvaluation ();
10667 /* so we now know that the size of destination is greater
10668 than the size of the source */
10669 /* we move to result for the size of source */
10670 size = AOP_SIZE (right);
10672 _startLazyDPSEvaluation ();
10675 aopPut (AOP (result),
10676 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10680 _endLazyDPSEvaluation ();
10682 /* now depending on the sign of the source && destination */
10683 size = AOP_SIZE (result) - AOP_SIZE (right);
10684 /* if unsigned or not an integral type */
10685 /* also, if the source is a bit, we don't need to sign extend, because
10686 * it can't possibly have set the sign bit.
10688 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10692 aopPut (AOP (result), zero, offset++);
10697 /* we need to extend the sign :{ */
10698 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10699 FALSE, FALSE, TRUE);
10701 emitcode ("rlc", "a");
10702 emitcode ("subb", "a,acc");
10704 aopPut (AOP (result), "a", offset++);
10707 /* we are done hurray !!!! */
10710 freeAsmop (right, NULL, ic, TRUE);
10711 freeAsmop (result, NULL, ic, TRUE);
10715 /*-----------------------------------------------------------------*/
10716 /* genDjnz - generate decrement & jump if not zero instrucion */
10717 /*-----------------------------------------------------------------*/
10719 genDjnz (iCode * ic, iCode * ifx)
10721 symbol *lbl, *lbl1;
10725 /* if the if condition has a false label
10726 then we cannot save */
10727 if (IC_FALSE (ifx))
10730 /* if the minus is not of the form
10732 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10733 !IS_OP_LITERAL (IC_RIGHT (ic)))
10736 if (operandLitValue (IC_RIGHT (ic)) != 1)
10739 /* if the size of this greater than one then no
10741 if (getSize (operandType (IC_RESULT (ic))) > 1)
10744 /* otherwise we can save BIG */
10745 D(emitcode(";", "genDjnz"););
10747 lbl = newiTempLabel (NULL);
10748 lbl1 = newiTempLabel (NULL);
10750 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10752 if (AOP_NEEDSACC(IC_RESULT(ic)))
10754 /* If the result is accessed indirectly via
10755 * the accumulator, we must explicitly write
10756 * it back after the decrement.
10758 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10760 if (strcmp(rByte, "a"))
10762 /* Something is hopelessly wrong */
10763 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10764 __FILE__, __LINE__);
10765 /* We can just give up; the generated code will be inefficient,
10766 * but what the hey.
10768 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10771 emitcode ("dec", "%s", rByte);
10772 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10773 emitcode ("jnz", "!tlabel", lbl->key + 100);
10775 else if (IS_AOP_PREG (IC_RESULT (ic)))
10777 emitcode ("dec", "%s",
10778 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10779 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10780 emitcode ("jnz", "!tlabel", lbl->key + 100);
10784 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10787 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10788 emitcode ("", "!tlabeldef", lbl->key + 100);
10789 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10790 emitcode ("", "!tlabeldef", lbl1->key + 100);
10792 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10793 ifx->generated = 1;
10797 /*-----------------------------------------------------------------*/
10798 /* genReceive - generate code for a receive iCode */
10799 /*-----------------------------------------------------------------*/
10801 genReceive (iCode * ic)
10804 D (emitcode (";", "genReceive ");
10807 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10808 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10809 IS_TRUE_SYMOP (IC_RESULT (ic))))
10811 int size = getSize (operandType (IC_RESULT (ic)));
10812 int offset = fReturnSizeDS390 - size;
10815 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10816 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10819 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10820 size = AOP_SIZE (IC_RESULT (ic));
10824 emitcode ("pop", "acc");
10825 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10832 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10834 assignResultValue (IC_RESULT (ic));
10837 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10840 /*-----------------------------------------------------------------*/
10841 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10842 /*-----------------------------------------------------------------*/
10843 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10845 operand *from , *to , *count;
10850 /* we know it has to be 3 parameters */
10851 assert (nparms == 3);
10853 rsave = newBitVect(16);
10854 /* save DPTR if it needs to be saved */
10855 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10856 if (bitVectBitValue(ic->rMask,i))
10857 rsave = bitVectSetBit(rsave,i);
10859 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10860 ds390_rUmaskForOp (IC_RESULT(ic))));
10867 aopOp (from, ic->next, FALSE, FALSE);
10869 /* get from into DPTR1 */
10870 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10871 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10872 if (options.model == MODEL_FLAT24) {
10873 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10876 freeAsmop (from, NULL, ic, FALSE);
10877 aopOp (to, ic, FALSE, FALSE);
10878 /* get "to" into DPTR */
10879 /* if the operand is already in dptr
10880 then we do nothing else we move the value to dptr */
10881 if (AOP_TYPE (to) != AOP_STR) {
10882 /* if already in DPTR then we need to push */
10883 if (AOP_TYPE(to) == AOP_DPTR) {
10884 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10885 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10886 if (options.model == MODEL_FLAT24)
10887 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10888 emitcode ("pop", "dph");
10889 emitcode ("pop", "dpl");
10891 _startLazyDPSEvaluation ();
10892 /* if this is remateriazable */
10893 if (AOP_TYPE (to) == AOP_IMMD) {
10894 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10895 } else { /* we need to get it byte by byte */
10896 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10897 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10898 if (options.model == MODEL_FLAT24) {
10899 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10902 _endLazyDPSEvaluation ();
10905 freeAsmop (to, NULL, ic, FALSE);
10907 aopOp (count, ic->next->next, FALSE,FALSE);
10908 lbl =newiTempLabel(NULL);
10910 /* now for the actual copy */
10911 if (AOP_TYPE(count) == AOP_LIT &&
10912 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10913 emitcode (";","OH JOY auto increment with djnz (very fast)");
10914 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10915 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10916 emitcode ("","!tlabeldef",lbl->key+100);
10918 emitcode ("clr","a");
10919 emitcode ("movc", "a,@a+dptr");
10921 emitcode ("movx", "a,@dptr");
10922 emitcode ("movx", "@dptr,a");
10923 emitcode ("inc", "dptr");
10924 emitcode ("inc", "dptr");
10925 emitcode ("djnz","b,!tlabel",lbl->key+100);
10927 symbol *lbl1 = newiTempLabel(NULL);
10929 emitcode (";"," Auto increment but no djnz");
10930 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10931 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10932 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10933 emitcode ("","!tlabeldef",lbl->key+100);
10935 emitcode ("clr","a");
10936 emitcode ("movc", "a,@a+dptr");
10938 emitcode ("movx", "a,@dptr");
10939 emitcode ("movx", "@dptr,a");
10940 emitcode ("inc", "dptr");
10941 emitcode ("inc", "dptr");
10942 emitcode ("mov","a,b");
10943 emitcode ("orl","a,_ap");
10944 emitcode ("jz","!tlabel",lbl1->key+100);
10945 emitcode ("mov","a,_ap");
10946 emitcode ("add","a,#!constbyte",0xFF);
10947 emitcode ("mov","_ap,a");
10948 emitcode ("mov","a,b");
10949 emitcode ("addc","a,#!constbyte",0xFF);
10950 emitcode ("mov","b,a");
10951 emitcode ("sjmp","!tlabel",lbl->key+100);
10952 emitcode ("","!tlabeldef",lbl1->key+100);
10954 emitcode ("mov", "dps,#0");
10955 freeAsmop (count, NULL, ic, FALSE);
10956 unsavermask(rsave);
10960 /*-----------------------------------------------------------------*/
10961 /* genMemsetX - gencode for memSetX data */
10962 /*-----------------------------------------------------------------*/
10963 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10965 operand *to , *val , *count;
10969 bitVect *rsave = NULL;
10971 /* we know it has to be 3 parameters */
10972 assert (nparms == 3);
10978 /* save DPTR if it needs to be saved */
10979 rsave = newBitVect(16);
10980 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10981 if (bitVectBitValue(ic->rMask,i))
10982 rsave = bitVectSetBit(rsave,i);
10984 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10985 ds390_rUmaskForOp (IC_RESULT(ic))));
10988 aopOp (to, ic, FALSE, FALSE);
10989 /* get "to" into DPTR */
10990 /* if the operand is already in dptr
10991 then we do nothing else we move the value to dptr */
10992 if (AOP_TYPE (to) != AOP_STR) {
10993 /* if already in DPTR then we need to push */
10994 if (AOP_TYPE(to) == AOP_DPTR) {
10995 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10996 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10997 if (options.model == MODEL_FLAT24)
10998 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10999 emitcode ("pop", "dph");
11000 emitcode ("pop", "dpl");
11002 _startLazyDPSEvaluation ();
11003 /* if this is remateriazable */
11004 if (AOP_TYPE (to) == AOP_IMMD) {
11005 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11006 } else { /* we need to get it byte by byte */
11007 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11008 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11009 if (options.model == MODEL_FLAT24) {
11010 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11013 _endLazyDPSEvaluation ();
11016 freeAsmop (to, NULL, ic, FALSE);
11018 aopOp (val, ic->next->next, FALSE,FALSE);
11019 aopOp (count, ic->next->next, FALSE,FALSE);
11020 lbl =newiTempLabel(NULL);
11021 /* now for the actual copy */
11022 if (AOP_TYPE(count) == AOP_LIT &&
11023 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11024 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11025 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11027 emitcode ("","!tlabeldef",lbl->key+100);
11028 emitcode ("movx", "@dptr,a");
11029 emitcode ("inc", "dptr");
11030 emitcode ("djnz","b,!tlabel",lbl->key+100);
11032 symbol *lbl1 = newiTempLabel(NULL);
11034 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11035 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11036 emitcode ("","!tlabeldef",lbl->key+100);
11037 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11039 emitcode ("movx", "a,@dptr");
11040 emitcode ("inc", "dptr");
11041 emitcode ("mov","a,b");
11042 emitcode ("orl","a,_ap");
11043 emitcode ("jz","!tlabel",lbl1->key+100);
11044 emitcode ("mov","a,_ap");
11045 emitcode ("add","a,#!constbyte",0xFF);
11046 emitcode ("mov","_ap,a");
11047 emitcode ("mov","a,b");
11048 emitcode ("addc","a,#!constbyte",0xFF);
11049 emitcode ("mov","b,a");
11050 emitcode ("sjmp","!tlabel",lbl->key+100);
11051 emitcode ("","!tlabeldef",lbl1->key+100);
11053 freeAsmop (count, NULL, ic, FALSE);
11054 unsavermask(rsave);
11057 /*-----------------------------------------------------------------*/
11058 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11059 /*-----------------------------------------------------------------*/
11060 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11063 operand *pnum, *result;
11066 assert (nparms==1);
11067 /* save registers that need to be saved */
11068 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11069 ds390_rUmaskForOp (IC_RESULT(ic))));
11072 aopOp (pnum, ic, FALSE, FALSE);
11073 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11074 freeAsmop (pnum, NULL, ic, FALSE);
11075 emitcode ("lcall","NatLib_LoadPrimitive");
11076 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11077 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11078 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11079 for (i = (size-1) ; i >= 0 ; i-- ) {
11080 emitcode ("push","a%s",javaRet[i]);
11082 for (i=0; i < size ; i++ ) {
11083 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11086 for (i = 0 ; i < size ; i++ ) {
11087 aopPut(AOP(result),javaRet[i],i);
11090 freeAsmop (result, NULL, ic, FALSE);
11091 unsavermask(rsave);
11094 /*-----------------------------------------------------------------*/
11095 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11096 /*-----------------------------------------------------------------*/
11097 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11100 operand *pnum, *result;
11104 assert (nparms==1);
11105 /* save registers that need to be saved */
11106 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11107 ds390_rUmaskForOp (IC_RESULT(ic))));
11110 aopOp (pnum, ic, FALSE, FALSE);
11111 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11112 freeAsmop (pnum, NULL, ic, FALSE);
11113 emitcode ("lcall","NatLib_LoadPointer");
11114 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11115 if (AOP_TYPE(result)!=AOP_STR) {
11116 for (i = 0 ; i < size ; i++ ) {
11117 aopPut(AOP(result),fReturn[i],i);
11120 freeAsmop (result, NULL, ic, FALSE);
11121 unsavermask(rsave);
11124 /*-----------------------------------------------------------------*/
11125 /* genNatLibInstallStateBlock - */
11126 /*-----------------------------------------------------------------*/
11127 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11128 operand **parms, const char *name)
11131 operand *psb, *handle;
11132 assert (nparms==2);
11134 /* save registers that need to be saved */
11135 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11136 ds390_rUmaskForOp (IC_RESULT(ic))));
11140 /* put pointer to state block into DPTR1 */
11141 aopOp (psb, ic, FALSE, FALSE);
11142 if (AOP_TYPE (psb) == AOP_IMMD) {
11143 emitcode ("mov","dps,#1");
11144 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11145 emitcode ("mov","dps,#0");
11147 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11148 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11149 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11151 freeAsmop (psb, NULL, ic, FALSE);
11153 /* put libraryID into DPTR */
11154 emitcode ("mov","dptr,#LibraryID");
11156 /* put handle into r3:r2 */
11157 aopOp (handle, ic, FALSE, FALSE);
11158 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11159 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11160 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11161 emitcode ("pop","ar3");
11162 emitcode ("pop","ar2");
11164 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11165 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11167 freeAsmop (psb, NULL, ic, FALSE);
11169 /* make the call */
11170 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11172 /* put return value into place*/
11174 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11176 aopPut(AOP(IC_RESULT(ic)),"a",0);
11177 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11178 unsavermask(rsave);
11181 /*-----------------------------------------------------------------*/
11182 /* genNatLibRemoveStateBlock - */
11183 /*-----------------------------------------------------------------*/
11184 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11190 /* save registers that need to be saved */
11191 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11192 ds390_rUmaskForOp (IC_RESULT(ic))));
11194 /* put libraryID into DPTR */
11195 emitcode ("mov","dptr,#LibraryID");
11196 /* make the call */
11197 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11198 unsavermask(rsave);
11201 /*-----------------------------------------------------------------*/
11202 /* genNatLibGetStateBlock - */
11203 /*-----------------------------------------------------------------*/
11204 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11205 operand **parms,const char *name)
11208 symbol *lbl = newiTempLabel(NULL);
11211 /* save registers that need to be saved */
11212 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11213 ds390_rUmaskForOp (IC_RESULT(ic))));
11215 /* put libraryID into DPTR */
11216 emitcode ("mov","dptr,#LibraryID");
11217 /* make the call */
11218 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11219 emitcode ("jnz","!tlabel",lbl->key+100);
11221 /* put return value into place */
11222 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11223 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11224 emitcode ("push","ar3");
11225 emitcode ("push","ar2");
11226 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11227 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11229 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11230 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11232 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11233 emitcode ("","!tlabeldef",lbl->key+100);
11234 unsavermask(rsave);
11237 /*-----------------------------------------------------------------*/
11238 /* genMMMalloc - */
11239 /*-----------------------------------------------------------------*/
11240 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11241 int size, const char *name)
11246 symbol *lbl = newiTempLabel(NULL);
11248 assert (nparms == 1);
11249 /* save registers that need to be saved */
11250 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11251 ds390_rUmaskForOp (IC_RESULT(ic))));
11254 aopOp (bsize,ic,FALSE,FALSE);
11256 /* put the size in R4-R2 */
11257 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11258 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11259 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11261 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11262 emitcode("pop","ar4");
11264 emitcode("pop","ar3");
11265 emitcode("pop","ar2");
11267 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11268 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11270 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11273 freeAsmop (bsize, NULL, ic, FALSE);
11275 /* make the call */
11276 emitcode ("lcall","MM_%s",name);
11277 emitcode ("jz","!tlabel",lbl->key+100);
11278 emitcode ("mov","r2,#!constbyte",0xff);
11279 emitcode ("mov","r3,#!constbyte",0xff);
11280 emitcode ("","!tlabeldef",lbl->key+100);
11281 /* we don't care about the pointer : we just save the handle */
11282 rsym = OP_SYMBOL(IC_RESULT(ic));
11283 if (rsym->liveFrom != rsym->liveTo) {
11284 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11285 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11286 emitcode ("push","ar3");
11287 emitcode ("push","ar2");
11288 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11289 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11291 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11292 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11294 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11296 unsavermask(rsave);
11299 /*-----------------------------------------------------------------*/
11301 /*-----------------------------------------------------------------*/
11302 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11307 assert (nparms == 1);
11308 /* save registers that need to be saved */
11309 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11310 ds390_rUmaskForOp (IC_RESULT(ic))));
11313 aopOp (handle,ic,FALSE,FALSE);
11315 /* put the size in R4-R2 */
11316 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11317 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11318 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11319 emitcode("pop","ar3");
11320 emitcode("pop","ar2");
11322 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11323 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11325 freeAsmop (handle, NULL, ic, FALSE);
11327 /* make the call */
11328 emitcode ("lcall","MM_Deref");
11331 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11332 if (rsym->liveFrom != rsym->liveTo) {
11333 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11334 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11335 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11336 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11337 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11341 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11342 unsavermask(rsave);
11345 /*-----------------------------------------------------------------*/
11346 /* genMMUnrestrictedPersist - */
11347 /*-----------------------------------------------------------------*/
11348 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11353 assert (nparms == 1);
11354 /* save registers that need to be saved */
11355 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11356 ds390_rUmaskForOp (IC_RESULT(ic))));
11359 aopOp (handle,ic,FALSE,FALSE);
11361 /* put the size in R3-R2 */
11362 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11363 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11364 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11365 emitcode("pop","ar3");
11366 emitcode("pop","ar2");
11368 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11369 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11371 freeAsmop (handle, NULL, ic, FALSE);
11373 /* make the call */
11374 emitcode ("lcall","MM_UnrestrictedPersist");
11377 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11378 if (rsym->liveFrom != rsym->liveTo) {
11379 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11380 aopPut(AOP(IC_RESULT(ic)),"a",0);
11381 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11384 unsavermask(rsave);
11387 /*-----------------------------------------------------------------*/
11388 /* genSystemExecJavaProcess - */
11389 /*-----------------------------------------------------------------*/
11390 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11393 operand *handle, *pp;
11395 assert (nparms==2);
11396 /* save registers that need to be saved */
11397 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11398 ds390_rUmaskForOp (IC_RESULT(ic))));
11403 /* put the handle in R3-R2 */
11404 aopOp (handle,ic,FALSE,FALSE);
11405 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11406 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11407 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11408 emitcode("pop","ar3");
11409 emitcode("pop","ar2");
11411 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11412 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11414 freeAsmop (handle, NULL, ic, FALSE);
11416 /* put pointer in DPTR */
11417 aopOp (pp,ic,FALSE,FALSE);
11418 if (AOP_TYPE(pp) == AOP_IMMD) {
11419 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11420 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11421 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11422 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11423 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11425 freeAsmop (handle, NULL, ic, FALSE);
11427 /* make the call */
11428 emitcode ("lcall","System_ExecJavaProcess");
11430 /* put result in place */
11432 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11433 if (rsym->liveFrom != rsym->liveTo) {
11434 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11435 aopPut(AOP(IC_RESULT(ic)),"a",0);
11436 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11440 unsavermask(rsave);
11443 /*-----------------------------------------------------------------*/
11444 /* genSystemRTCRegisters - */
11445 /*-----------------------------------------------------------------*/
11446 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11452 assert (nparms==1);
11453 /* save registers that need to be saved */
11454 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11455 ds390_rUmaskForOp (IC_RESULT(ic))));
11458 /* put pointer in DPTR */
11459 aopOp (pp,ic,FALSE,FALSE);
11460 if (AOP_TYPE (pp) == AOP_IMMD) {
11461 emitcode ("mov","dps,#1");
11462 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11463 emitcode ("mov","dps,#0");
11465 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11466 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11467 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11469 freeAsmop (pp, NULL, ic, FALSE);
11471 /* make the call */
11472 emitcode ("lcall","System_%sRTCRegisters",name);
11474 unsavermask(rsave);
11477 /*-----------------------------------------------------------------*/
11478 /* genSystemThreadSleep - */
11479 /*-----------------------------------------------------------------*/
11480 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11485 assert (nparms==1);
11486 /* save registers that need to be saved */
11487 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11488 ds390_rUmaskForOp (IC_RESULT(ic))));
11491 aopOp(to,ic,FALSE,FALSE);
11492 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11493 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11494 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11495 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11496 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11497 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11498 emitcode ("pop","ar3");
11499 emitcode ("pop","ar2");
11500 emitcode ("pop","ar1");
11501 emitcode ("pop","ar0");
11503 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11504 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11505 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11506 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11508 freeAsmop (to, NULL, ic, FALSE);
11510 /* suspend in acc */
11512 aopOp(s,ic,FALSE,FALSE);
11513 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11514 freeAsmop (s, NULL, ic, FALSE);
11516 /* make the call */
11517 emitcode ("lcall","System_%s",name);
11519 unsavermask(rsave);
11522 /*-----------------------------------------------------------------*/
11523 /* genSystemThreadResume - */
11524 /*-----------------------------------------------------------------*/
11525 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11530 assert (nparms==2);
11531 /* save registers that need to be saved */
11532 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11533 ds390_rUmaskForOp (IC_RESULT(ic))));
11539 aopOp(pid,ic,FALSE,FALSE);
11540 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11541 freeAsmop (pid, NULL, ic, FALSE);
11544 aopOp(tid,ic,FALSE,FALSE);
11545 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11546 freeAsmop (tid, NULL, ic, FALSE);
11548 emitcode ("lcall","System_ThreadResume");
11550 /* put result into place */
11552 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11553 if (rsym->liveFrom != rsym->liveTo) {
11554 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11555 aopPut(AOP(IC_RESULT(ic)),"a",0);
11556 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11559 unsavermask(rsave);
11562 /*-----------------------------------------------------------------*/
11563 /* genSystemProcessResume - */
11564 /*-----------------------------------------------------------------*/
11565 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11570 assert (nparms==1);
11571 /* save registers that need to be saved */
11572 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11573 ds390_rUmaskForOp (IC_RESULT(ic))));
11578 aopOp(pid,ic,FALSE,FALSE);
11579 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11580 freeAsmop (pid, NULL, ic, FALSE);
11582 emitcode ("lcall","System_ProcessResume");
11584 unsavermask(rsave);
11587 /*-----------------------------------------------------------------*/
11589 /*-----------------------------------------------------------------*/
11590 static void genSystem (iCode *ic,int nparms,char *name)
11592 assert(nparms == 0);
11594 emitcode ("lcall","System_%s",name);
11597 /*-----------------------------------------------------------------*/
11598 /* genSystemPoll - */
11599 /*-----------------------------------------------------------------*/
11600 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11605 assert (nparms==1);
11606 /* save registers that need to be saved */
11607 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11608 ds390_rUmaskForOp (IC_RESULT(ic))));
11611 aopOp (fp,ic,FALSE,FALSE);
11612 if (AOP_TYPE (fp) == AOP_IMMD) {
11613 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11614 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11615 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11616 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11617 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11619 freeAsmop (fp, NULL, ic, FALSE);
11621 emitcode ("lcall","System_%sPoll",name);
11623 /* put result into place */
11625 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11626 if (rsym->liveFrom != rsym->liveTo) {
11627 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11628 aopPut(AOP(IC_RESULT(ic)),"a",0);
11629 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11632 unsavermask(rsave);
11635 /*-----------------------------------------------------------------*/
11636 /* genSystemGetCurrentID - */
11637 /*-----------------------------------------------------------------*/
11638 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11640 assert (nparms==0);
11642 emitcode ("lcall","System_GetCurrent%sId",name);
11643 /* put result into place */
11645 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11646 if (rsym->liveFrom != rsym->liveTo) {
11647 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11648 aopPut(AOP(IC_RESULT(ic)),"a",0);
11649 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11654 /*-----------------------------------------------------------------*/
11655 /* genBuiltIn - calls the appropriate function to generating code */
11656 /* for a built in function */
11657 /*-----------------------------------------------------------------*/
11658 static void genBuiltIn (iCode *ic)
11660 operand *bi_parms[MAX_BUILTIN_ARGS];
11665 /* get all the arguments for a built in function */
11666 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11668 /* which function is it */
11669 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11670 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11671 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11672 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11673 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11674 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11675 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11676 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11677 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11678 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11679 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11680 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11681 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11682 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11683 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11684 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11685 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11686 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11687 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11688 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11689 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11690 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11691 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11692 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11693 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11694 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11695 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11696 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11697 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11698 } else if (strcmp(bif->name,"MM_Malloc")==0) {
11699 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11700 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11701 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11702 } else if (strcmp(bif->name,"MM_Free")==0) {
11703 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11704 } else if (strcmp(bif->name,"MM_Deref")==0) {
11705 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11706 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11707 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11708 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11709 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11710 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11711 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11712 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11713 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11714 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11715 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11716 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11717 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11718 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11719 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11720 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11721 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11722 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11723 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11724 } else if (strcmp(bif->name,"System_SaveThread")==0) {
11725 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11726 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11727 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11728 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11729 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11730 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11731 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11732 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11733 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11734 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11735 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11736 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11737 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11738 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11739 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11740 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11741 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11742 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11743 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11744 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11745 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11747 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11753 /*-----------------------------------------------------------------*/
11754 /* gen390Code - generate code for Dallas 390 based controllers */
11755 /*-----------------------------------------------------------------*/
11757 gen390Code (iCode * lic)
11762 lineHead = lineCurr = NULL;
11764 if (options.model == MODEL_FLAT24) {
11765 fReturnSizeDS390 = 5;
11766 fReturn = fReturn24;
11768 fReturnSizeDS390 = 4;
11769 fReturn = fReturn16;
11770 options.stack10bit=0;
11774 /* print the allocation information */
11776 printAllocInfo (currFunc, codeOutFile);
11778 /* if debug information required */
11779 if (options.debug && currFunc)
11781 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11783 if (IS_STATIC (currFunc->etype))
11784 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11786 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11789 /* stack pointer name */
11790 if (options.useXstack)
11796 for (ic = lic; ic; ic = ic->next)
11799 if (cln != ic->lineno)
11804 emitcode ("", "C$%s$%d$%d$%d ==.",
11805 FileBaseName (ic->filename), ic->lineno,
11806 ic->level, ic->block);
11809 emitcode (";", "%s %d", ic->filename, ic->lineno);
11812 /* if the result is marked as
11813 spilt and rematerializable or code for
11814 this has already been generated then
11816 if (resultRemat (ic) || ic->generated)
11819 /* depending on the operation */
11839 /* IPOP happens only when trying to restore a
11840 spilt live range, if there is an ifx statement
11841 following this pop then the if statement might
11842 be using some of the registers being popped which
11843 would destory the contents of the register so
11844 we need to check for this condition and handle it */
11846 ic->next->op == IFX &&
11847 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11848 genIfx (ic->next, ic);
11866 genEndFunction (ic);
11886 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11903 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11907 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11914 /* note these two are xlated by algebraic equivalence
11915 during parsing SDCC.y */
11916 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11917 "got '>=' or '<=' shouldn't have come here");
11921 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11933 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11937 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11941 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11965 genRightShift (ic);
11968 case GET_VALUE_AT_ADDRESS:
11969 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11973 if (POINTER_SET (ic))
11974 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
12000 if (ic->builtinSEND) genBuiltIn(ic);
12001 else addSet (&_G.sendSet, ic);
12014 /* now we are ready to call the
12015 peep hole optimizer */
12016 if (!options.nopeep)
12017 peepHole (&lineHead);
12019 /* now do the actual printing */
12020 printLine (lineHead, codeOutFile);