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[] =
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 /* regsInCommon - two operands have some registers in common */
612 /*-----------------------------------------------------------------*/
614 regsInCommon (operand * op1, operand * op2)
619 /* if they have registers in common */
620 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
623 sym1 = OP_SYMBOL (op1);
624 sym2 = OP_SYMBOL (op2);
626 if (sym1->nRegs == 0 || sym2->nRegs == 0)
629 for (i = 0; i < sym1->nRegs; i++)
635 for (j = 0; j < sym2->nRegs; j++)
640 if (sym2->regs[j] == sym1->regs[i])
648 /*-----------------------------------------------------------------*/
649 /* operandsEqu - equivalent */
650 /*-----------------------------------------------------------------*/
652 operandsEqu (operand * op1, operand * op2)
656 /* if they not symbols */
657 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
660 sym1 = OP_SYMBOL (op1);
661 sym2 = OP_SYMBOL (op2);
663 /* if both are itemps & one is spilt
664 and the other is not then false */
665 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
666 sym1->isspilt != sym2->isspilt)
669 /* if they are the same */
673 if (strcmp (sym1->rname, sym2->rname) == 0)
677 /* if left is a tmp & right is not */
678 if (IS_ITEMP (op1) &&
681 (sym1->usl.spillLoc == sym2))
684 if (IS_ITEMP (op2) &&
688 (sym2->usl.spillLoc == sym1))
694 /*-----------------------------------------------------------------*/
695 /* sameRegs - two asmops have the same registers */
696 /*-----------------------------------------------------------------*/
698 sameRegs (asmop * aop1, asmop * aop2)
704 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
711 if (aop1->type != AOP_REG ||
712 aop2->type != AOP_REG)
715 if (aop1->size != aop2->size)
718 for (i = 0; i < aop1->size; i++)
719 if (aop1->aopu.aop_reg[i] !=
720 aop2->aopu.aop_reg[i])
726 /*-----------------------------------------------------------------*/
727 /* aopOp - allocates an asmop for an operand : */
728 /*-----------------------------------------------------------------*/
730 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
739 /* if this a literal */
740 if (IS_OP_LITERAL (op))
742 op->aop = aop = newAsmop (AOP_LIT);
743 aop->aopu.aop_lit = op->operand.valOperand;
744 aop->size = getSize (operandType (op));
748 /* if already has a asmop then continue */
752 /* if the underlying symbol has a aop */
753 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
755 op->aop = OP_SYMBOL (op)->aop;
759 /* if this is a true symbol */
760 if (IS_TRUE_SYMOP (op))
762 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
766 /* this is a temporary : this has
772 e) can be a return use only */
774 sym = OP_SYMBOL (op);
777 /* if the type is a conditional */
778 if (sym->regType == REG_CND)
780 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
785 /* if it is spilt then two situations
787 b) has a spill location */
788 if (sym->isspilt || sym->nRegs == 0)
791 /* rematerialize it NOW */
794 sym->aop = op->aop = aop =
796 aop->size = getSize (sym->type);
803 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
804 aop->size = getSize (sym->type);
805 for (i = 0; i < 2; i++)
806 aop->aopu.aop_str[i] = accUse[i];
816 /* a AOP_STR uses DPTR, but DPTR is already in use;
819 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
822 aop = op->aop = sym->aop = newAsmop (AOP_STR);
823 aop->size = getSize (sym->type);
824 for (i = 0; i < (int) fReturnSizeDS390; i++)
825 aop->aopu.aop_str[i] = fReturn[i];
829 /* else spill location */
830 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
831 /* force a new aop if sizes differ */
832 sym->usl.spillLoc->aop = NULL;
834 sym->aop = op->aop = aop =
835 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
836 aop->size = getSize (sym->type);
840 /* must be in a register */
841 sym->aop = op->aop = aop = newAsmop (AOP_REG);
842 aop->size = sym->nRegs;
843 for (i = 0; i < sym->nRegs; i++)
844 aop->aopu.aop_reg[i] = sym->regs[i];
847 /*-----------------------------------------------------------------*/
848 /* freeAsmop - free up the asmop given to an operand */
849 /*----------------------------------------------------------------*/
851 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
868 /* depending on the asmop type only three cases need work AOP_RO
869 , AOP_R1 && AOP_STK */
877 emitcode ("pop", "ar0");
881 bitVectUnSetBit (ic->rUsed, R0_IDX);
889 emitcode ("pop", "ar1");
893 bitVectUnSetBit (ic->rUsed, R1_IDX);
899 int stk = aop->aopu.aop_stk + aop->size;
900 bitVectUnSetBit (ic->rUsed, R0_IDX);
901 bitVectUnSetBit (ic->rUsed, R1_IDX);
903 getFreePtr (ic, &aop, FALSE);
905 if (options.stack10bit)
907 /* I'm not sure what to do here yet... */
910 "*** Warning: probably generating bad code for "
911 "10 bit stack mode.\n");
916 emitcode ("mov", "a,_bp");
917 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
918 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
922 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
927 emitcode ("pop", "acc");
928 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
931 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
934 freeAsmop (op, NULL, ic, TRUE);
937 emitcode ("pop", "ar0");
943 emitcode ("pop", "ar1");
950 /* all other cases just dealloc */
956 OP_SYMBOL (op)->aop = NULL;
957 /* if the symbol has a spill */
959 SPIL_LOC (op)->aop = NULL;
964 /*------------------------------------------------------------------*/
965 /* aopGet - for fetching value of the aop */
967 /* Set canClobberACC if you are sure it is OK to clobber the value */
968 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
969 /* just less efficient. */
970 /*------------------------------------------------------------------*/
982 /* offset is greater than
984 if (offset > (aop->size - 1) &&
985 aop->type != AOP_LIT)
988 /* depending on type */
994 /* if we need to increment it */
995 while (offset > aop->coff)
997 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1001 while (offset < aop->coff)
1003 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1010 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1011 return (dname ? "acc" : "a");
1013 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1014 rs = Safe_calloc (1, strlen (s) + 1);
1021 if (aop->type == AOP_DPTR2)
1027 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1033 while (offset > aop->coff)
1035 emitcode ("inc", "dptr");
1039 while (offset < aop->coff)
1041 emitcode ("lcall", "__decdptr");
1048 emitcode ("clr", "a");
1049 emitcode ("movc", "a,@a+dptr");
1053 emitcode ("movx", "a,@dptr");
1056 if (aop->type == AOP_DPTR2)
1062 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1063 return DP2_RESULT_REG;
1066 return (dname ? "acc" : "a");
1069 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1070 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1072 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1076 tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1079 tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1082 tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1084 default: /* should not need this (just in case) */
1085 sprintf (s, "#(%s >> %d)",
1086 aop->aopu.aop_immd.aop_immd1,
1092 aop->aopu.aop_immd.aop_immd1);
1093 rs = Safe_calloc (1, strlen (s) + 1);
1099 sprintf (s, "(%s + %d)",
1103 sprintf (s, "%s", aop->aopu.aop_dir);
1104 rs = Safe_calloc (1, strlen (s) + 1);
1110 return aop->aopu.aop_reg[offset]->dname;
1112 return aop->aopu.aop_reg[offset]->name;
1115 emitcode ("clr", "a");
1116 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1117 emitcode ("rlc", "a");
1118 return (dname ? "acc" : "a");
1121 if (!offset && dname)
1123 return aop->aopu.aop_str[offset];
1126 return aopLiteral (aop->aopu.aop_lit, offset);
1130 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1134 return aop->aopu.aop_str[offset];
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopget got unsupported aop->type");
1142 /*-----------------------------------------------------------------*/
1143 /* aopPut - puts a string for a aop */
1144 /*-----------------------------------------------------------------*/
1146 aopPut (asmop * aop, char *s, int offset)
1150 if (aop->size && offset > (aop->size - 1))
1152 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1153 "aopPut got offset > aop->size");
1157 /* will assign value to value */
1158 /* depending on where it is ofcourse */
1163 sprintf (d, "(%s + %d)",
1164 aop->aopu.aop_dir, offset);
1166 sprintf (d, "%s", aop->aopu.aop_dir);
1169 emitcode ("mov", "%s,%s", d, s);
1174 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1175 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1178 strcmp (s, "r0") == 0 ||
1179 strcmp (s, "r1") == 0 ||
1180 strcmp (s, "r2") == 0 ||
1181 strcmp (s, "r3") == 0 ||
1182 strcmp (s, "r4") == 0 ||
1183 strcmp (s, "r5") == 0 ||
1184 strcmp (s, "r6") == 0 ||
1185 strcmp (s, "r7") == 0)
1186 emitcode ("mov", "%s,%s",
1187 aop->aopu.aop_reg[offset]->dname, s);
1189 emitcode ("mov", "%s,%s",
1190 aop->aopu.aop_reg[offset]->name, s);
1197 if (aop->type == AOP_DPTR2)
1205 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1206 "aopPut writting to code space");
1210 while (offset > aop->coff)
1213 emitcode ("inc", "dptr");
1216 while (offset < aop->coff)
1219 emitcode ("lcall", "__decdptr");
1224 /* if not in accumulater */
1227 emitcode ("movx", "@dptr,a");
1229 if (aop->type == AOP_DPTR2)
1237 while (offset > aop->coff)
1240 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1242 while (offset < aop->coff)
1245 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1252 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1258 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1260 else if (strcmp (s, "r0") == 0 ||
1261 strcmp (s, "r1") == 0 ||
1262 strcmp (s, "r2") == 0 ||
1263 strcmp (s, "r3") == 0 ||
1264 strcmp (s, "r4") == 0 ||
1265 strcmp (s, "r5") == 0 ||
1266 strcmp (s, "r6") == 0 ||
1267 strcmp (s, "r7") == 0)
1270 sprintf (buffer, "a%s", s);
1271 emitcode ("mov", "@%s,%s",
1272 aop->aopu.aop_ptr->name, buffer);
1275 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1280 if (strcmp (s, "a") == 0)
1281 emitcode ("push", "acc");
1285 emitcode ("push", "acc");
1287 emitcode ("push", s);
1293 /* if bit variable */
1294 if (!aop->aopu.aop_dir)
1296 emitcode ("clr", "a");
1297 emitcode ("rlc", "a");
1302 emitcode ("clr", "%s", aop->aopu.aop_dir);
1304 emitcode ("setb", "%s", aop->aopu.aop_dir);
1305 else if (!strcmp (s, "c"))
1306 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1309 if (strcmp (s, "a"))
1314 symbol *lbl = newiTempLabel (NULL);
1315 emitcode ("clr", "c");
1316 emitcode ("jz", "!tlabel", lbl->key + 100);
1317 emitcode ("cpl", "c");
1318 emitcode ("", "!tlabeldef", lbl->key + 100);
1319 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1327 if (strcmp (aop->aopu.aop_str[offset], s))
1328 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1333 if (!offset && (strcmp (s, "acc") == 0))
1336 if (strcmp (aop->aopu.aop_str[offset], s))
1337 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1341 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1342 "aopPut got unsupported aop->type");
1349 /*--------------------------------------------------------------------*/
1350 /* reAdjustPreg - points a register back to where it should (coff==0) */
1351 /*--------------------------------------------------------------------*/
1353 reAdjustPreg (asmop * aop)
1355 if ((aop->coff==0) || (aop->size <= 1)) {
1364 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1368 if (aop->type == AOP_DPTR2)
1375 emitcode ("lcall", "__decdptr");
1378 if (aop->type == AOP_DPTR2)
1388 #define AOP(op) op->aop
1389 #define AOP_TYPE(op) AOP(op)->type
1390 #define AOP_SIZE(op) AOP(op)->size
1391 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1392 AOP_TYPE(x) == AOP_R0))
1394 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1395 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1398 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1399 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1400 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1402 /* Workaround for DS80C390 bug: div ab may return bogus results
1403 * if A is accessed in instruction immediately before the div.
1405 * Will be fixed in B4 rev of processor, Dallas claims.
1408 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1409 if (!AOP_NEEDSACC(RIGHT)) \
1411 /* We can load A first, then B, since \
1412 * B (the RIGHT operand) won't clobber A, \
1413 * thus avoiding touching A right before the div. \
1415 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1416 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1418 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1422 /* Just stuff in a nop after loading A. */ \
1423 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1424 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1426 emitcode("nop", "; workaround for DS80C390 div bug."); \
1429 /*-----------------------------------------------------------------*/
1430 /* genNotFloat - generates not for float operations */
1431 /*-----------------------------------------------------------------*/
1433 genNotFloat (operand * op, operand * res)
1439 D (emitcode (";", "genNotFloat ");
1442 /* we will put 127 in the first byte of
1444 aopPut (AOP (res), "#127", 0);
1445 size = AOP_SIZE (op) - 1;
1448 _startLazyDPSEvaluation ();
1449 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1454 emitcode ("orl", "a,%s",
1456 offset++, FALSE, FALSE, FALSE));
1458 _endLazyDPSEvaluation ();
1460 tlbl = newiTempLabel (NULL);
1461 aopPut (res->aop, one, 1);
1462 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1463 aopPut (res->aop, zero, 1);
1464 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1466 size = res->aop->size - 2;
1468 /* put zeros in the rest */
1470 aopPut (res->aop, zero, offset++);
1473 /*-----------------------------------------------------------------*/
1474 /* opIsGptr: returns non-zero if the passed operand is */
1475 /* a generic pointer type. */
1476 /*-----------------------------------------------------------------*/
1478 opIsGptr (operand * op)
1480 sym_link *type = operandType (op);
1482 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1489 /*-----------------------------------------------------------------*/
1490 /* getDataSize - get the operand data size */
1491 /*-----------------------------------------------------------------*/
1493 getDataSize (operand * op)
1496 size = AOP_SIZE (op);
1497 if (size == GPTRSIZE)
1499 sym_link *type = operandType (op);
1500 if (IS_GENPTR (type))
1502 /* generic pointer; arithmetic operations
1503 * should ignore the high byte (pointer type).
1511 /*-----------------------------------------------------------------*/
1512 /* outAcc - output Acc */
1513 /*-----------------------------------------------------------------*/
1515 outAcc (operand * result)
1518 size = getDataSize (result);
1521 aopPut (AOP (result), "a", 0);
1524 /* unsigned or positive */
1527 aopPut (AOP (result), zero, offset++);
1532 /*-----------------------------------------------------------------*/
1533 /* outBitC - output a bit C */
1534 /*-----------------------------------------------------------------*/
1536 outBitC (operand * result)
1538 /* if the result is bit */
1539 if (AOP_TYPE (result) == AOP_CRY)
1541 aopPut (AOP (result), "c", 0);
1545 emitcode ("clr", "a");
1546 emitcode ("rlc", "a");
1551 /*-----------------------------------------------------------------*/
1552 /* toBoolean - emit code for orl a,operator(sizeop) */
1553 /*-----------------------------------------------------------------*/
1555 toBoolean (operand * oper)
1557 int size = AOP_SIZE (oper) - 1;
1561 /* The generic part of a generic pointer should
1562 * not participate in it's truth value.
1564 * i.e. 0x10000000 is zero.
1566 if (opIsGptr (oper))
1568 D (emitcode (";", "toBoolean: generic ptr special case.");
1573 _startLazyDPSEvaluation ();
1574 if (AOP_NEEDSACC (oper) && size)
1577 emitcode ("push", "b");
1578 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1582 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1588 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1592 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1595 _endLazyDPSEvaluation ();
1599 emitcode ("mov", "a,b");
1600 emitcode ("pop", "b");
1605 /*-----------------------------------------------------------------*/
1606 /* genNot - generate code for ! operation */
1607 /*-----------------------------------------------------------------*/
1612 sym_link *optype = operandType (IC_LEFT (ic));
1614 D (emitcode (";", "genNot ");
1617 /* assign asmOps to operand & result */
1618 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1619 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1621 /* if in bit space then a special case */
1622 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1624 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1625 emitcode ("cpl", "c");
1626 outBitC (IC_RESULT (ic));
1630 /* if type float then do float */
1631 if (IS_FLOAT (optype))
1633 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1637 toBoolean (IC_LEFT (ic));
1639 tlbl = newiTempLabel (NULL);
1640 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1641 emitcode ("", "!tlabeldef", tlbl->key + 100);
1642 outBitC (IC_RESULT (ic));
1645 /* release the aops */
1646 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1647 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1651 /*-----------------------------------------------------------------*/
1652 /* genCpl - generate code for complement */
1653 /*-----------------------------------------------------------------*/
1660 D (emitcode (";", "genCpl ");
1664 /* assign asmOps to operand & result */
1665 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1666 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1668 /* if both are in bit space then
1670 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1671 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1674 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1675 emitcode ("cpl", "c");
1676 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1680 size = AOP_SIZE (IC_RESULT (ic));
1681 _startLazyDPSEvaluation ();
1684 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1686 emitcode ("cpl", "a");
1687 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1689 _endLazyDPSEvaluation ();
1693 /* release the aops */
1694 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1698 /*-----------------------------------------------------------------*/
1699 /* genUminusFloat - unary minus for floating points */
1700 /*-----------------------------------------------------------------*/
1702 genUminusFloat (operand * op, operand * result)
1704 int size, offset = 0;
1706 /* for this we just need to flip the
1707 first it then copy the rest in place */
1708 D (emitcode (";", "genUminusFloat");
1711 _startLazyDPSEvaluation ();
1712 size = AOP_SIZE (op) - 1;
1713 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1716 emitcode ("cpl", "acc.7");
1717 aopPut (AOP (result), "a", 3);
1721 aopPut (AOP (result),
1722 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1726 _endLazyDPSEvaluation ();
1729 /*-----------------------------------------------------------------*/
1730 /* genUminus - unary minus code generation */
1731 /*-----------------------------------------------------------------*/
1733 genUminus (iCode * ic)
1736 sym_link *optype, *rtype;
1738 D (emitcode (";", "genUminus ");
1743 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1744 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1746 /* if both in bit space then special
1748 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1749 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1752 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1753 emitcode ("cpl", "c");
1754 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1758 optype = operandType (IC_LEFT (ic));
1759 rtype = operandType (IC_RESULT (ic));
1761 /* if float then do float stuff */
1762 if (IS_FLOAT (optype))
1764 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1768 /* otherwise subtract from zero */
1769 size = AOP_SIZE (IC_LEFT (ic));
1771 _startLazyDPSEvaluation ();
1774 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1775 if (!strcmp (l, "a"))
1779 emitcode ("cpl", "a");
1780 emitcode ("addc", "a,#0");
1786 emitcode ("clr", "a");
1787 emitcode ("subb", "a,%s", l);
1789 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1791 _endLazyDPSEvaluation ();
1793 /* if any remaining bytes in the result */
1794 /* we just need to propagate the sign */
1795 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1797 emitcode ("rlc", "a");
1798 emitcode ("subb", "a,acc");
1800 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1804 /* release the aops */
1805 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1806 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1809 /*-----------------------------------------------------------------*/
1810 /* saveRegisters - will look for a call and save the registers */
1811 /*-----------------------------------------------------------------*/
1813 saveRegisters (iCode * lic)
1821 for (ic = lic; ic; ic = ic->next)
1822 if (ic->op == CALL || ic->op == PCALL)
1827 fprintf (stderr, "found parameter push with no function call\n");
1831 /* if the registers have been saved already then
1833 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1835 /* special case if DPTR alive across a function call then must save it
1836 even though callee saves */
1837 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1839 rsave = newBitVect(ic->rMask->size);
1840 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1841 if (bitVectBitValue(ic->rMask,i))
1842 rsave = bitVectSetBit(rsave,i);
1845 /* safe the registers in use at this time but skip the
1846 ones for the result */
1847 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1848 ds390_rUmaskForOp (IC_RESULT(ic)));
1851 if (options.useXstack)
1853 if (bitVectBitValue (rsave, R0_IDX))
1854 emitcode ("mov", "b,r0");
1855 emitcode ("mov", "r0,%s", spname);
1856 for (i = 0; i < ds390_nRegs; i++)
1858 if (bitVectBitValue (rsave, i))
1861 emitcode ("mov", "a,b");
1863 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1864 emitcode ("movx", "@r0,a");
1865 emitcode ("inc", "r0");
1868 emitcode ("mov", "%s,r0", spname);
1869 if (bitVectBitValue (rsave, R0_IDX))
1870 emitcode ("mov", "r0,b");
1873 for (i = 0; i < ds390_nRegs; i++)
1875 if (bitVectBitValue (rsave, i))
1876 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1879 detype = getSpec (operandType (IC_LEFT (ic)));
1882 /*-----------------------------------------------------------------*/
1883 /* unsaveRegisters - pop the pushed registers */
1884 /*-----------------------------------------------------------------*/
1886 unsaveRegisters (iCode * ic)
1891 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1893 rsave = newBitVect(ic->rMask->size);
1894 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1895 if (bitVectBitValue(ic->rMask,i))
1896 rsave = bitVectSetBit(rsave,i);
1899 /* restore the registers in use at this time but skip the
1900 ones for the result */
1901 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1902 ds390_rUmaskForOp (IC_RESULT(ic)));
1904 if (options.useXstack)
1906 emitcode ("mov", "r0,%s", spname);
1907 for (i = ds390_nRegs; i >= 0; i--)
1909 if (bitVectBitValue (rsave, i))
1911 emitcode ("dec", "r0");
1912 emitcode ("movx", "a,@r0");
1914 emitcode ("mov", "b,a");
1916 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1920 emitcode ("mov", "%s,r0", spname);
1921 if (bitVectBitValue (rsave, R0_IDX))
1922 emitcode ("mov", "r0,b");
1925 for (i = ds390_nRegs; i >= 0; i--)
1927 if (bitVectBitValue (rsave, i))
1928 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1934 /*-----------------------------------------------------------------*/
1936 /*-----------------------------------------------------------------*/
1938 pushSide (operand * oper, int size)
1941 _startLazyDPSEvaluation ();
1944 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1945 if (AOP_TYPE (oper) != AOP_REG &&
1946 AOP_TYPE (oper) != AOP_DIR &&
1949 emitcode ("mov", "a,%s", l);
1950 emitcode ("push", "acc");
1953 emitcode ("push", "%s", l);
1955 _endLazyDPSEvaluation ();
1958 /*-----------------------------------------------------------------*/
1959 /* assignResultValue - */
1960 /*-----------------------------------------------------------------*/
1962 assignResultValue (operand * oper)
1965 int size = AOP_SIZE (oper);
1967 _startLazyDPSEvaluation ();
1970 aopPut (AOP (oper), fReturn[offset], offset);
1973 _endLazyDPSEvaluation ();
1977 /*-----------------------------------------------------------------*/
1978 /* genXpush - pushes onto the external stack */
1979 /*-----------------------------------------------------------------*/
1981 genXpush (iCode * ic)
1983 asmop *aop = newAsmop (0);
1985 int size, offset = 0;
1987 D (emitcode (";", "genXpush ");
1990 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1991 r = getFreePtr (ic, &aop, FALSE);
1994 emitcode ("mov", "%s,_spx", r->name);
1996 size = AOP_SIZE (IC_LEFT (ic));
1997 _startLazyDPSEvaluation ();
2001 char *l = aopGet (AOP (IC_LEFT (ic)),
2002 offset++, FALSE, FALSE, TRUE);
2004 emitcode ("movx", "@%s,a", r->name);
2005 emitcode ("inc", "%s", r->name);
2008 _endLazyDPSEvaluation ();
2011 emitcode ("mov", "_spx,%s", r->name);
2013 freeAsmop (NULL, aop, ic, TRUE);
2014 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2017 /*-----------------------------------------------------------------*/
2018 /* genIpush - genrate code for pushing this gets a little complex */
2019 /*-----------------------------------------------------------------*/
2021 genIpush (iCode * ic)
2023 int size, offset = 0;
2026 D (emitcode (";", "genIpush ");
2029 /* if this is not a parm push : ie. it is spill push
2030 and spill push is always done on the local stack */
2034 /* and the item is spilt then do nothing */
2035 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2038 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2039 size = AOP_SIZE (IC_LEFT (ic));
2040 /* push it on the stack */
2041 _startLazyDPSEvaluation ();
2044 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2050 emitcode ("push", "%s", l);
2052 _endLazyDPSEvaluation ();
2056 /* this is a paramter push: in this case we call
2057 the routine to find the call and save those
2058 registers that need to be saved */
2061 /* if use external stack then call the external
2062 stack pushing routine */
2063 if (options.useXstack)
2069 /* then do the push */
2070 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2072 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2073 size = AOP_SIZE (IC_LEFT (ic));
2075 _startLazyDPSEvaluation ();
2078 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2079 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2080 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2083 emitcode ("mov", "a,%s", l);
2084 emitcode ("push", "acc");
2087 emitcode ("push", "%s", l);
2089 _endLazyDPSEvaluation ();
2091 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2094 /*-----------------------------------------------------------------*/
2095 /* genIpop - recover the registers: can happen only for spilling */
2096 /*-----------------------------------------------------------------*/
2098 genIpop (iCode * ic)
2102 D (emitcode (";", "genIpop ");
2106 /* if the temp was not pushed then */
2107 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2110 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2111 size = AOP_SIZE (IC_LEFT (ic));
2112 offset = (size - 1);
2113 _startLazyDPSEvaluation ();
2116 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2117 FALSE, TRUE, TRUE));
2119 _endLazyDPSEvaluation ();
2121 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2124 /*-----------------------------------------------------------------*/
2125 /* unsaveRBank - restores the resgister bank from stack */
2126 /*-----------------------------------------------------------------*/
2128 unsaveRBank (int bank, iCode * ic, bool popPsw)
2134 if (options.useXstack)
2138 /* Assume r0 is available for use. */
2139 r = ds390_regWithIdx (R0_IDX);;
2144 r = getFreePtr (ic, &aop, FALSE);
2146 emitcode ("mov", "%s,_spx", r->name);
2151 if (options.useXstack)
2153 emitcode ("movx", "a,@%s", r->name);
2154 emitcode ("mov", "psw,a");
2155 emitcode ("dec", "%s", r->name);
2159 emitcode ("pop", "psw");
2163 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2165 if (options.useXstack)
2167 emitcode ("movx", "a,@%s", r->name);
2168 emitcode ("mov", "(%s+%d),a",
2169 regs390[i].base, 8 * bank + regs390[i].offset);
2170 emitcode ("dec", "%s", r->name);
2174 emitcode ("pop", "(%s+%d)",
2175 regs390[i].base, 8 * bank + regs390[i].offset);
2178 if (options.useXstack)
2180 emitcode ("mov", "_spx,%s", r->name);
2185 freeAsmop (NULL, aop, ic, TRUE);
2189 /*-----------------------------------------------------------------*/
2190 /* saveRBank - saves an entire register bank on the stack */
2191 /*-----------------------------------------------------------------*/
2193 saveRBank (int bank, iCode * ic, bool pushPsw)
2199 if (options.useXstack)
2203 /* Assume r0 is available for use. */
2204 r = ds390_regWithIdx (R0_IDX);;
2209 r = getFreePtr (ic, &aop, FALSE);
2211 emitcode ("mov", "%s,_spx", r->name);
2214 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2216 if (options.useXstack)
2218 emitcode ("inc", "%s", r->name);
2219 emitcode ("mov", "a,(%s+%d)",
2220 regs390[i].base, 8 * bank + regs390[i].offset);
2221 emitcode ("movx", "@%s,a", r->name);
2224 emitcode ("push", "(%s+%d)",
2225 regs390[i].base, 8 * bank + regs390[i].offset);
2230 if (options.useXstack)
2232 emitcode ("mov", "a,psw");
2233 emitcode ("movx", "@%s,a", r->name);
2234 emitcode ("inc", "%s", r->name);
2235 emitcode ("mov", "_spx,%s", r->name);
2239 emitcode ("push", "psw");
2242 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2247 freeAsmop (NULL, aop, ic, TRUE);
2256 /*-----------------------------------------------------------------*/
2257 /* genCall - generates a call statement */
2258 /*-----------------------------------------------------------------*/
2260 genCall (iCode * ic)
2263 bool restoreBank = FALSE;
2264 bool swapBanks = FALSE;
2266 D (emitcode (";", "genCall "););
2268 /* if we are calling a not _naked function that is not using
2269 the same register bank then we need to save the
2270 destination registers on the stack */
2271 dtype = operandType (IC_LEFT (ic));
2272 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2273 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2274 IFFUNC_ISISR (currFunc->type))
2278 /* This is unexpected; the bank should have been saved in
2281 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2287 /* if caller saves & we have not saved then */
2291 /* if send set is not empty the assign */
2292 /* We've saved all the registers we care about;
2293 * therefore, we may clobber any register not used
2294 * in the calling convention (i.e. anything not in
2301 for (sic = setFirstItem (_G.sendSet); sic;
2302 sic = setNextItem (_G.sendSet))
2304 int size, offset = 0;
2307 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2308 size = AOP_SIZE (IC_LEFT (sic));
2310 _startLazyDPSEvaluation ();
2313 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2314 FALSE, FALSE, TRUE);
2315 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2317 emitcode("mov", "%s,%s", regs390[offset].name, l);
2319 else if (strcmp (l, fReturn[offset]))
2321 emitcode ("mov", "%s,%s",
2327 _endLazyDPSEvaluation ();
2328 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2330 size = AOP_SIZE (IC_LEFT (sic));
2338 emitcode("mov", "%s,%s",
2339 fReturn[size], regs390[size].name);
2343 // we know that dpl(hxb) is the result, so
2344 _startLazyDPSEvaluation ();
2345 size=getSize(operandType(IC_LEFT(sic)));
2347 aopOp (IC_LEFT (sic), sic, FALSE,
2348 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2350 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2354 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2355 FALSE, FALSE, TRUE);
2356 if (strcmp (l, fReturn[offset]))
2358 emitcode ("mov", "%s,%s",
2364 _endLazyDPSEvaluation ();
2366 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2373 emitcode ("mov", "psw,#!constbyte",
2374 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2378 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2379 OP_SYMBOL (IC_LEFT (ic))->rname :
2380 OP_SYMBOL (IC_LEFT (ic))->name));
2384 emitcode ("mov", "psw,#!constbyte",
2385 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2388 /* if we need assign a result value */
2389 if ((IS_ITEMP (IC_RESULT (ic)) &&
2390 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2391 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2392 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2393 IS_TRUE_SYMOP (IC_RESULT (ic)))
2395 if (isOperandInFarSpace (IC_RESULT (ic))
2396 && getSize (operandType (IC_RESULT (ic))) <= 2)
2398 int size = getSize (operandType (IC_RESULT (ic)));
2400 /* Special case for 1 or 2 byte return in far space. */
2404 emitcode ("mov", "b,%s", fReturn[1]);
2407 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2408 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2412 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2414 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2419 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2422 assignResultValue (IC_RESULT (ic));
2424 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2428 /* adjust the stack for parameters if
2430 if (ic->parmBytes) {
2431 if (options.stack10bit) {
2432 emitcode ("clr","c");
2433 emitcode ("mov","a,sp");
2434 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2435 emitcode ("mov","sp,a");
2436 emitcode ("mov","a,esp");
2437 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2438 emitcode ("mov","esp,a");
2441 if (ic->parmBytes > 3) {
2442 emitcode ("mov", "a,%s", spname);
2443 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2444 emitcode ("mov", "%s,a", spname);
2446 for (i = 0; i < ic->parmBytes; i++)
2447 emitcode ("dec", "%s", spname);
2451 /* if we hade saved some registers then unsave them */
2453 unsaveRegisters (ic);
2455 /* if register bank was saved then pop them */
2457 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2460 /*-----------------------------------------------------------------*/
2461 /* genPcall - generates a call by pointer statement */
2462 /*-----------------------------------------------------------------*/
2464 genPcall (iCode * ic)
2467 symbol *rlbl = newiTempLabel (NULL);
2468 bool restoreBank=FALSE;
2470 D (emitcode (";", "genPcall ");
2474 /* if caller saves & we have not saved then */
2478 /* if we are calling a function that is not using
2479 the same register bank then we need to save the
2480 destination registers on the stack */
2481 dtype = operandType (IC_LEFT (ic));
2482 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2483 IFFUNC_ISISR (currFunc->type) &&
2484 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2485 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2489 /* push the return address on to the stack */
2490 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2491 emitcode ("push", "acc");
2492 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2493 emitcode ("push", "acc");
2495 if (options.model == MODEL_FLAT24)
2497 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2498 emitcode ("push", "acc");
2501 /* now push the calling address */
2502 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2504 pushSide (IC_LEFT (ic), FPTRSIZE);
2506 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2508 /* if send set is not empty the assign */
2513 for (sic = setFirstItem (_G.sendSet); sic;
2514 sic = setNextItem (_G.sendSet))
2516 int size, offset = 0;
2518 // we know that dpl(hxb) is the result, so
2519 _startLazyDPSEvaluation ();
2520 size=getSize(operandType(IC_LEFT(sic)));
2522 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2524 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2528 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2529 FALSE, FALSE, TRUE);
2530 if (strcmp (l, fReturn[offset]))
2532 emitcode ("mov", "%s,%s",
2538 _endLazyDPSEvaluation ();
2539 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2544 emitcode ("ret", "");
2545 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2548 /* if we need assign a result value */
2549 if ((IS_ITEMP (IC_RESULT (ic)) &&
2550 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2551 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2552 IS_TRUE_SYMOP (IC_RESULT (ic)))
2556 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2559 assignResultValue (IC_RESULT (ic));
2561 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2564 /* adjust the stack for parameters if
2569 if (ic->parmBytes > 3)
2571 emitcode ("mov", "a,%s", spname);
2572 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2573 emitcode ("mov", "%s,a", spname);
2576 for (i = 0; i < ic->parmBytes; i++)
2577 emitcode ("dec", "%s", spname);
2581 /* if register bank was saved then unsave them */
2583 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2585 /* if we hade saved some registers then
2588 unsaveRegisters (ic);
2592 /*-----------------------------------------------------------------*/
2593 /* resultRemat - result is rematerializable */
2594 /*-----------------------------------------------------------------*/
2596 resultRemat (iCode * ic)
2598 if (SKIP_IC (ic) || ic->op == IFX)
2601 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2603 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2604 if (sym->remat && !POINTER_SET (ic))
2611 #if defined(__BORLANDC__) || defined(_MSC_VER)
2612 #define STRCASECMP stricmp
2614 #define STRCASECMP strcasecmp
2617 /*-----------------------------------------------------------------*/
2618 /* inExcludeList - return 1 if the string is in exclude Reg list */
2619 /*-----------------------------------------------------------------*/
2621 inExcludeList (char *s)
2625 if (options.excludeRegs[i] &&
2626 STRCASECMP (options.excludeRegs[i], "none") == 0)
2629 for (i = 0; options.excludeRegs[i]; i++)
2631 if (options.excludeRegs[i] &&
2632 STRCASECMP (s, options.excludeRegs[i]) == 0)
2638 /*-----------------------------------------------------------------*/
2639 /* genFunction - generated code for function entry */
2640 /*-----------------------------------------------------------------*/
2642 genFunction (iCode * ic)
2646 bool switchedPSW = FALSE;
2648 D (emitcode (";", "genFunction "););
2651 /* create the function header */
2652 emitcode (";", "-----------------------------------------");
2653 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2654 emitcode (";", "-----------------------------------------");
2656 emitcode ("", "%s:", sym->rname);
2657 ftype = operandType (IC_LEFT (ic));
2659 if (IFFUNC_ISNAKED(ftype))
2661 emitcode(";", "naked function: no prologue.");
2665 if (options.stack_probe)
2666 emitcode ("lcall","__stack_probe");
2667 /* if critical function then turn interrupts off */
2668 if (IFFUNC_ISCRITICAL (ftype))
2669 emitcode ("clr", "ea");
2671 /* here we need to generate the equates for the
2672 register bank if required */
2673 if (FUNC_REGBANK (ftype) != rbank)
2677 rbank = FUNC_REGBANK (ftype);
2678 for (i = 0; i < ds390_nRegs; i++)
2680 if (regs390[i].print) {
2681 if (strcmp (regs390[i].base, "0") == 0)
2682 emitcode ("", "%s !equ !constbyte",
2684 8 * rbank + regs390[i].offset);
2686 emitcode ("", "%s !equ %s + !constbyte",
2689 8 * rbank + regs390[i].offset);
2694 /* if this is an interrupt service routine then
2695 save acc, b, dpl, dph */
2696 if (IFFUNC_ISISR (sym->type))
2699 if (!inExcludeList ("acc"))
2700 emitcode ("push", "acc");
2701 if (!inExcludeList ("b"))
2702 emitcode ("push", "b");
2703 if (!inExcludeList ("dpl"))
2704 emitcode ("push", "dpl");
2705 if (!inExcludeList ("dph"))
2706 emitcode ("push", "dph");
2707 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2709 emitcode ("push", "dpx");
2710 /* Make sure we're using standard DPTR */
2711 emitcode ("push", "dps");
2712 emitcode ("mov", "dps,#0");
2713 if (options.stack10bit)
2715 /* This ISR could conceivably use DPTR2. Better save it. */
2716 emitcode ("push", "dpl1");
2717 emitcode ("push", "dph1");
2718 emitcode ("push", "dpx1");
2719 emitcode ("push", DP2_RESULT_REG);
2722 /* if this isr has no bank i.e. is going to
2723 run with bank 0 , then we need to save more
2725 if (!FUNC_REGBANK (sym->type))
2728 /* if this function does not call any other
2729 function then we can be economical and
2730 save only those registers that are used */
2731 if (!IFFUNC_HASFCALL(sym->type))
2735 /* if any registers used */
2738 /* save the registers used */
2739 for (i = 0; i < sym->regsUsed->size; i++)
2741 if (bitVectBitValue (sym->regsUsed, i) ||
2742 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2743 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2750 /* this function has a function call cannot
2751 determines register usage so we will have to push the
2753 saveRBank (0, ic, FALSE);
2758 /* This ISR uses a non-zero bank.
2760 * We assume that the bank is available for our
2763 * However, if this ISR calls a function which uses some
2764 * other bank, we must save that bank entirely.
2766 unsigned long banksToSave = 0;
2768 if (IFFUNC_HASFCALL(sym->type))
2771 #define MAX_REGISTER_BANKS 4
2776 for (i = ic; i; i = i->next)
2778 if (i->op == ENDFUNCTION)
2780 /* we got to the end OK. */
2788 dtype = operandType (IC_LEFT(i));
2790 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2792 /* Mark this bank for saving. */
2793 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2795 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2799 banksToSave |= (1 << FUNC_REGBANK(dtype));
2802 /* And note that we don't need to do it in
2810 /* This is a mess; we have no idea what
2811 * register bank the called function might
2814 * The only thing I can think of to do is
2815 * throw a warning and hope.
2817 werror(W_FUNCPTR_IN_USING_ISR);
2821 if (banksToSave && options.useXstack)
2823 /* Since we aren't passing it an ic,
2824 * saveRBank will assume r0 is available to abuse.
2826 * So switch to our (trashable) bank now, so
2827 * the caller's R0 isn't trashed.
2829 emitcode ("push", "psw");
2830 emitcode ("mov", "psw,#!constbyte",
2831 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2835 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2837 if (banksToSave & (1 << ix))
2839 saveRBank(ix, NULL, FALSE);
2843 // jwk: this needs a closer look
2844 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2849 /* if callee-save to be used for this function
2850 then save the registers being used in this function */
2851 if (IFFUNC_CALLEESAVES(sym->type))
2855 /* if any registers used */
2858 /* save the registers used */
2859 for (i = 0; i < sym->regsUsed->size; i++)
2861 if (bitVectBitValue (sym->regsUsed, i) ||
2862 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2864 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2872 /* set the register bank to the desired value */
2873 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2876 emitcode ("push", "psw");
2877 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2880 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2881 if (options.stack10bit) {
2882 emitcode ("push","_bpx");
2883 emitcode ("push","_bpx+1");
2884 emitcode ("mov","_bpx,%s",spname);
2885 emitcode ("mov","_bpx+1,esp");
2886 emitcode ("anl","_bpx+1,#3");
2888 if (options.useXstack) {
2889 emitcode ("mov", "r0,%s", spname);
2890 emitcode ("mov", "a,_bp");
2891 emitcode ("movx", "@r0,a");
2892 emitcode ("inc", "%s", spname);
2894 /* set up the stack */
2895 emitcode ("push", "_bp"); /* save the callers stack */
2897 emitcode ("mov", "_bp,%s", spname);
2901 /* adjust the stack for the function */
2904 if (options.stack10bit) {
2905 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2906 assert (sym->recvSize <= 4);
2907 emitcode ("mov","a,sp");
2908 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2909 emitcode ("mov","sp,a");
2910 emitcode ("mov","a,esp");
2911 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2912 emitcode ("mov","esp,a");
2915 werror (W_STACK_OVERFLOW, sym->name);
2917 if (i > 3 && sym->recvSize < 4) {
2919 emitcode ("mov", "a,sp");
2920 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2921 emitcode ("mov", "sp,a");
2925 emitcode ("inc", "sp");
2932 emitcode ("mov", "a,_spx");
2933 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2934 emitcode ("mov", "_spx,a");
2939 /*-----------------------------------------------------------------*/
2940 /* genEndFunction - generates epilogue for functions */
2941 /*-----------------------------------------------------------------*/
2943 genEndFunction (iCode * ic)
2945 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2947 D (emitcode (";", "genEndFunction "););
2949 if (IFFUNC_ISNAKED(sym->type))
2951 emitcode(";", "naked function: no epilogue.");
2955 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2956 if (options.stack10bit) {
2957 emitcode ("mov", "sp,_bpx", spname);
2958 emitcode ("mov", "esp,_bpx+1", spname);
2960 emitcode ("mov", "%s,_bp", spname);
2964 /* if use external stack but some variables were
2965 added to the local stack then decrement the
2967 if (options.useXstack && sym->stack) {
2968 emitcode ("mov", "a,sp");
2969 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2970 emitcode ("mov", "sp,a");
2974 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2975 if (options.useXstack) {
2976 emitcode ("mov", "r0,%s", spname);
2977 emitcode ("movx", "a,@r0");
2978 emitcode ("mov", "_bp,a");
2979 emitcode ("dec", "%s", spname);
2981 if (options.stack10bit) {
2982 emitcode ("pop", "_bpx+1");
2983 emitcode ("pop", "_bpx");
2985 emitcode ("pop", "_bp");
2990 /* restore the register bank */
2991 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2993 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2994 || !options.useXstack)
2996 /* Special case of ISR using non-zero bank with useXstack
2999 emitcode ("pop", "psw");
3003 if (IFFUNC_ISISR (sym->type))
3006 /* now we need to restore the registers */
3007 /* if this isr has no bank i.e. is going to
3008 run with bank 0 , then we need to save more
3010 if (!FUNC_REGBANK (sym->type))
3012 /* if this function does not call any other
3013 function then we can be economical and
3014 save only those registers that are used */
3015 if (!IFFUNC_HASFCALL(sym->type))
3019 /* if any registers used */
3022 /* save the registers used */
3023 for (i = sym->regsUsed->size; i >= 0; i--)
3025 if (bitVectBitValue (sym->regsUsed, i) ||
3026 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3027 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3034 /* this function has a function call cannot
3035 determines register usage so we will have to pop the
3037 unsaveRBank (0, ic, FALSE);
3042 /* This ISR uses a non-zero bank.
3044 * Restore any register banks saved by genFunction
3047 // jwk: this needs a closer look
3048 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3051 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3053 if (savedBanks & (1 << ix))
3055 unsaveRBank(ix, NULL, FALSE);
3059 if (options.useXstack)
3061 /* Restore bank AFTER calling unsaveRBank,
3062 * since it can trash r0.
3064 emitcode ("pop", "psw");
3068 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3070 if (options.stack10bit)
3072 emitcode ("pop", DP2_RESULT_REG);
3073 emitcode ("pop", "dpx1");
3074 emitcode ("pop", "dph1");
3075 emitcode ("pop", "dpl1");
3077 emitcode ("pop", "dps");
3078 emitcode ("pop", "dpx");
3080 if (!inExcludeList ("dph"))
3081 emitcode ("pop", "dph");
3082 if (!inExcludeList ("dpl"))
3083 emitcode ("pop", "dpl");
3084 if (!inExcludeList ("b"))
3085 emitcode ("pop", "b");
3086 if (!inExcludeList ("acc"))
3087 emitcode ("pop", "acc");
3089 if (IFFUNC_ISCRITICAL (sym->type))
3090 emitcode ("setb", "ea");
3092 /* if debug then send end of function */
3093 if (options.debug && currFunc) {
3095 emitcode ("", "C$%s$%d$%d$%d ==.",
3096 FileBaseName (ic->filename), currFunc->lastLine,
3097 ic->level, ic->block);
3098 if (IS_STATIC (currFunc->etype))
3099 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3101 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3105 emitcode ("reti", "");
3109 if (IFFUNC_ISCRITICAL (sym->type))
3110 emitcode ("setb", "ea");
3112 if (IFFUNC_CALLEESAVES(sym->type))
3116 /* if any registers used */
3119 /* save the registers used */
3120 for (i = sym->regsUsed->size; i >= 0; i--)
3122 if (bitVectBitValue (sym->regsUsed, i) ||
3123 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3124 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3130 /* if debug then send end of function */
3131 if (options.debug && currFunc)
3134 emitcode ("", "C$%s$%d$%d$%d ==.",
3135 FileBaseName (ic->filename), currFunc->lastLine,
3136 ic->level, ic->block);
3137 if (IS_STATIC (currFunc->etype))
3138 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3140 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3144 emitcode ("ret", "");
3149 /*-----------------------------------------------------------------*/
3150 /* genRet - generate code for return statement */
3151 /*-----------------------------------------------------------------*/
3155 int size, offset = 0, pushed = 0;
3157 D (emitcode (";", "genRet ");
3160 /* if we have no return value then
3161 just generate the "ret" */
3165 /* we have something to return then
3166 move the return value into place */
3167 aopOp (IC_LEFT (ic), ic, FALSE,
3168 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3169 size = AOP_SIZE (IC_LEFT (ic));
3171 _startLazyDPSEvaluation ();
3175 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3177 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3178 FALSE, TRUE, FALSE);
3179 emitcode ("push", "%s", l);
3184 /* Since A is the last element of fReturn,
3185 * is is OK to clobber it in the aopGet.
3187 l = aopGet (AOP (IC_LEFT (ic)), offset,
3188 FALSE, FALSE, TRUE);
3189 if (strcmp (fReturn[offset], l))
3190 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3193 _endLazyDPSEvaluation ();
3200 if (strcmp (fReturn[pushed], "a"))
3201 emitcode ("pop", fReturn[pushed]);
3203 emitcode ("pop", "acc");
3206 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3209 /* generate a jump to the return label
3210 if the next is not the return statement */
3211 if (!(ic->next && ic->next->op == LABEL &&
3212 IC_LABEL (ic->next) == returnLabel))
3214 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3218 /*-----------------------------------------------------------------*/
3219 /* genLabel - generates a label */
3220 /*-----------------------------------------------------------------*/
3222 genLabel (iCode * ic)
3224 /* special case never generate */
3225 if (IC_LABEL (ic) == entryLabel)
3228 D (emitcode (";", "genLabel ");
3231 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3234 /*-----------------------------------------------------------------*/
3235 /* genGoto - generates a ljmp */
3236 /*-----------------------------------------------------------------*/
3238 genGoto (iCode * ic)
3240 D (emitcode (";", "genGoto ");
3242 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3245 /*-----------------------------------------------------------------*/
3246 /* findLabelBackwards: walks back through the iCode chain looking */
3247 /* for the given label. Returns number of iCode instructions */
3248 /* between that label and given ic. */
3249 /* Returns zero if label not found. */
3250 /*-----------------------------------------------------------------*/
3252 findLabelBackwards (iCode * ic, int key)
3261 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3263 /* printf("findLabelBackwards = %d\n", count); */
3271 /*-----------------------------------------------------------------*/
3272 /* genPlusIncr :- does addition with increment if possible */
3273 /*-----------------------------------------------------------------*/
3275 genPlusIncr (iCode * ic)
3277 unsigned int icount;
3278 unsigned int size = getDataSize (IC_RESULT (ic));
3280 /* will try to generate an increment */
3281 /* if the right side is not a literal
3283 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3286 /* if the literal value of the right hand side
3287 is greater than 4 then it is not worth it */
3288 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3291 /* if increment 16 bits in register */
3293 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3294 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3295 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3303 /* If the next instruction is a goto and the goto target
3304 * is <= 5 instructions previous to this, we can generate
3305 * jumps straight to that target.
3307 if (ic->next && ic->next->op == GOTO
3308 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3311 emitcode (";", "tail increment optimized (range %d)", labelRange);
3312 tlbl = IC_LABEL (ic->next);
3317 tlbl = newiTempLabel (NULL);
3320 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3321 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3322 IS_AOP_PREG (IC_RESULT (ic)))
3323 emitcode ("cjne", "%s,#0,!tlabel"
3324 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3328 emitcode ("clr", "a");
3329 emitcode ("cjne", "a,%s,!tlabel"
3330 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3334 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3337 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3338 IS_AOP_PREG (IC_RESULT (ic)))
3339 emitcode ("cjne", "%s,#0,!tlabel"
3340 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3343 emitcode ("cjne", "a,%s,!tlabel"
3344 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3347 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3351 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3352 IS_AOP_PREG (IC_RESULT (ic)))
3353 emitcode ("cjne", "%s,#0,!tlabel"
3354 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3358 emitcode ("cjne", "a,%s,!tlabel"
3359 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3362 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3367 emitcode ("", "!tlabeldef", tlbl->key + 100);
3372 /* if the sizes are greater than 1 then we cannot */
3373 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3374 AOP_SIZE (IC_LEFT (ic)) > 1)
3377 /* we can if the aops of the left & result match or
3378 if they are in registers and the registers are the
3381 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3382 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3383 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3388 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3389 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3390 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3395 _startLazyDPSEvaluation ();
3398 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3400 _endLazyDPSEvaluation ();
3409 /*-----------------------------------------------------------------*/
3410 /* outBitAcc - output a bit in acc */
3411 /*-----------------------------------------------------------------*/
3413 outBitAcc (operand * result)
3415 symbol *tlbl = newiTempLabel (NULL);
3416 /* if the result is a bit */
3417 if (AOP_TYPE (result) == AOP_CRY)
3419 aopPut (AOP (result), "a", 0);
3423 emitcode ("jz", "!tlabel", tlbl->key + 100);
3424 emitcode ("mov", "a,%s", one);
3425 emitcode ("", "!tlabeldef", tlbl->key + 100);
3430 /*-----------------------------------------------------------------*/
3431 /* genPlusBits - generates code for addition of two bits */
3432 /*-----------------------------------------------------------------*/
3434 genPlusBits (iCode * ic)
3436 D (emitcode (";", "genPlusBits ");
3438 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3440 symbol *lbl = newiTempLabel (NULL);
3441 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3442 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3443 emitcode ("cpl", "c");
3444 emitcode ("", "!tlabeldef", (lbl->key + 100));
3445 outBitC (IC_RESULT (ic));
3449 emitcode ("clr", "a");
3450 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3451 emitcode ("rlc", "a");
3452 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3453 emitcode ("addc", "a,#0");
3454 outAcc (IC_RESULT (ic));
3459 adjustArithmeticResult (iCode * ic)
3461 if (opIsGptr (IC_RESULT (ic)) &&
3462 opIsGptr (IC_LEFT (ic)) &&
3463 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3465 aopPut (AOP (IC_RESULT (ic)),
3466 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3470 if (opIsGptr (IC_RESULT (ic)) &&
3471 opIsGptr (IC_RIGHT (ic)) &&
3472 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3474 aopPut (AOP (IC_RESULT (ic)),
3475 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3479 if (opIsGptr (IC_RESULT (ic)) &&
3480 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3481 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3482 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3483 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3486 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3487 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3491 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3492 // Please don't bring it back without a really good reason.
3493 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3494 // (because all three operands are in far space).
3495 #define AOP_OP_3(ic) \
3496 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3497 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3498 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3499 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3500 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3501 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3503 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3505 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3509 // Macro to aopOp all three operands of an ic. If this cannot be done,
3510 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3511 // will be set TRUE. The caller must then handle the case specially, noting
3512 // that the IC_RESULT operand is not aopOp'd.
3513 #define AOP_OP_3_NOFATAL(ic, rc) \
3514 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3515 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3516 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3517 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3518 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3520 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3525 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3526 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3528 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3529 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3531 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3533 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3537 // aopOp the left & right operands of an ic.
3538 #define AOP_OP_2(ic) \
3539 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3540 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3542 // convienience macro.
3543 #define AOP_SET_LOCALS(ic) \
3544 left = IC_LEFT(ic); \
3545 right = IC_RIGHT(ic); \
3546 result = IC_RESULT(ic);
3549 // Given an integer value of pushedSize bytes on the stack,
3550 // adjust it to be resultSize bytes, either by discarding
3551 // the most significant bytes or by zero-padding.
3553 // On exit from this macro, pushedSize will have been adjusted to
3554 // equal resultSize, and ACC may be trashed.
3555 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3556 /* If the pushed data is bigger than the result, \
3557 * simply discard unused bytes. Icky, but works. \
3559 while (pushedSize > resultSize) \
3561 D (emitcode (";", "discarding unused result byte."););\
3562 emitcode ("pop", "acc"); \
3565 if (pushedSize < resultSize) \
3567 emitcode ("clr", "a"); \
3568 /* Conversly, we haven't pushed enough here. \
3569 * just zero-pad, and all is well. \
3571 while (pushedSize < resultSize) \
3573 emitcode("push", "acc"); \
3577 assert(pushedSize == resultSize);
3579 /*-----------------------------------------------------------------*/
3580 /* genPlus - generates code for addition */
3581 /*-----------------------------------------------------------------*/
3583 genPlus (iCode * ic)
3585 int size, offset = 0;
3586 bool pushResult = FALSE;
3589 D (emitcode (";", "genPlus "););
3591 /* special cases :- */
3592 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3593 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3594 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3595 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3597 while (size--) emitcode ("inc","dptr");
3599 emitcode ("mov","a,dpl");
3600 emitcode ("add","a,#!constbyte",size & 0xff);
3601 emitcode ("mov","dpl,a");
3602 emitcode ("mov","a,dph");
3603 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3604 emitcode ("mov","dph,a");
3605 emitcode ("mov","a,dpx");
3606 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3607 emitcode ("mov","dpx,a");
3609 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3612 if ( IS_SYMOP(IC_LEFT(ic)) &&
3613 OP_SYMBOL(IC_LEFT(ic))->remat &&
3614 isOperandInFarSpace(IC_RIGHT(ic))) {
3615 operand *op = IC_RIGHT(ic);
3616 IC_RIGHT(ic) = IC_LEFT(ic);
3620 AOP_OP_3_NOFATAL (ic, pushResult);
3623 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3628 /* if literal, literal on the right or
3629 if left requires ACC or right is already
3631 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3632 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3633 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3635 operand *t = IC_RIGHT (ic);
3636 IC_RIGHT (ic) = IC_LEFT (ic);
3638 emitcode (";", "Swapped plus args.");
3641 /* if both left & right are in bit
3643 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3644 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3650 /* if left in bit space & right literal */
3651 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3652 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3654 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3655 /* if result in bit space */
3656 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3658 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3659 emitcode ("cpl", "c");
3660 outBitC (IC_RESULT (ic));
3664 size = getDataSize (IC_RESULT (ic));
3665 _startLazyDPSEvaluation ();
3668 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3669 emitcode ("addc", "a,#0");
3670 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3672 _endLazyDPSEvaluation ();
3677 /* if I can do an increment instead
3678 of add then GOOD for ME */
3679 if (genPlusIncr (ic) == TRUE)
3681 emitcode (";", "did genPlusIncr");
3686 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3688 _startLazyDPSEvaluation ();
3691 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3693 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3695 emitcode ("add", "a,%s",
3696 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3698 emitcode ("addc", "a,%s",
3699 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3703 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3705 /* right is going to use ACC or we would have taken the
3708 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3710 D(emitcode(";", "+ AOP_ACC special case."););
3711 emitcode("xch", "a, %s", DP2_RESULT_REG);
3713 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3716 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3719 emitcode("add", "a, %s", DP2_RESULT_REG);
3723 emitcode ("add", "a,%s",
3724 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3729 emitcode ("addc", "a,%s",
3730 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3735 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3739 emitcode ("push", "acc");
3743 _endLazyDPSEvaluation ();
3747 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3749 size = getDataSize (IC_LEFT (ic));
3750 rSize = getDataSize (IC_RESULT (ic));
3752 ADJUST_PUSHED_RESULT(size, rSize);
3754 _startLazyDPSEvaluation ();
3757 emitcode ("pop", "acc");
3758 aopPut (AOP (IC_RESULT (ic)), "a", size);
3760 _endLazyDPSEvaluation ();
3763 adjustArithmeticResult (ic);
3766 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3767 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3768 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3771 /*-----------------------------------------------------------------*/
3772 /* genMinusDec :- does subtraction with deccrement if possible */
3773 /*-----------------------------------------------------------------*/
3775 genMinusDec (iCode * ic)
3777 unsigned int icount;
3778 unsigned int size = getDataSize (IC_RESULT (ic));
3780 /* will try to generate an increment */
3781 /* if the right side is not a literal
3783 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3786 /* if the literal value of the right hand side
3787 is greater than 4 then it is not worth it */
3788 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3791 /* if decrement 16 bits in register */
3792 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3793 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3794 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3802 /* If the next instruction is a goto and the goto target
3803 * is <= 5 instructions previous to this, we can generate
3804 * jumps straight to that target.
3806 if (ic->next && ic->next->op == GOTO
3807 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3810 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3811 tlbl = IC_LABEL (ic->next);
3816 tlbl = newiTempLabel (NULL);
3820 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3821 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3822 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3823 IS_AOP_PREG (IC_RESULT (ic)))
3824 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3825 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3829 emitcode ("mov", "a,#!constbyte",0xff);
3830 emitcode ("cjne", "a,%s,!tlabel"
3831 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3834 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3837 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3838 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3839 IS_AOP_PREG (IC_RESULT (ic)))
3840 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3841 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3845 emitcode ("cjne", "a,%s,!tlabel"
3846 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3849 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3853 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3854 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3855 IS_AOP_PREG (IC_RESULT (ic)))
3856 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3857 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3861 emitcode ("cjne", "a,%s,!tlabel"
3862 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3865 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3869 emitcode ("", "!tlabeldef", tlbl->key + 100);
3874 /* if the sizes are greater than 1 then we cannot */
3875 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3876 AOP_SIZE (IC_LEFT (ic)) > 1)
3879 /* we can if the aops of the left & result match or
3880 if they are in registers and the registers are the
3883 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3884 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3885 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3888 _startLazyDPSEvaluation ();
3891 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3893 _endLazyDPSEvaluation ();
3901 /*-----------------------------------------------------------------*/
3902 /* addSign - complete with sign */
3903 /*-----------------------------------------------------------------*/
3905 addSign (operand * result, int offset, int sign)
3907 int size = (getDataSize (result) - offset);
3910 _startLazyDPSEvaluation();
3913 emitcode ("rlc", "a");
3914 emitcode ("subb", "a,acc");
3917 aopPut (AOP (result), "a", offset++);
3924 aopPut (AOP (result), zero, offset++);
3927 _endLazyDPSEvaluation();
3931 /*-----------------------------------------------------------------*/
3932 /* genMinusBits - generates code for subtraction of two bits */
3933 /*-----------------------------------------------------------------*/
3935 genMinusBits (iCode * ic)
3937 symbol *lbl = newiTempLabel (NULL);
3939 D (emitcode (";", "genMinusBits "););
3941 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3943 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3944 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3945 emitcode ("cpl", "c");
3946 emitcode ("", "!tlabeldef", (lbl->key + 100));
3947 outBitC (IC_RESULT (ic));
3951 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3952 emitcode ("subb", "a,acc");
3953 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3954 emitcode ("inc", "a");
3955 emitcode ("", "!tlabeldef", (lbl->key + 100));
3956 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3957 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3961 /*-----------------------------------------------------------------*/
3962 /* genMinus - generates code for subtraction */
3963 /*-----------------------------------------------------------------*/
3965 genMinus (iCode * ic)
3967 int size, offset = 0;
3969 unsigned long lit = 0L;
3970 bool pushResult = FALSE;
3972 D (emitcode (";", "genMinus "););
3974 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3975 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3976 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3977 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3983 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3985 /* special cases :- */
3986 /* if both left & right are in bit space */
3987 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3988 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3994 /* if I can do an decrement instead
3995 of subtract then GOOD for ME */
3996 if (genMinusDec (ic) == TRUE)
4001 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4003 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4009 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4014 /* if literal, add a,#-lit, else normal subb */
4015 _startLazyDPSEvaluation ();
4018 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4019 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4020 emitcode ("subb", "a,%s",
4021 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4024 /* first add without previous c */
4026 if (!size && lit==-1) {
4027 emitcode ("dec", "a");
4029 emitcode ("add", "a,#!constbyte",
4030 (unsigned int) (lit & 0x0FFL));
4033 emitcode ("addc", "a,#!constbyte",
4034 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4040 emitcode ("push", "acc");
4044 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4048 _endLazyDPSEvaluation ();
4052 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4054 size = getDataSize (IC_LEFT (ic));
4055 rSize = getDataSize (IC_RESULT (ic));
4057 ADJUST_PUSHED_RESULT(size, rSize);
4059 _startLazyDPSEvaluation ();
4062 emitcode ("pop", "acc");
4063 aopPut (AOP (IC_RESULT (ic)), "a", size);
4065 _endLazyDPSEvaluation ();
4068 adjustArithmeticResult (ic);
4071 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4072 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4073 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4077 /*-----------------------------------------------------------------*/
4078 /* genMultbits :- multiplication of bits */
4079 /*-----------------------------------------------------------------*/
4081 genMultbits (operand * left,
4086 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4087 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4088 aopOp(result, ic, TRUE, FALSE);
4093 /*-----------------------------------------------------------------*/
4094 /* genMultOneByte : 8*8=8/16 bit multiplication */
4095 /*-----------------------------------------------------------------*/
4097 genMultOneByte (operand * left,
4102 sym_link *opetype = operandType (result);
4106 /* (if two literals: the value is computed before) */
4107 /* if one literal, literal on the right */
4108 if (AOP_TYPE (left) == AOP_LIT)
4113 emitcode (";", "swapped left and right");
4116 if (SPEC_USIGN(opetype)
4117 // ignore the sign of left and right, what else can we do?
4118 || (SPEC_USIGN(operandType(left)) &&
4119 SPEC_USIGN(operandType(right)))) {
4120 // just an unsigned 8*8=8/16 multiply
4121 //emitcode (";","unsigned");
4122 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4123 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4124 emitcode ("mul", "ab");
4126 _G.accInUse++; _G.bInUse++;
4127 aopOp(result, ic, TRUE, FALSE);
4129 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4131 // this should never happen
4132 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4133 AOP_SIZE(result), __FILE__, lineno);
4137 aopPut (AOP (result), "a", 0);
4138 _G.accInUse--; _G.bInUse--;
4139 if (AOP_SIZE(result)==2)
4141 aopPut (AOP (result), "b", 1);
4146 // we have to do a signed multiply
4148 emitcode (";", "signed");
4149 emitcode ("clr", "F0"); // reset sign flag
4150 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4152 lbl=newiTempLabel(NULL);
4153 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4154 // left side is negative, 8-bit two's complement, this fails for -128
4155 emitcode ("setb", "F0"); // set sign flag
4156 emitcode ("cpl", "a");
4157 emitcode ("inc", "a");
4159 emitcode ("", "!tlabeldef", lbl->key+100);
4162 if (AOP_TYPE(right)==AOP_LIT) {
4163 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4164 /* AND literal negative */
4165 if ((int) val < 0) {
4166 emitcode ("cpl", "F0"); // complement sign flag
4167 emitcode ("mov", "b,#!constbyte", -val);
4169 emitcode ("mov", "b,#!constbyte", val);
4172 lbl=newiTempLabel(NULL);
4173 emitcode ("mov", "b,a");
4174 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4175 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4176 // right side is negative, 8-bit two's complement
4177 emitcode ("cpl", "F0"); // complement sign flag
4178 emitcode ("cpl", "a");
4179 emitcode ("inc", "a");
4180 emitcode ("", "!tlabeldef", lbl->key+100);
4182 emitcode ("mul", "ab");
4184 _G.accInUse++;_G.bInUse++;
4185 aopOp(result, ic, TRUE, FALSE);
4187 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4189 // this should never happen
4190 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4191 AOP_SIZE(result), __FILE__, lineno);
4195 lbl=newiTempLabel(NULL);
4196 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4197 // only ONE op was negative, we have to do a 8/16-bit two's complement
4198 emitcode ("cpl", "a"); // lsb
4199 if (AOP_SIZE(result)==1) {
4200 emitcode ("inc", "a");
4202 emitcode ("add", "a,#1");
4203 emitcode ("xch", "a,b");
4204 emitcode ("cpl", "a"); // msb
4205 emitcode ("addc", "a,#0");
4206 emitcode ("xch", "a,b");
4209 emitcode ("", "!tlabeldef", lbl->key+100);
4210 aopPut (AOP (result), "a", 0);
4211 _G.accInUse--;_G.bInUse--;
4212 if (AOP_SIZE(result)==2) {
4213 aopPut (AOP (result), "b", 1);
4217 /*-----------------------------------------------------------------*/
4218 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4219 /*-----------------------------------------------------------------*/
4220 static void genMultTwoByte (operand *left, operand *right,
4221 operand *result, iCode *ic)
4223 sym_link *retype = getSpec(operandType(right));
4224 sym_link *letype = getSpec(operandType(left));
4225 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4228 if (AOP_TYPE (left) == AOP_LIT) {
4233 /* save EA bit in F1 */
4234 lbl = newiTempLabel(NULL);
4235 emitcode ("setb","F1");
4236 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4237 emitcode ("clr","F1");
4238 emitcode("","!tlabeldef",lbl->key+100);
4240 /* load up MB with right */
4242 emitcode("clr","F0");
4243 if (AOP_TYPE(right) == AOP_LIT) {
4244 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4246 emitcode("setb","F0");
4249 emitcode ("mov","mb,#!constbyte",val & 0xff);
4250 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4252 lbl = newiTempLabel(NULL);
4253 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4254 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4255 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4256 emitcode ("xch", "a,b");
4257 emitcode ("cpl","a");
4258 emitcode ("add", "a,#1");
4259 emitcode ("xch", "a,b");
4260 emitcode ("cpl", "a"); // msb
4261 emitcode ("addc", "a,#0");
4262 emitcode ("setb","F0");
4263 emitcode ("","!tlabeldef",lbl->key+100);
4264 emitcode ("mov","mb,b");
4265 emitcode ("mov","mb,a");
4268 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4269 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4271 /* load up MA with left */
4273 lbl = newiTempLabel(NULL);
4274 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4275 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4276 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4277 emitcode ("xch", "a,b");
4278 emitcode ("cpl","a");
4279 emitcode ("add", "a,#1");
4280 emitcode ("xch", "a,b");
4281 emitcode ("cpl", "a"); // msb
4282 emitcode ("addc","a,#0");
4283 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4284 emitcode ("setb","F0");
4285 emitcode ("","!tlabeldef",lbl->key+100);
4286 emitcode ("mov","ma,b");
4287 emitcode ("mov","ma,a");
4289 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4290 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4292 /* wait for multiplication to finish */
4293 lbl = newiTempLabel(NULL);
4294 emitcode("","!tlabeldef", lbl->key+100);
4295 emitcode("mov","a,mcnt1");
4296 emitcode("anl","a,#!constbyte",0x80);
4297 emitcode("jnz","!tlabel",lbl->key+100);
4299 freeAsmop (left, NULL, ic, TRUE);
4300 freeAsmop (right, NULL, ic,TRUE);
4301 aopOp(result, ic, TRUE, FALSE);
4303 /* if unsigned then simple */
4305 emitcode ("mov","a,ma");
4306 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4307 emitcode ("mov","a,ma");
4308 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4309 aopPut(AOP(result),"ma",1);
4310 aopPut(AOP(result),"ma",0);
4312 emitcode("push","ma");
4313 emitcode("push","ma");
4314 emitcode("push","ma");
4316 /* negate result if needed */
4317 lbl = newiTempLabel(NULL);
4318 emitcode("jnb","F0,!tlabel",lbl->key+100);
4319 emitcode("cpl","a");
4320 emitcode("add","a,#1");
4321 emitcode("","!tlabeldef", lbl->key+100);
4322 if (AOP_TYPE(result) == AOP_ACC)
4324 D(emitcode(";", "ACC special case."););
4325 /* We know result is the only live aop, and
4326 * it's obviously not a DPTR2, so AP is available.
4328 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4332 aopPut(AOP(result),"a",0);
4335 emitcode("pop","acc");
4336 lbl = newiTempLabel(NULL);
4337 emitcode("jnb","F0,!tlabel",lbl->key+100);
4338 emitcode("cpl","a");
4339 emitcode("addc","a,#0");
4340 emitcode("","!tlabeldef", lbl->key+100);
4341 aopPut(AOP(result),"a",1);
4342 emitcode("pop","acc");
4343 if (AOP_SIZE(result) >= 3) {
4344 lbl = newiTempLabel(NULL);
4345 emitcode("jnb","F0,!tlabel",lbl->key+100);
4346 emitcode("cpl","a");
4347 emitcode("addc","a,#0");
4348 emitcode("","!tlabeldef", lbl->key+100);
4349 aopPut(AOP(result),"a",2);
4351 emitcode("pop","acc");
4352 if (AOP_SIZE(result) >= 4) {
4353 lbl = newiTempLabel(NULL);
4354 emitcode("jnb","F0,!tlabel",lbl->key+100);
4355 emitcode("cpl","a");
4356 emitcode("addc","a,#0");
4357 emitcode("","!tlabeldef", lbl->key+100);
4358 aopPut(AOP(result),"a",3);
4360 if (AOP_TYPE(result) == AOP_ACC)
4362 /* We stashed the result away above. */
4363 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4367 freeAsmop (result, NULL, ic, TRUE);
4369 /* restore EA bit in F1 */
4370 lbl = newiTempLabel(NULL);
4371 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4372 emitcode ("setb","EA");
4373 emitcode("","!tlabeldef",lbl->key+100);
4377 /*-----------------------------------------------------------------*/
4378 /* genMult - generates code for multiplication */
4379 /*-----------------------------------------------------------------*/
4381 genMult (iCode * ic)
4383 operand *left = IC_LEFT (ic);
4384 operand *right = IC_RIGHT (ic);
4385 operand *result = IC_RESULT (ic);
4387 D (emitcode (";", "genMult "););
4389 /* assign the amsops */
4392 /* special cases first */
4394 if (AOP_TYPE (left) == AOP_CRY &&
4395 AOP_TYPE (right) == AOP_CRY)
4397 genMultbits (left, right, result, ic);
4401 /* if both are of size == 1 */
4402 if (AOP_SIZE (left) == 1 &&
4403 AOP_SIZE (right) == 1)
4405 genMultOneByte (left, right, result, ic);
4409 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4410 /* use the ds390 ARITHMETIC accel UNIT */
4411 genMultTwoByte (left, right, result, ic);
4414 /* should have been converted to function call */
4418 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4419 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4420 freeAsmop (result, NULL, ic, TRUE);
4423 /*-----------------------------------------------------------------*/
4424 /* genDivbits :- division of bits */
4425 /*-----------------------------------------------------------------*/
4427 genDivbits (operand * left,
4435 /* the result must be bit */
4436 LOAD_AB_FOR_DIV (left, right, l);
4437 emitcode ("div", "ab");
4438 emitcode ("rrc", "a");
4439 aopOp(result, ic, TRUE, FALSE);
4441 aopPut (AOP (result), "c", 0);
4444 /*-----------------------------------------------------------------*/
4445 /* genDivOneByte : 8 bit division */
4446 /*-----------------------------------------------------------------*/
4448 genDivOneByte (operand * left,
4453 sym_link *opetype = operandType (result);
4459 /* signed or unsigned */
4460 if (SPEC_USIGN (opetype))
4462 /* unsigned is easy */
4463 LOAD_AB_FOR_DIV (left, right, l);
4464 emitcode ("div", "ab");
4467 aopOp(result, ic, TRUE, FALSE);
4468 aopPut (AOP (result), "a", 0);
4471 size = AOP_SIZE (result) - 1;
4475 aopPut (AOP (result), zero, offset++);
4480 /* signed is a little bit more difficult */
4482 /* save the signs of the operands */
4483 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4485 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4486 emitcode ("push", "acc"); /* save it on the stack */
4488 /* now sign adjust for both left & right */
4489 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4491 lbl = newiTempLabel (NULL);
4492 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4493 emitcode ("cpl", "a");
4494 emitcode ("inc", "a");
4495 emitcode ("", "!tlabeldef", (lbl->key + 100));
4496 emitcode ("mov", "b,a");
4498 /* sign adjust left side */
4499 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4502 lbl = newiTempLabel (NULL);
4503 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4504 emitcode ("cpl", "a");
4505 emitcode ("inc", "a");
4506 emitcode ("", "!tlabeldef", (lbl->key + 100));
4508 /* now the division */
4509 emitcode ("nop", "; workaround for DS80C390 div bug.");
4510 emitcode ("div", "ab");
4511 /* we are interested in the lower order
4513 emitcode ("mov", "b,a");
4514 lbl = newiTempLabel (NULL);
4515 emitcode ("pop", "acc");
4516 /* if there was an over flow we don't
4517 adjust the sign of the result */
4518 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4519 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4521 emitcode ("clr", "a");
4522 emitcode ("subb", "a,b");
4523 emitcode ("mov", "b,a");
4524 emitcode ("", "!tlabeldef", (lbl->key + 100));
4526 /* now we are done */
4527 _G.accInUse++; _G.bInUse++;
4528 aopOp(result, ic, TRUE, FALSE);
4530 aopPut (AOP (result), "b", 0);
4532 size = AOP_SIZE (result) - 1;
4536 emitcode ("mov", "c,b.7");
4537 emitcode ("subb", "a,acc");
4541 aopPut (AOP (result), "a", offset++);
4543 _G.accInUse--; _G.bInUse--;
4547 /*-----------------------------------------------------------------*/
4548 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4549 /*-----------------------------------------------------------------*/
4550 static void genDivTwoByte (operand *left, operand *right,
4551 operand *result, iCode *ic)
4553 sym_link *retype = getSpec(operandType(right));
4554 sym_link *letype = getSpec(operandType(left));
4555 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4558 /* save EA bit in F1 */
4559 lbl = newiTempLabel(NULL);
4560 emitcode ("setb","F1");
4561 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4562 emitcode ("clr","F1");
4563 emitcode("","!tlabeldef",lbl->key+100);
4565 /* load up MA with left */
4567 emitcode("clr","F0");
4568 lbl = newiTempLabel(NULL);
4569 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4570 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4571 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4572 emitcode ("xch", "a,b");
4573 emitcode ("cpl","a");
4574 emitcode ("add", "a,#1");
4575 emitcode ("xch", "a,b");
4576 emitcode ("cpl", "a"); // msb
4577 emitcode ("addc","a,#0");
4578 emitcode ("setb","F0");
4579 emitcode ("","!tlabeldef",lbl->key+100);
4580 emitcode ("mov","ma,b");
4581 emitcode ("mov","ma,a");
4583 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4584 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4587 /* load up MB with right */
4589 if (AOP_TYPE(right) == AOP_LIT) {
4590 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4592 lbl = newiTempLabel(NULL);
4593 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4594 emitcode("setb","F0");
4595 emitcode ("","!tlabeldef",lbl->key+100);
4598 emitcode ("mov","mb,#!constbyte",val & 0xff);
4599 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4601 lbl = newiTempLabel(NULL);
4602 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4603 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4604 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4605 emitcode ("xch", "a,b");
4606 emitcode ("cpl","a");
4607 emitcode ("add", "a,#1");
4608 emitcode ("xch", "a,b");
4609 emitcode ("cpl", "a"); // msb
4610 emitcode ("addc", "a,#0");
4611 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4612 emitcode ("setb","F0");
4613 emitcode ("","!tlabeldef",lbl->key+100);
4614 emitcode ("mov","mb,b");
4615 emitcode ("mov","mb,a");
4618 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4619 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4622 /* wait for multiplication to finish */
4623 lbl = newiTempLabel(NULL);
4624 emitcode("","!tlabeldef", lbl->key+100);
4625 emitcode("mov","a,mcnt1");
4626 emitcode("anl","a,#!constbyte",0x80);
4627 emitcode("jnz","!tlabel",lbl->key+100);
4629 freeAsmop (left, NULL, ic, TRUE);
4630 freeAsmop (right, NULL, ic,TRUE);
4631 aopOp(result, ic, TRUE, FALSE);
4633 /* if unsigned then simple */
4635 aopPut(AOP(result),"ma",1);
4636 aopPut(AOP(result),"ma",0);
4638 emitcode("push","ma");
4640 /* negate result if needed */
4641 lbl = newiTempLabel(NULL);
4642 emitcode("jnb","F0,!tlabel",lbl->key+100);
4643 emitcode("cpl","a");
4644 emitcode("add","a,#1");
4645 emitcode("","!tlabeldef", lbl->key+100);
4646 aopPut(AOP(result),"a",0);
4647 emitcode("pop","acc");
4648 lbl = newiTempLabel(NULL);
4649 emitcode("jnb","F0,!tlabel",lbl->key+100);
4650 emitcode("cpl","a");
4651 emitcode("addc","a,#0");
4652 emitcode("","!tlabeldef", lbl->key+100);
4653 aopPut(AOP(result),"a",1);
4655 freeAsmop (result, NULL, ic, TRUE);
4656 /* restore EA bit in F1 */
4657 lbl = newiTempLabel(NULL);
4658 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4659 emitcode ("setb","EA");
4660 emitcode("","!tlabeldef",lbl->key+100);
4664 /*-----------------------------------------------------------------*/
4665 /* genDiv - generates code for division */
4666 /*-----------------------------------------------------------------*/
4670 operand *left = IC_LEFT (ic);
4671 operand *right = IC_RIGHT (ic);
4672 operand *result = IC_RESULT (ic);
4674 D (emitcode (";", "genDiv "););
4676 /* assign the amsops */
4679 /* special cases first */
4681 if (AOP_TYPE (left) == AOP_CRY &&
4682 AOP_TYPE (right) == AOP_CRY)
4684 genDivbits (left, right, result, ic);
4688 /* if both are of size == 1 */
4689 if (AOP_SIZE (left) == 1 &&
4690 AOP_SIZE (right) == 1)
4692 genDivOneByte (left, right, result, ic);
4696 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4697 /* use the ds390 ARITHMETIC accel UNIT */
4698 genDivTwoByte (left, right, result, ic);
4701 /* should have been converted to function call */
4704 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706 freeAsmop (result, NULL, ic, TRUE);
4709 /*-----------------------------------------------------------------*/
4710 /* genModbits :- modulus of bits */
4711 /*-----------------------------------------------------------------*/
4713 genModbits (operand * left,
4721 /* the result must be bit */
4722 LOAD_AB_FOR_DIV (left, right, l);
4723 emitcode ("div", "ab");
4724 emitcode ("mov", "a,b");
4725 emitcode ("rrc", "a");
4726 aopOp(result, ic, TRUE, FALSE);
4727 aopPut (AOP (result), "c", 0);
4730 /*-----------------------------------------------------------------*/
4731 /* genModOneByte : 8 bit modulus */
4732 /*-----------------------------------------------------------------*/
4734 genModOneByte (operand * left,
4739 sym_link *opetype = operandType (result);
4743 /* signed or unsigned */
4744 if (SPEC_USIGN (opetype))
4746 /* unsigned is easy */
4747 LOAD_AB_FOR_DIV (left, right, l);
4748 emitcode ("div", "ab");
4749 aopOp(result, ic, TRUE, FALSE);
4750 aopPut (AOP (result), "b", 0);
4754 /* signed is a little bit more difficult */
4756 /* save the signs of the operands */
4757 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4760 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4761 emitcode ("push", "acc"); /* save it on the stack */
4763 /* now sign adjust for both left & right */
4764 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4767 lbl = newiTempLabel (NULL);
4768 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4769 emitcode ("cpl", "a");
4770 emitcode ("inc", "a");
4771 emitcode ("", "!tlabeldef", (lbl->key + 100));
4772 emitcode ("mov", "b,a");
4774 /* sign adjust left side */
4775 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4778 lbl = newiTempLabel (NULL);
4779 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4780 emitcode ("cpl", "a");
4781 emitcode ("inc", "a");
4782 emitcode ("", "!tlabeldef", (lbl->key + 100));
4784 /* now the multiplication */
4785 emitcode ("nop", "; workaround for DS80C390 div bug.");
4786 emitcode ("div", "ab");
4787 /* we are interested in the lower order
4789 lbl = newiTempLabel (NULL);
4790 emitcode ("pop", "acc");
4791 /* if there was an over flow we don't
4792 adjust the sign of the result */
4793 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4794 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4796 emitcode ("clr", "a");
4797 emitcode ("subb", "a,b");
4798 emitcode ("mov", "b,a");
4799 emitcode ("", "!tlabeldef", (lbl->key + 100));
4802 /* now we are done */
4803 aopOp(result, ic, TRUE, FALSE);
4804 aopPut (AOP (result), "b", 0);
4809 /*-----------------------------------------------------------------*/
4810 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4811 /*-----------------------------------------------------------------*/
4812 static void genModTwoByte (operand *left, operand *right,
4813 operand *result, iCode *ic)
4815 sym_link *retype = getSpec(operandType(right));
4816 sym_link *letype = getSpec(operandType(left));
4817 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4820 /* load up MA with left */
4821 /* save EA bit in F1 */
4822 lbl = newiTempLabel(NULL);
4823 emitcode ("setb","F1");
4824 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4825 emitcode ("clr","F1");
4826 emitcode("","!tlabeldef",lbl->key+100);
4829 lbl = newiTempLabel(NULL);
4830 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4831 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4832 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4833 emitcode ("xch", "a,b");
4834 emitcode ("cpl","a");
4835 emitcode ("add", "a,#1");
4836 emitcode ("xch", "a,b");
4837 emitcode ("cpl", "a"); // msb
4838 emitcode ("addc","a,#0");
4839 emitcode ("","!tlabeldef",lbl->key+100);
4840 emitcode ("mov","ma,b");
4841 emitcode ("mov","ma,a");
4843 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4844 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4847 /* load up MB with right */
4849 if (AOP_TYPE(right) == AOP_LIT) {
4850 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4854 emitcode ("mov","mb,#!constbyte",val & 0xff);
4855 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4857 lbl = newiTempLabel(NULL);
4858 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4859 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4860 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4861 emitcode ("xch", "a,b");
4862 emitcode ("cpl","a");
4863 emitcode ("add", "a,#1");
4864 emitcode ("xch", "a,b");
4865 emitcode ("cpl", "a"); // msb
4866 emitcode ("addc", "a,#0");
4867 emitcode ("","!tlabeldef",lbl->key+100);
4868 emitcode ("mov","mb,b");
4869 emitcode ("mov","mb,a");
4872 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4873 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4876 /* wait for multiplication to finish */
4877 lbl = newiTempLabel(NULL);
4878 emitcode("","!tlabeldef", lbl->key+100);
4879 emitcode("mov","a,mcnt1");
4880 emitcode("anl","a,#!constbyte",0x80);
4881 emitcode("jnz","!tlabel",lbl->key+100);
4883 freeAsmop (left, NULL, ic, TRUE);
4884 freeAsmop (right, NULL, ic,TRUE);
4885 aopOp(result, ic, TRUE, FALSE);
4887 aopPut(AOP(result),"mb",1);
4888 aopPut(AOP(result),"mb",0);
4889 freeAsmop (result, NULL, ic, TRUE);
4891 /* restore EA bit in F1 */
4892 lbl = newiTempLabel(NULL);
4893 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4894 emitcode ("setb","EA");
4895 emitcode("","!tlabeldef",lbl->key+100);
4899 /*-----------------------------------------------------------------*/
4900 /* genMod - generates code for division */
4901 /*-----------------------------------------------------------------*/
4905 operand *left = IC_LEFT (ic);
4906 operand *right = IC_RIGHT (ic);
4907 operand *result = IC_RESULT (ic);
4909 D (emitcode (";", "genMod "); );
4911 /* assign the amsops */
4914 /* special cases first */
4916 if (AOP_TYPE (left) == AOP_CRY &&
4917 AOP_TYPE (right) == AOP_CRY)
4919 genModbits (left, right, result, ic);
4923 /* if both are of size == 1 */
4924 if (AOP_SIZE (left) == 1 &&
4925 AOP_SIZE (right) == 1)
4927 genModOneByte (left, right, result, ic);
4931 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4932 /* use the ds390 ARITHMETIC accel UNIT */
4933 genModTwoByte (left, right, result, ic);
4937 /* should have been converted to function call */
4941 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4942 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (result, NULL, ic, TRUE);
4946 /*-----------------------------------------------------------------*/
4947 /* genIfxJump :- will create a jump depending on the ifx */
4948 /*-----------------------------------------------------------------*/
4950 genIfxJump (iCode * ic, char *jval)
4953 symbol *tlbl = newiTempLabel (NULL);
4956 D (emitcode (";", "genIfxJump ");
4959 /* if true label then we jump if condition
4963 jlbl = IC_TRUE (ic);
4964 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4965 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4969 /* false label is present */
4970 jlbl = IC_FALSE (ic);
4971 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4972 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4974 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4975 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
4977 emitcode (inst, "!tlabel", tlbl->key + 100);
4978 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
4979 emitcode ("", "!tlabeldef", tlbl->key + 100);
4981 /* mark the icode as generated */
4985 /*-----------------------------------------------------------------*/
4986 /* genCmp :- greater or less than comparison */
4987 /*-----------------------------------------------------------------*/
4989 genCmp (operand * left, operand * right,
4990 iCode * ic, iCode * ifx, int sign)
4992 int size, offset = 0;
4993 unsigned long lit = 0L;
4996 D (emitcode (";", "genCmp");
4999 result = IC_RESULT (ic);
5001 /* if left & right are bit variables */
5002 if (AOP_TYPE (left) == AOP_CRY &&
5003 AOP_TYPE (right) == AOP_CRY)
5005 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5006 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5010 /* subtract right from left if at the
5011 end the carry flag is set then we know that
5012 left is greater than right */
5013 size = max (AOP_SIZE (left), AOP_SIZE (right));
5015 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5016 if ((size == 1) && !sign &&
5017 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5019 symbol *lbl = newiTempLabel (NULL);
5020 emitcode ("cjne", "%s,%s,!tlabel",
5021 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5022 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5024 emitcode ("", "!tlabeldef", lbl->key + 100);
5028 if (AOP_TYPE (right) == AOP_LIT)
5030 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5031 /* optimize if(x < 0) or if(x >= 0) */
5040 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5042 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5043 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5045 aopOp (result, ic, FALSE, FALSE);
5047 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5049 freeAsmop (result, NULL, ic, TRUE);
5050 genIfxJump (ifx, "acc.7");
5055 emitcode ("rlc", "a");
5057 goto release_freedLR;
5065 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5066 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5067 //emitcode (";", "genCmp #2");
5068 if (sign && (size == 0))
5070 //emitcode (";", "genCmp #3");
5071 emitcode ("xrl", "a,#!constbyte",0x80);
5072 if (AOP_TYPE (right) == AOP_LIT)
5074 unsigned long lit = (unsigned long)
5075 floatFromVal (AOP (right)->aopu.aop_lit);
5076 //emitcode (";", "genCmp #3.1");
5077 emitcode ("subb", "a,#!constbyte",
5078 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5082 //emitcode (";", "genCmp #3.2");
5083 if (AOP_NEEDSACC (right))
5085 emitcode ("push", "acc");
5087 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5088 FALSE, FALSE, FALSE));
5089 emitcode ("xrl", "b,#!constbyte",0x80);
5090 if (AOP_NEEDSACC (right))
5092 emitcode ("pop", "acc");
5094 emitcode ("subb", "a,b");
5101 //emitcode (";", "genCmp #4");
5102 if (AOP_NEEDSACC (right))
5105 //emitcode (";", "genCmp #4.1");
5106 emitcode ("xch", "a, b");
5107 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5108 emitcode ("xch", "a, b");
5113 //emitcode (";", "genCmp #4.2");
5114 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5117 emitcode ("subb", "a,%s", s);
5124 /* Don't need the left & right operands any more; do need the result. */
5125 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128 aopOp (result, ic, FALSE, FALSE);
5132 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5138 /* if the result is used in the next
5139 ifx conditional branch then generate
5140 code a little differently */
5143 genIfxJump (ifx, "c");
5149 /* leave the result in acc */
5151 freeAsmop (result, NULL, ic, TRUE);
5154 /*-----------------------------------------------------------------*/
5155 /* genCmpGt :- greater than comparison */
5156 /*-----------------------------------------------------------------*/
5158 genCmpGt (iCode * ic, iCode * ifx)
5160 operand *left, *right;
5161 sym_link *letype, *retype;
5164 D (emitcode (";", "genCmpGt ");
5167 left = IC_LEFT (ic);
5168 right = IC_RIGHT (ic);
5170 letype = getSpec (operandType (left));
5171 retype = getSpec (operandType (right));
5172 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5174 /* assign the left & right amsops */
5177 genCmp (right, left, ic, ifx, sign);
5180 /*-----------------------------------------------------------------*/
5181 /* genCmpLt - less than comparisons */
5182 /*-----------------------------------------------------------------*/
5184 genCmpLt (iCode * ic, iCode * ifx)
5186 operand *left, *right;
5187 sym_link *letype, *retype;
5190 D (emitcode (";", "genCmpLt "););
5192 left = IC_LEFT (ic);
5193 right = IC_RIGHT (ic);
5195 letype = getSpec (operandType (left));
5196 retype = getSpec (operandType (right));
5197 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5199 /* assign the left & right amsops */
5202 genCmp (left, right, ic, ifx, sign);
5205 /*-----------------------------------------------------------------*/
5206 /* gencjneshort - compare and jump if not equal */
5207 /*-----------------------------------------------------------------*/
5209 gencjneshort (operand * left, operand * right, symbol * lbl)
5211 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5213 unsigned long lit = 0L;
5215 D (emitcode (";", "gencjneshort");
5218 /* if the left side is a literal or
5219 if the right is in a pointer register and left
5221 if ((AOP_TYPE (left) == AOP_LIT) ||
5222 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5229 if (AOP_TYPE (right) == AOP_LIT)
5230 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5232 if (opIsGptr (left) || opIsGptr (right))
5234 /* We are comparing a generic pointer to something.
5235 * Exclude the generic type byte from the comparison.
5238 D (emitcode (";", "cjneshort: generic ptr special case.");
5243 /* if the right side is a literal then anything goes */
5244 if (AOP_TYPE (right) == AOP_LIT &&
5245 AOP_TYPE (left) != AOP_DIR)
5249 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5251 emitcode ("cjne", "a,%s,!tlabel",
5252 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5258 /* if the right side is in a register or in direct space or
5259 if the left is a pointer register & right is not */
5260 else if (AOP_TYPE (right) == AOP_REG ||
5261 AOP_TYPE (right) == AOP_DIR ||
5262 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5263 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5267 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5268 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5269 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5270 emitcode ("jnz", "!tlabel", lbl->key + 100);
5272 emitcode ("cjne", "a,%s,!tlabel",
5273 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5280 /* right is a pointer reg need both a & b */
5283 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5284 if (strcmp (l, "b"))
5285 emitcode ("mov", "b,%s", l);
5286 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5287 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5293 /*-----------------------------------------------------------------*/
5294 /* gencjne - compare and jump if not equal */
5295 /*-----------------------------------------------------------------*/
5297 gencjne (operand * left, operand * right, symbol * lbl)
5299 symbol *tlbl = newiTempLabel (NULL);
5301 D (emitcode (";", "gencjne");
5304 gencjneshort (left, right, lbl);
5306 emitcode ("mov", "a,%s", one);
5307 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5308 emitcode ("", "!tlabeldef", lbl->key + 100);
5309 emitcode ("clr", "a");
5310 emitcode ("", "!tlabeldef", tlbl->key + 100);
5313 /*-----------------------------------------------------------------*/
5314 /* genCmpEq - generates code for equal to */
5315 /*-----------------------------------------------------------------*/
5317 genCmpEq (iCode * ic, iCode * ifx)
5319 operand *left, *right, *result;
5321 D (emitcode (";", "genCmpEq ");
5325 AOP_SET_LOCALS (ic);
5327 /* if literal, literal on the right or
5328 if the right is in a pointer register and left
5330 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5331 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5333 operand *t = IC_RIGHT (ic);
5334 IC_RIGHT (ic) = IC_LEFT (ic);
5338 if (ifx && /* !AOP_SIZE(result) */
5339 OP_SYMBOL (result) &&
5340 OP_SYMBOL (result)->regType == REG_CND)
5343 /* if they are both bit variables */
5344 if (AOP_TYPE (left) == AOP_CRY &&
5345 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5347 if (AOP_TYPE (right) == AOP_LIT)
5349 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5352 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5353 emitcode ("cpl", "c");
5357 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5361 emitcode ("clr", "c");
5363 /* AOP_TYPE(right) == AOP_CRY */
5367 symbol *lbl = newiTempLabel (NULL);
5368 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5369 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5370 emitcode ("cpl", "c");
5371 emitcode ("", "!tlabeldef", (lbl->key + 100));
5373 /* if true label then we jump if condition
5375 tlbl = newiTempLabel (NULL);
5378 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5379 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5383 emitcode ("jc", "!tlabel", tlbl->key + 100);
5384 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5386 emitcode ("", "!tlabeldef", tlbl->key + 100);
5390 tlbl = newiTempLabel (NULL);
5391 gencjneshort (left, right, tlbl);
5394 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5395 emitcode ("", "!tlabeldef", tlbl->key + 100);
5399 symbol *lbl = newiTempLabel (NULL);
5400 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5401 emitcode ("", "!tlabeldef", tlbl->key + 100);
5402 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5403 emitcode ("", "!tlabeldef", lbl->key + 100);
5406 /* mark the icode as generated */
5409 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5410 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5414 /* if they are both bit variables */
5415 if (AOP_TYPE (left) == AOP_CRY &&
5416 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5418 if (AOP_TYPE (right) == AOP_LIT)
5420 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5423 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5424 emitcode ("cpl", "c");
5428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5432 emitcode ("clr", "c");
5434 /* AOP_TYPE(right) == AOP_CRY */
5438 symbol *lbl = newiTempLabel (NULL);
5439 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5440 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5441 emitcode ("cpl", "c");
5442 emitcode ("", "!tlabeldef", (lbl->key + 100));
5445 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5448 aopOp (result, ic, TRUE, FALSE);
5451 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5458 genIfxJump (ifx, "c");
5461 /* if the result is used in an arithmetic operation
5462 then put the result in place */
5467 gencjne (left, right, newiTempLabel (NULL));
5469 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5470 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5472 aopOp (result, ic, TRUE, FALSE);
5474 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5476 aopPut (AOP (result), "a", 0);
5481 genIfxJump (ifx, "a");
5484 /* if the result is used in an arithmetic operation
5485 then put the result in place */
5486 if (AOP_TYPE (result) != AOP_CRY)
5488 /* leave the result in acc */
5492 freeAsmop (result, NULL, ic, TRUE);
5495 /*-----------------------------------------------------------------*/
5496 /* ifxForOp - returns the icode containing the ifx for operand */
5497 /*-----------------------------------------------------------------*/
5499 ifxForOp (operand * op, iCode * ic)
5501 /* if true symbol then needs to be assigned */
5502 if (IS_TRUE_SYMOP (op))
5505 /* if this has register type condition and
5506 the next instruction is ifx with the same operand
5507 and live to of the operand is upto the ifx only then */
5509 ic->next->op == IFX &&
5510 IC_COND (ic->next)->key == op->key &&
5511 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5516 /*-----------------------------------------------------------------*/
5517 /* hasInc - operand is incremented before any other use */
5518 /*-----------------------------------------------------------------*/
5520 hasInc (operand *op, iCode *ic)
5522 sym_link *type = operandType(op);
5523 sym_link *retype = getSpec (type);
5524 iCode *lic = ic->next;
5527 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5528 if (!IS_SYMOP(op)) return NULL;
5530 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5531 isize = getSize(type->next);
5533 /* if operand of the form op = op + <sizeof *op> */
5534 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5535 isOperandEqual(IC_RESULT(lic),op) &&
5536 isOperandLiteral(IC_RIGHT(lic)) &&
5537 operandLitValue(IC_RIGHT(lic)) == isize) {
5540 /* if the operand used or deffed */
5541 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5544 /* if GOTO or IFX */
5545 if (lic->op == IFX || lic->op == GOTO) break;
5551 /*-----------------------------------------------------------------*/
5552 /* genAndOp - for && operation */
5553 /*-----------------------------------------------------------------*/
5555 genAndOp (iCode * ic)
5557 operand *left, *right, *result;
5560 D (emitcode (";", "genAndOp "););
5562 /* note here that && operations that are in an
5563 if statement are taken away by backPatchLabels
5564 only those used in arthmetic operations remain */
5566 AOP_SET_LOCALS (ic);
5568 /* if both are bit variables */
5569 if (AOP_TYPE (left) == AOP_CRY &&
5570 AOP_TYPE (right) == AOP_CRY)
5572 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5573 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5574 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5575 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5577 aopOp (result,ic,FALSE, FALSE);
5582 tlbl = newiTempLabel (NULL);
5584 emitcode ("jz", "!tlabel", tlbl->key + 100);
5586 emitcode ("", "!tlabeldef", tlbl->key + 100);
5587 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5590 aopOp (result,ic,FALSE, FALSE);
5593 freeAsmop (result, NULL, ic, TRUE);
5597 /*-----------------------------------------------------------------*/
5598 /* genOrOp - for || operation */
5599 /*-----------------------------------------------------------------*/
5601 genOrOp (iCode * ic)
5603 operand *left, *right, *result;
5606 D (emitcode (";", "genOrOp "););
5608 /* note here that || operations that are in an
5609 if statement are taken away by backPatchLabels
5610 only those used in arthmetic operations remain */
5612 AOP_SET_LOCALS (ic);
5614 /* if both are bit variables */
5615 if (AOP_TYPE (left) == AOP_CRY &&
5616 AOP_TYPE (right) == AOP_CRY)
5618 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5619 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5620 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5621 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5623 aopOp (result,ic,FALSE, FALSE);
5629 tlbl = newiTempLabel (NULL);
5631 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5633 emitcode ("", "!tlabeldef", tlbl->key + 100);
5634 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5635 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5637 aopOp (result,ic,FALSE, FALSE);
5642 freeAsmop (result, NULL, ic, TRUE);
5645 /*-----------------------------------------------------------------*/
5646 /* isLiteralBit - test if lit == 2^n */
5647 /*-----------------------------------------------------------------*/
5649 isLiteralBit (unsigned long lit)
5651 unsigned long pw[32] =
5652 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5653 0x100L, 0x200L, 0x400L, 0x800L,
5654 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5655 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5656 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5657 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5658 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5661 for (idx = 0; idx < 32; idx++)
5667 /*-----------------------------------------------------------------*/
5668 /* continueIfTrue - */
5669 /*-----------------------------------------------------------------*/
5671 continueIfTrue (iCode * ic)
5674 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5678 /*-----------------------------------------------------------------*/
5680 /*-----------------------------------------------------------------*/
5682 jumpIfTrue (iCode * ic)
5685 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5689 /*-----------------------------------------------------------------*/
5690 /* jmpTrueOrFalse - */
5691 /*-----------------------------------------------------------------*/
5693 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5695 // ugly but optimized by peephole
5698 symbol *nlbl = newiTempLabel (NULL);
5699 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5700 emitcode ("", "!tlabeldef", tlbl->key + 100);
5701 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5702 emitcode ("", "!tlabeldef", nlbl->key + 100);
5706 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5707 emitcode ("", "!tlabeldef", tlbl->key + 100);
5712 // Generate code to perform a bit-wise logic operation
5713 // on two operands in far space (assumed to already have been
5714 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5715 // in far space. This requires pushing the result on the stack
5716 // then popping it into the result.
5718 genFarFarLogicOp(iCode *ic, char *logicOp)
5720 int size, resultSize, compSize;
5724 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5725 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5726 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5728 _startLazyDPSEvaluation();
5729 for (size = compSize; (size--); offset++)
5731 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5732 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5733 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5735 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5736 emitcode ("push", "acc");
5738 _endLazyDPSEvaluation();
5740 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5741 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5742 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5744 resultSize = AOP_SIZE(IC_RESULT(ic));
5746 ADJUST_PUSHED_RESULT(compSize, resultSize);
5748 _startLazyDPSEvaluation();
5751 emitcode ("pop", "acc");
5752 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5754 _endLazyDPSEvaluation();
5755 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5759 /*-----------------------------------------------------------------*/
5760 /* genAnd - code for and */
5761 /*-----------------------------------------------------------------*/
5763 genAnd (iCode * ic, iCode * ifx)
5765 operand *left, *right, *result;
5766 int size, offset = 0;
5767 unsigned long lit = 0L;
5772 D (emitcode (";", "genAnd "););
5774 AOP_OP_3_NOFATAL (ic, pushResult);
5775 AOP_SET_LOCALS (ic);
5779 genFarFarLogicOp(ic, "anl");
5784 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5786 AOP_TYPE (left), AOP_TYPE (right));
5787 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5789 AOP_SIZE (left), AOP_SIZE (right));
5792 /* if left is a literal & right is not then exchange them */
5793 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5794 #ifdef LOGIC_OPS_BROKEN
5795 || AOP_NEEDSACC (left)
5799 operand *tmp = right;
5804 /* if result = right then exchange them */
5805 if (sameRegs (AOP (result), AOP (right)))
5807 operand *tmp = right;
5812 /* if right is bit then exchange them */
5813 if (AOP_TYPE (right) == AOP_CRY &&
5814 AOP_TYPE (left) != AOP_CRY)
5816 operand *tmp = right;
5820 if (AOP_TYPE (right) == AOP_LIT)
5821 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5823 size = AOP_SIZE (result);
5826 // result = bit & yy;
5827 if (AOP_TYPE (left) == AOP_CRY)
5829 // c = bit & literal;
5830 if (AOP_TYPE (right) == AOP_LIT)
5834 if (size && sameRegs (AOP (result), AOP (left)))
5837 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5842 if (size && (AOP_TYPE (result) == AOP_CRY))
5844 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5847 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5852 emitcode ("clr", "c");
5857 if (AOP_TYPE (right) == AOP_CRY)
5860 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5861 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5866 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5868 emitcode ("rrc", "a");
5869 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5877 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5878 genIfxJump (ifx, "c");
5882 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5883 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5884 if ((AOP_TYPE (right) == AOP_LIT) &&
5885 (AOP_TYPE (result) == AOP_CRY) &&
5886 (AOP_TYPE (left) != AOP_CRY))
5888 int posbit = isLiteralBit (lit);
5893 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5896 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5902 sprintf (buffer, "acc.%d", posbit & 0x07);
5903 genIfxJump (ifx, buffer);
5910 symbol *tlbl = newiTempLabel (NULL);
5911 int sizel = AOP_SIZE (left);
5913 emitcode ("setb", "c");
5916 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5918 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5920 if ((posbit = isLiteralBit (bytelit)) != 0)
5921 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5924 if (bytelit != 0x0FFL)
5925 emitcode ("anl", "a,%s",
5926 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5927 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5932 // bit = left & literal
5935 emitcode ("clr", "c");
5936 emitcode ("", "!tlabeldef", tlbl->key + 100);
5938 // if(left & literal)
5942 jmpTrueOrFalse (ifx, tlbl);
5950 /* if left is same as result */
5951 if (sameRegs (AOP (result), AOP (left)))
5953 for (; size--; offset++)
5955 if (AOP_TYPE (right) == AOP_LIT)
5957 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5959 else if (bytelit == 0)
5960 aopPut (AOP (result), zero, offset);
5961 else if (IS_AOP_PREG (result))
5963 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5964 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5965 aopPut (AOP (result), "a", offset);
5968 emitcode ("anl", "%s,%s",
5969 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5970 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5974 if (AOP_TYPE (left) == AOP_ACC)
5975 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5978 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5979 if (IS_AOP_PREG (result))
5981 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5982 aopPut (AOP (result), "a", offset);
5986 emitcode ("anl", "%s,a",
5987 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5994 // left & result in different registers
5995 if (AOP_TYPE (result) == AOP_CRY)
5998 // if(size), result in bit
5999 // if(!size && ifx), conditional oper: if(left & right)
6000 symbol *tlbl = newiTempLabel (NULL);
6001 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6003 emitcode ("setb", "c");
6006 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6007 emitcode ("anl", "a,%s",
6008 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6010 if (AOP_TYPE(left)==AOP_ACC) {
6011 emitcode("mov", "b,a");
6012 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6013 emitcode("anl", "a,b");
6015 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6016 emitcode ("anl", "a,%s",
6017 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6020 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6026 emitcode ("", "!tlabeldef", tlbl->key + 100);
6030 jmpTrueOrFalse (ifx, tlbl);
6034 for (; (size--); offset++)
6037 // result = left & right
6038 if (AOP_TYPE (right) == AOP_LIT)
6040 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6042 aopPut (AOP (result),
6043 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6047 else if (bytelit == 0)
6049 aopPut (AOP (result), zero, offset);
6052 D (emitcode (";", "better literal AND."););
6053 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6054 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6055 FALSE, FALSE, FALSE));
6060 // faster than result <- left, anl result,right
6061 // and better if result is SFR
6062 if (AOP_TYPE (left) == AOP_ACC)
6064 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6065 FALSE, FALSE, FALSE));
6069 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6070 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6072 emitcode("mov", "b,a");
6076 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6077 emitcode ("anl", "a,%s", rOp);
6080 aopPut (AOP (result), "a", offset);
6086 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6087 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6088 freeAsmop (result, NULL, ic, TRUE);
6092 /*-----------------------------------------------------------------*/
6093 /* genOr - code for or */
6094 /*-----------------------------------------------------------------*/
6096 genOr (iCode * ic, iCode * ifx)
6098 operand *left, *right, *result;
6099 int size, offset = 0;
6100 unsigned long lit = 0L;
6103 D (emitcode (";", "genOr "););
6105 AOP_OP_3_NOFATAL (ic, pushResult);
6106 AOP_SET_LOCALS (ic);
6110 genFarFarLogicOp(ic, "orl");
6116 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6118 AOP_TYPE (left), AOP_TYPE (right));
6119 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6121 AOP_SIZE (left), AOP_SIZE (right));
6124 /* if left is a literal & right is not then exchange them */
6125 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6126 #ifdef LOGIC_OPS_BROKEN
6127 || AOP_NEEDSACC (left) // I think this is a net loss now.
6131 operand *tmp = right;
6136 /* if result = right then exchange them */
6137 if (sameRegs (AOP (result), AOP (right)))
6139 operand *tmp = right;
6144 /* if right is bit then exchange them */
6145 if (AOP_TYPE (right) == AOP_CRY &&
6146 AOP_TYPE (left) != AOP_CRY)
6148 operand *tmp = right;
6152 if (AOP_TYPE (right) == AOP_LIT)
6153 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6155 size = AOP_SIZE (result);
6159 if (AOP_TYPE (left) == AOP_CRY)
6161 if (AOP_TYPE (right) == AOP_LIT)
6163 // c = bit & literal;
6166 // lit != 0 => result = 1
6167 if (AOP_TYPE (result) == AOP_CRY)
6170 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6172 continueIfTrue (ifx);
6175 emitcode ("setb", "c");
6179 // lit == 0 => result = left
6180 if (size && sameRegs (AOP (result), AOP (left)))
6182 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6187 if (AOP_TYPE (right) == AOP_CRY)
6190 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6191 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6196 symbol *tlbl = newiTempLabel (NULL);
6197 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6198 emitcode ("setb", "c");
6199 emitcode ("jb", "%s,!tlabel",
6200 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6202 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6203 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6205 jmpTrueOrFalse (ifx, tlbl);
6211 emitcode ("", "!tlabeldef", tlbl->key + 100);
6220 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6221 genIfxJump (ifx, "c");
6225 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6226 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6227 if ((AOP_TYPE (right) == AOP_LIT) &&
6228 (AOP_TYPE (result) == AOP_CRY) &&
6229 (AOP_TYPE (left) != AOP_CRY))
6235 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6237 continueIfTrue (ifx);
6242 // lit = 0, result = boolean(left)
6244 emitcode ("setb", "c");
6248 symbol *tlbl = newiTempLabel (NULL);
6249 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6251 emitcode ("", "!tlabeldef", tlbl->key + 100);
6255 genIfxJump (ifx, "a");
6263 /* if left is same as result */
6264 if (sameRegs (AOP (result), AOP (left)))
6266 for (; size--; offset++)
6268 if (AOP_TYPE (right) == AOP_LIT)
6270 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6276 if (IS_AOP_PREG (left))
6278 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6279 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6280 aopPut (AOP (result), "a", offset);
6284 emitcode ("orl", "%s,%s",
6285 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6286 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6292 if (AOP_TYPE (left) == AOP_ACC)
6294 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6298 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6299 if (IS_AOP_PREG (left))
6301 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6302 aopPut (AOP (result), "a", offset);
6306 emitcode ("orl", "%s,a",
6307 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6315 // left & result in different registers
6316 if (AOP_TYPE (result) == AOP_CRY)
6319 // if(size), result in bit
6320 // if(!size && ifx), conditional oper: if(left | right)
6321 symbol *tlbl = newiTempLabel (NULL);
6322 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6324 emitcode ("setb", "c");
6327 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6328 emitcode ("orl", "a,%s",
6329 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6331 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6332 emitcode ("orl", "a,%s",
6333 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6335 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6341 emitcode ("", "!tlabeldef", tlbl->key + 100);
6345 jmpTrueOrFalse (ifx, tlbl);
6349 _startLazyDPSEvaluation();
6350 for (; (size--); offset++)
6353 // result = left & right
6354 if (AOP_TYPE (right) == AOP_LIT)
6356 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6358 aopPut (AOP (result),
6359 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6363 D (emitcode (";", "better literal OR."););
6364 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6365 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6366 FALSE, FALSE, FALSE));
6371 // faster than result <- left, anl result,right
6372 // and better if result is SFR
6373 if (AOP_TYPE (left) == AOP_ACC)
6375 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6376 FALSE, FALSE, FALSE));
6380 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6382 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6384 emitcode("mov", "b,a");
6388 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6389 emitcode ("orl", "a,%s", rOp);
6392 aopPut (AOP (result), "a", offset);
6394 _endLazyDPSEvaluation();
6399 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6400 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6401 freeAsmop (result, NULL, ic, TRUE);
6404 /*-----------------------------------------------------------------*/
6405 /* genXor - code for xclusive or */
6406 /*-----------------------------------------------------------------*/
6408 genXor (iCode * ic, iCode * ifx)
6410 operand *left, *right, *result;
6411 int size, offset = 0;
6412 unsigned long lit = 0L;
6415 D (emitcode (";", "genXor "););
6417 AOP_OP_3_NOFATAL (ic, pushResult);
6418 AOP_SET_LOCALS (ic);
6422 genFarFarLogicOp(ic, "xrl");
6427 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6429 AOP_TYPE (left), AOP_TYPE (right));
6430 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6432 AOP_SIZE (left), AOP_SIZE (right));
6435 /* if left is a literal & right is not ||
6436 if left needs acc & right does not */
6437 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6438 #ifdef LOGIC_OPS_BROKEN
6439 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6443 operand *tmp = right;
6448 /* if result = right then exchange them */
6449 if (sameRegs (AOP (result), AOP (right)))
6451 operand *tmp = right;
6456 /* if right is bit then exchange them */
6457 if (AOP_TYPE (right) == AOP_CRY &&
6458 AOP_TYPE (left) != AOP_CRY)
6460 operand *tmp = right;
6464 if (AOP_TYPE (right) == AOP_LIT)
6465 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6467 size = AOP_SIZE (result);
6471 if (AOP_TYPE (left) == AOP_CRY)
6473 if (AOP_TYPE (right) == AOP_LIT)
6475 // c = bit & literal;
6478 // lit>>1 != 0 => result = 1
6479 if (AOP_TYPE (result) == AOP_CRY)
6482 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6484 continueIfTrue (ifx);
6487 emitcode ("setb", "c");
6494 // lit == 0, result = left
6495 if (size && sameRegs (AOP (result), AOP (left)))
6497 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6501 // lit == 1, result = not(left)
6502 if (size && sameRegs (AOP (result), AOP (left)))
6504 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6509 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6510 emitcode ("cpl", "c");
6519 symbol *tlbl = newiTempLabel (NULL);
6520 if (AOP_TYPE (right) == AOP_CRY)
6523 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6527 int sizer = AOP_SIZE (right);
6529 // if val>>1 != 0, result = 1
6530 emitcode ("setb", "c");
6533 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6535 // test the msb of the lsb
6536 emitcode ("anl", "a,#!constbyte",0xfe);
6537 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6541 emitcode ("rrc", "a");
6543 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6544 emitcode ("cpl", "c");
6545 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6552 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6553 genIfxJump (ifx, "c");
6557 if (sameRegs (AOP (result), AOP (left)))
6559 /* if left is same as result */
6560 for (; size--; offset++)
6562 if (AOP_TYPE (right) == AOP_LIT)
6564 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6566 else if (IS_AOP_PREG (left))
6568 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6569 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6570 aopPut (AOP (result), "a", offset);
6573 emitcode ("xrl", "%s,%s",
6574 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6575 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6579 if (AOP_TYPE (left) == AOP_ACC)
6580 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6583 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6584 if (IS_AOP_PREG (left))
6586 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6587 aopPut (AOP (result), "a", offset);
6590 emitcode ("xrl", "%s,a",
6591 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6598 // left & result in different registers
6599 if (AOP_TYPE (result) == AOP_CRY)
6602 // if(size), result in bit
6603 // if(!size && ifx), conditional oper: if(left ^ right)
6604 symbol *tlbl = newiTempLabel (NULL);
6605 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6608 emitcode ("setb", "c");
6611 if ((AOP_TYPE (right) == AOP_LIT) &&
6612 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6614 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6618 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6619 emitcode ("xrl", "a,%s",
6620 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6622 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6623 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6625 emitcode("mov", "b,a");
6629 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6630 emitcode ("xrl", "a,%s", rOp);
6633 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6639 emitcode ("", "!tlabeldef", tlbl->key + 100);
6643 jmpTrueOrFalse (ifx, tlbl);
6647 for (; (size--); offset++)
6650 // result = left & right
6651 if (AOP_TYPE (right) == AOP_LIT)
6653 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6655 aopPut (AOP (result),
6656 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6660 D (emitcode (";", "better literal XOR."););
6661 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6662 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6663 FALSE, FALSE, FALSE));
6667 // faster than result <- left, anl result,right
6668 // and better if result is SFR
6669 if (AOP_TYPE (left) == AOP_ACC)
6671 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6672 FALSE, FALSE, FALSE));
6676 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6677 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6679 emitcode("mov", "b,a");
6683 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6684 emitcode ("xrl", "a,%s", rOp);
6687 aopPut (AOP (result), "a", offset);
6694 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6695 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6696 freeAsmop (result, NULL, ic, TRUE);
6699 /*-----------------------------------------------------------------*/
6700 /* genInline - write the inline code out */
6701 /*-----------------------------------------------------------------*/
6703 genInline (iCode * ic)
6705 char *buffer, *bp, *bp1;
6707 D (emitcode (";", "genInline ");
6710 _G.inLine += (!options.asmpeep);
6712 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6713 strcpy (buffer, IC_INLINE (ic));
6715 /* emit each line as a code */
6740 /* emitcode("",buffer); */
6741 _G.inLine -= (!options.asmpeep);
6744 /*-----------------------------------------------------------------*/
6745 /* genRRC - rotate right with carry */
6746 /*-----------------------------------------------------------------*/
6750 operand *left, *result;
6751 int size, offset = 0;
6754 D (emitcode (";", "genRRC ");
6757 /* rotate right with carry */
6758 left = IC_LEFT (ic);
6759 result = IC_RESULT (ic);
6760 aopOp (left, ic, FALSE, FALSE);
6761 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6763 /* move it to the result */
6764 size = AOP_SIZE (result);
6768 _startLazyDPSEvaluation ();
6771 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6773 emitcode ("rrc", "a");
6774 if (AOP_SIZE (result) > 1)
6775 aopPut (AOP (result), "a", offset--);
6777 _endLazyDPSEvaluation ();
6779 /* now we need to put the carry into the
6780 highest order byte of the result */
6781 if (AOP_SIZE (result) > 1)
6783 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6786 emitcode ("mov", "acc.7,c");
6787 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6788 freeAsmop (left, NULL, ic, TRUE);
6789 freeAsmop (result, NULL, ic, TRUE);
6792 /*-----------------------------------------------------------------*/
6793 /* genRLC - generate code for rotate left with carry */
6794 /*-----------------------------------------------------------------*/
6798 operand *left, *result;
6799 int size, offset = 0;
6802 D (emitcode (";", "genRLC ");
6805 /* rotate right with carry */
6806 left = IC_LEFT (ic);
6807 result = IC_RESULT (ic);
6808 aopOp (left, ic, FALSE, FALSE);
6809 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6811 /* move it to the result */
6812 size = AOP_SIZE (result);
6816 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6818 emitcode ("add", "a,acc");
6819 if (AOP_SIZE (result) > 1)
6821 aopPut (AOP (result), "a", offset++);
6824 _startLazyDPSEvaluation ();
6827 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6829 emitcode ("rlc", "a");
6830 if (AOP_SIZE (result) > 1)
6831 aopPut (AOP (result), "a", offset++);
6833 _endLazyDPSEvaluation ();
6835 /* now we need to put the carry into the
6836 highest order byte of the result */
6837 if (AOP_SIZE (result) > 1)
6839 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6842 emitcode ("mov", "acc.0,c");
6843 aopPut (AOP (result), "a", 0);
6844 freeAsmop (left, NULL, ic, TRUE);
6845 freeAsmop (result, NULL, ic, TRUE);
6848 /*-----------------------------------------------------------------*/
6849 /* genGetHbit - generates code get highest order bit */
6850 /*-----------------------------------------------------------------*/
6852 genGetHbit (iCode * ic)
6854 operand *left, *result;
6855 left = IC_LEFT (ic);
6856 result = IC_RESULT (ic);
6857 aopOp (left, ic, FALSE, FALSE);
6858 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6860 D (emitcode (";", "genGetHbit ");
6863 /* get the highest order byte into a */
6864 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6865 if (AOP_TYPE (result) == AOP_CRY)
6867 emitcode ("rlc", "a");
6872 emitcode ("rl", "a");
6873 emitcode ("anl", "a,#1");
6878 freeAsmop (left, NULL, ic, TRUE);
6879 freeAsmop (result, NULL, ic, TRUE);
6882 /*-----------------------------------------------------------------*/
6883 /* AccRol - rotate left accumulator by known count */
6884 /*-----------------------------------------------------------------*/
6886 AccRol (int shCount)
6888 shCount &= 0x0007; // shCount : 0..7
6895 emitcode ("rl", "a");
6898 emitcode ("rl", "a");
6899 emitcode ("rl", "a");
6902 emitcode ("swap", "a");
6903 emitcode ("rr", "a");
6906 emitcode ("swap", "a");
6909 emitcode ("swap", "a");
6910 emitcode ("rl", "a");
6913 emitcode ("rr", "a");
6914 emitcode ("rr", "a");
6917 emitcode ("rr", "a");
6922 /*-----------------------------------------------------------------*/
6923 /* AccLsh - left shift accumulator by known count */
6924 /*-----------------------------------------------------------------*/
6926 AccLsh (int shCount)
6931 emitcode ("add", "a,acc");
6932 else if (shCount == 2)
6934 emitcode ("add", "a,acc");
6935 emitcode ("add", "a,acc");
6939 /* rotate left accumulator */
6941 /* and kill the lower order bits */
6942 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
6947 /*-----------------------------------------------------------------*/
6948 /* AccRsh - right shift accumulator by known count */
6949 /*-----------------------------------------------------------------*/
6951 AccRsh (int shCount)
6958 emitcode ("rrc", "a");
6962 /* rotate right accumulator */
6963 AccRol (8 - shCount);
6964 /* and kill the higher order bits */
6965 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6970 #ifdef BETTER_LITERAL_SHIFT
6971 /*-----------------------------------------------------------------*/
6972 /* AccSRsh - signed right shift accumulator by known count */
6973 /*-----------------------------------------------------------------*/
6975 AccSRsh (int shCount)
6982 emitcode ("mov", "c,acc.7");
6983 emitcode ("rrc", "a");
6985 else if (shCount == 2)
6987 emitcode ("mov", "c,acc.7");
6988 emitcode ("rrc", "a");
6989 emitcode ("mov", "c,acc.7");
6990 emitcode ("rrc", "a");
6994 tlbl = newiTempLabel (NULL);
6995 /* rotate right accumulator */
6996 AccRol (8 - shCount);
6997 /* and kill the higher order bits */
6998 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6999 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7000 emitcode ("orl", "a,#!constbyte",
7001 (unsigned char) ~SRMask[shCount]);
7002 emitcode ("", "!tlabeldef", tlbl->key + 100);
7008 #ifdef BETTER_LITERAL_SHIFT
7009 /*-----------------------------------------------------------------*/
7010 /* shiftR1Left2Result - shift right one byte from left to result */
7011 /*-----------------------------------------------------------------*/
7013 shiftR1Left2Result (operand * left, int offl,
7014 operand * result, int offr,
7015 int shCount, int sign)
7017 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7018 /* shift right accumulator */
7023 aopPut (AOP (result), "a", offr);
7027 #ifdef BETTER_LITERAL_SHIFT
7028 /*-----------------------------------------------------------------*/
7029 /* shiftL1Left2Result - shift left one byte from left to result */
7030 /*-----------------------------------------------------------------*/
7032 shiftL1Left2Result (operand * left, int offl,
7033 operand * result, int offr, int shCount)
7035 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7036 /* shift left accumulator */
7038 aopPut (AOP (result), "a", offr);
7042 #ifdef BETTER_LITERAL_SHIFT
7043 /*-----------------------------------------------------------------*/
7044 /* movLeft2Result - move byte from left to result */
7045 /*-----------------------------------------------------------------*/
7047 movLeft2Result (operand * left, int offl,
7048 operand * result, int offr, int sign)
7051 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7053 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7055 if (*l == '@' && (IS_AOP_PREG (result)))
7057 emitcode ("mov", "a,%s", l);
7058 aopPut (AOP (result), "a", offr);
7064 aopPut (AOP (result), l, offr);
7068 /* MSB sign in acc.7 ! */
7069 if (getDataSize (left) == offl + 1)
7071 emitcode ("mov", "a,%s", l);
7072 aopPut (AOP (result), "a", offr);
7080 #ifdef BETTER_LITERAL_SHIFT
7081 /*-----------------------------------------------------------------*/
7082 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7083 /*-----------------------------------------------------------------*/
7087 emitcode ("rrc", "a");
7088 emitcode ("xch", "a,%s", x);
7089 emitcode ("rrc", "a");
7090 emitcode ("xch", "a,%s", x);
7094 #ifdef BETTER_LITERAL_SHIFT
7096 /*-----------------------------------------------------------------*/
7097 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7098 /*-----------------------------------------------------------------*/
7102 emitcode ("xch", "a,%s", x);
7103 emitcode ("rlc", "a");
7104 emitcode ("xch", "a,%s", x);
7105 emitcode ("rlc", "a");
7109 #ifdef BETTER_LITERAL_SHIFT
7110 /*-----------------------------------------------------------------*/
7111 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7112 /*-----------------------------------------------------------------*/
7116 emitcode ("xch", "a,%s", x);
7117 emitcode ("add", "a,acc");
7118 emitcode ("xch", "a,%s", x);
7119 emitcode ("rlc", "a");
7123 #ifdef BETTER_LITERAL_SHIFT
7124 /*-----------------------------------------------------------------*/
7125 /* AccAXLsh - left shift a:x by known count (0..7) */
7126 /*-----------------------------------------------------------------*/
7128 AccAXLsh (char *x, int shCount)
7143 case 5: // AAAAABBB:CCCCCDDD
7145 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7147 emitcode ("anl", "a,#!constbyte",
7148 SLMask[shCount]); // BBB00000:CCCCCDDD
7150 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7152 AccRol (shCount); // DDDCCCCC:BBB00000
7154 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7156 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7158 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7160 emitcode ("anl", "a,#!constbyte",
7161 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7163 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7165 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7168 case 6: // AAAAAABB:CCCCCCDD
7169 emitcode ("anl", "a,#!constbyte",
7170 SRMask[shCount]); // 000000BB:CCCCCCDD
7171 emitcode ("mov", "c,acc.0"); // c = B
7172 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7174 AccAXRrl1 (x); // BCCCCCCD:D000000B
7175 AccAXRrl1 (x); // BBCCCCCC:DD000000
7177 emitcode("rrc","a");
7178 emitcode("xch","a,%s", x);
7179 emitcode("rrc","a");
7180 emitcode("mov","c,acc.0"); //<< get correct bit
7181 emitcode("xch","a,%s", x);
7183 emitcode("rrc","a");
7184 emitcode("xch","a,%s", x);
7185 emitcode("rrc","a");
7186 emitcode("xch","a,%s", x);
7189 case 7: // a:x <<= 7
7191 emitcode ("anl", "a,#!constbyte",
7192 SRMask[shCount]); // 0000000B:CCCCCCCD
7194 emitcode ("mov", "c,acc.0"); // c = B
7196 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7198 AccAXRrl1 (x); // BCCCCCCC:D0000000
7207 #ifdef BETTER_LITERAL_SHIFT
7209 /*-----------------------------------------------------------------*/
7210 /* AccAXRsh - right shift a:x known count (0..7) */
7211 /*-----------------------------------------------------------------*/
7213 AccAXRsh (char *x, int shCount)
7221 AccAXRrl1 (x); // 0->a:x
7226 AccAXRrl1 (x); // 0->a:x
7229 AccAXRrl1 (x); // 0->a:x
7234 case 5: // AAAAABBB:CCCCCDDD = a:x
7236 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7238 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7240 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7242 emitcode ("anl", "a,#!constbyte",
7243 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7245 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7247 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7249 emitcode ("anl", "a,#!constbyte",
7250 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7252 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7254 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7256 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7259 case 6: // AABBBBBB:CCDDDDDD
7261 emitcode ("mov", "c,acc.7");
7262 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7264 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7266 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7268 emitcode ("anl", "a,#!constbyte",
7269 SRMask[shCount]); // 000000AA:BBBBBBCC
7272 case 7: // ABBBBBBB:CDDDDDDD
7274 emitcode ("mov", "c,acc.7"); // c = A
7276 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7278 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7280 emitcode ("anl", "a,#!constbyte",
7281 SRMask[shCount]); // 0000000A:BBBBBBBC
7290 #ifdef BETTER_LITERAL_SHIFT
7291 /*-----------------------------------------------------------------*/
7292 /* AccAXRshS - right shift signed a:x known count (0..7) */
7293 /*-----------------------------------------------------------------*/
7295 AccAXRshS (char *x, int shCount)
7303 emitcode ("mov", "c,acc.7");
7304 AccAXRrl1 (x); // s->a:x
7308 emitcode ("mov", "c,acc.7");
7309 AccAXRrl1 (x); // s->a:x
7311 emitcode ("mov", "c,acc.7");
7312 AccAXRrl1 (x); // s->a:x
7317 case 5: // AAAAABBB:CCCCCDDD = a:x
7319 tlbl = newiTempLabel (NULL);
7320 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7322 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7324 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7326 emitcode ("anl", "a,#!constbyte",
7327 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7329 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7331 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7333 emitcode ("anl", "a,#!constbyte",
7334 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7336 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7338 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7340 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7342 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7343 emitcode ("orl", "a,#!constbyte",
7344 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7346 emitcode ("", "!tlabeldef", tlbl->key + 100);
7347 break; // SSSSAAAA:BBBCCCCC
7349 case 6: // AABBBBBB:CCDDDDDD
7351 tlbl = newiTempLabel (NULL);
7352 emitcode ("mov", "c,acc.7");
7353 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7355 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7357 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7359 emitcode ("anl", "a,#!constbyte",
7360 SRMask[shCount]); // 000000AA:BBBBBBCC
7362 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7363 emitcode ("orl", "a,#!constbyte",
7364 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7366 emitcode ("", "!tlabeldef", tlbl->key + 100);
7368 case 7: // ABBBBBBB:CDDDDDDD
7370 tlbl = newiTempLabel (NULL);
7371 emitcode ("mov", "c,acc.7"); // c = A
7373 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7375 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7377 emitcode ("anl", "a,#!constbyte",
7378 SRMask[shCount]); // 0000000A:BBBBBBBC
7380 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7381 emitcode ("orl", "a,#!constbyte",
7382 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7384 emitcode ("", "!tlabeldef", tlbl->key + 100);
7392 #ifdef BETTER_LITERAL_SHIFT
7394 _loadLeftIntoAx(char **lsb,
7400 // Get the initial value from left into a pair of registers.
7401 // MSB must be in A, LSB can be any register.
7403 // If the result is held in registers, it is an optimization
7404 // if the LSB can be held in the register which will hold the,
7405 // result LSB since this saves us from having to copy it into
7406 // the result following AccAXLsh.
7408 // If the result is addressed indirectly, this is not a gain.
7409 if (AOP_NEEDSACC(result))
7413 _startLazyDPSEvaluation();
7414 if (AOP_TYPE(left) == AOP_DPTR2)
7417 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7418 // get LSB in DP2_RESULT_REG.
7419 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7420 assert(!strcmp(leftByte, DP2_RESULT_REG));
7424 // get LSB into DP2_RESULT_REG
7425 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7426 if (strcmp(leftByte, DP2_RESULT_REG))
7429 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7432 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7433 assert(strcmp(leftByte, DP2_RESULT_REG));
7436 _endLazyDPSEvaluation();
7437 *lsb = DP2_RESULT_REG;
7441 if (sameRegs (AOP (result), AOP (left)) &&
7442 ((offl + MSB16) == offr))
7444 /* don't crash result[offr] */
7445 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7446 emitcode ("xch", "a,%s",
7447 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7451 movLeft2Result (left, offl, result, offr, 0);
7452 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7454 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7455 assert(strcmp(*lsb,"a"));
7460 _storeAxResults(char *lsb,
7464 _startLazyDPSEvaluation();
7465 if (AOP_NEEDSACC(result))
7467 /* We have to explicitly update the result LSB.
7469 emitcode("xch","a,%s", lsb);
7470 aopPut(AOP(result), "a", offr);
7471 emitcode("mov","a,%s", lsb);
7473 if (getDataSize (result) > 1)
7475 aopPut (AOP (result), "a", offr + MSB16);
7477 _endLazyDPSEvaluation();
7480 /*-----------------------------------------------------------------*/
7481 /* shiftL2Left2Result - shift left two bytes from left to result */
7482 /*-----------------------------------------------------------------*/
7484 shiftL2Left2Result (operand * left, int offl,
7485 operand * result, int offr, int shCount)
7489 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7491 AccAXLsh (lsb, shCount);
7493 _storeAxResults(lsb, result, offr);
7497 #ifdef BETTER_LITERAL_SHIFT
7498 /*-----------------------------------------------------------------*/
7499 /* shiftR2Left2Result - shift right two bytes from left to result */
7500 /*-----------------------------------------------------------------*/
7502 shiftR2Left2Result (operand * left, int offl,
7503 operand * result, int offr,
7504 int shCount, int sign)
7508 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7510 /* a:x >> shCount (x = lsb(result)) */
7513 AccAXRshS(lsb, shCount);
7517 AccAXRsh(lsb, shCount);
7520 _storeAxResults(lsb, result, offr);
7526 /*-----------------------------------------------------------------*/
7527 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7528 /*-----------------------------------------------------------------*/
7530 shiftLLeftOrResult (operand * left, int offl,
7531 operand * result, int offr, int shCount)
7533 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7534 /* shift left accumulator */
7536 /* or with result */
7537 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7538 /* back to result */
7539 aopPut (AOP (result), "a", offr);
7545 /*-----------------------------------------------------------------*/
7546 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7547 /*-----------------------------------------------------------------*/
7549 shiftRLeftOrResult (operand * left, int offl,
7550 operand * result, int offr, int shCount)
7552 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7553 /* shift right accumulator */
7555 /* or with result */
7556 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7557 /* back to result */
7558 aopPut (AOP (result), "a", offr);
7562 #ifdef BETTER_LITERAL_SHIFT
7563 /*-----------------------------------------------------------------*/
7564 /* genlshOne - left shift a one byte quantity by known count */
7565 /*-----------------------------------------------------------------*/
7567 genlshOne (operand * result, operand * left, int shCount)
7569 D (emitcode (";", "genlshOne "););
7570 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7574 #ifdef BETTER_LITERAL_SHIFT
7575 /*-----------------------------------------------------------------*/
7576 /* genlshTwo - left shift two bytes by known amount != 0 */
7577 /*-----------------------------------------------------------------*/
7579 genlshTwo (operand * result, operand * left, int shCount)
7583 D (emitcode (";", "genlshTwo "););
7585 size = getDataSize (result);
7587 /* if shCount >= 8 */
7592 _startLazyDPSEvaluation();
7598 _endLazyDPSEvaluation();
7599 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7600 aopPut (AOP (result), zero, LSB);
7604 movLeft2Result (left, LSB, result, MSB16, 0);
7605 aopPut (AOP (result), zero, LSB);
7606 _endLazyDPSEvaluation();
7611 aopPut (AOP (result), zero, LSB);
7612 _endLazyDPSEvaluation();
7616 /* 1 <= shCount <= 7 */
7621 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7625 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7633 /*-----------------------------------------------------------------*/
7634 /* shiftLLong - shift left one long from left to result */
7635 /* offl = LSB or MSB16 */
7636 /*-----------------------------------------------------------------*/
7638 shiftLLong (operand * left, operand * result, int offr)
7641 int size = AOP_SIZE (result);
7643 if (size >= LSB + offr)
7645 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7647 emitcode ("add", "a,acc");
7648 if (sameRegs (AOP (left), AOP (result)) &&
7649 size >= MSB16 + offr && offr != LSB)
7650 emitcode ("xch", "a,%s",
7651 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7653 aopPut (AOP (result), "a", LSB + offr);
7656 if (size >= MSB16 + offr)
7658 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7660 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7663 emitcode ("rlc", "a");
7664 if (sameRegs (AOP (left), AOP (result)) &&
7665 size >= MSB24 + offr && offr != LSB)
7666 emitcode ("xch", "a,%s",
7667 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7669 aopPut (AOP (result), "a", MSB16 + offr);
7672 if (size >= MSB24 + offr)
7674 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7676 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7679 emitcode ("rlc", "a");
7680 if (sameRegs (AOP (left), AOP (result)) &&
7681 size >= MSB32 + offr && offr != LSB)
7682 emitcode ("xch", "a,%s",
7683 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7685 aopPut (AOP (result), "a", MSB24 + offr);
7688 if (size > MSB32 + offr)
7690 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7692 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7695 emitcode ("rlc", "a");
7696 aopPut (AOP (result), "a", MSB32 + offr);
7699 aopPut (AOP (result), zero, LSB);
7705 /*-----------------------------------------------------------------*/
7706 /* genlshFour - shift four byte by a known amount != 0 */
7707 /*-----------------------------------------------------------------*/
7709 genlshFour (operand * result, operand * left, int shCount)
7713 D (emitcode (";", "genlshFour ");
7716 size = AOP_SIZE (result);
7718 /* if shifting more that 3 bytes */
7723 /* lowest order of left goes to the highest
7724 order of the destination */
7725 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7727 movLeft2Result (left, LSB, result, MSB32, 0);
7728 aopPut (AOP (result), zero, LSB);
7729 aopPut (AOP (result), zero, MSB16);
7730 aopPut (AOP (result), zero, MSB24);
7734 /* more than two bytes */
7735 else if (shCount >= 16)
7737 /* lower order two bytes goes to higher order two bytes */
7739 /* if some more remaining */
7741 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7744 movLeft2Result (left, MSB16, result, MSB32, 0);
7745 movLeft2Result (left, LSB, result, MSB24, 0);
7747 aopPut (AOP (result), zero, MSB16);
7748 aopPut (AOP (result), zero, LSB);
7752 /* if more than 1 byte */
7753 else if (shCount >= 8)
7755 /* lower order three bytes goes to higher order three bytes */
7760 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7762 movLeft2Result (left, LSB, result, MSB16, 0);
7768 movLeft2Result (left, MSB24, result, MSB32, 0);
7769 movLeft2Result (left, MSB16, result, MSB24, 0);
7770 movLeft2Result (left, LSB, result, MSB16, 0);
7771 aopPut (AOP (result), zero, LSB);
7773 else if (shCount == 1)
7774 shiftLLong (left, result, MSB16);
7777 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7778 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7779 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7780 aopPut (AOP (result), zero, LSB);
7785 /* 1 <= shCount <= 7 */
7786 else if (shCount <= 2)
7788 shiftLLong (left, result, LSB);
7790 shiftLLong (result, result, LSB);
7792 /* 3 <= shCount <= 7, optimize */
7795 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7796 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7797 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7802 #ifdef BETTER_LITERAL_SHIFT
7803 /*-----------------------------------------------------------------*/
7804 /* genLeftShiftLiteral - left shifting by known count */
7805 /*-----------------------------------------------------------------*/
7807 genLeftShiftLiteral (operand * left,
7812 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7815 size = getSize (operandType (result));
7817 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7819 /* We only handle certain easy cases so far. */
7821 && (shCount < (size * 8))
7825 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7829 freeAsmop (right, NULL, ic, TRUE);
7831 aopOp(left, ic, FALSE, FALSE);
7832 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7835 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7837 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7838 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7840 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7843 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7845 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7846 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7848 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7854 emitcode ("; shift left ", "result %d, left %d", size,
7858 /* I suppose that the left size >= result size */
7861 _startLazyDPSEvaluation();
7864 movLeft2Result (left, size, result, size, 0);
7866 _endLazyDPSEvaluation();
7868 else if (shCount >= (size * 8))
7870 _startLazyDPSEvaluation();
7873 aopPut (AOP (result), zero, size);
7875 _endLazyDPSEvaluation();
7882 genlshOne (result, left, shCount);
7886 genlshTwo (result, left, shCount);
7890 genlshFour (result, left, shCount);
7894 fprintf(stderr, "*** ack! mystery literal shift!\n");
7898 freeAsmop (left, NULL, ic, TRUE);
7899 freeAsmop (result, NULL, ic, TRUE);
7904 /*-----------------------------------------------------------------*/
7905 /* genLeftShift - generates code for left shifting */
7906 /*-----------------------------------------------------------------*/
7908 genLeftShift (iCode * ic)
7910 operand *left, *right, *result;
7913 symbol *tlbl, *tlbl1;
7915 D (emitcode (";", "genLeftShift "););
7917 right = IC_RIGHT (ic);
7918 left = IC_LEFT (ic);
7919 result = IC_RESULT (ic);
7921 aopOp (right, ic, FALSE, FALSE);
7924 #ifdef BETTER_LITERAL_SHIFT
7925 /* if the shift count is known then do it
7926 as efficiently as possible */
7927 if (AOP_TYPE (right) == AOP_LIT)
7929 if (genLeftShiftLiteral (left, right, result, ic))
7936 /* shift count is unknown then we have to form
7937 a loop get the loop count in B : Note: we take
7938 only the lower order byte since shifting
7939 more that 32 bits make no sense anyway, ( the
7940 largest size of an object can be only 32 bits ) */
7942 if (AOP_TYPE (right) == AOP_LIT)
7944 /* Really should be handled by genLeftShiftLiteral,
7945 * but since I'm too lazy to fix that today, at least we can make
7946 * some small improvement.
7948 emitcode("mov", "b,#!constbyte",
7949 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7953 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7954 emitcode ("inc", "b");
7956 freeAsmop (right, NULL, ic, TRUE);
7957 aopOp (left, ic, FALSE, FALSE);
7958 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7960 /* now move the left to the result if they are not the
7962 if (!sameRegs (AOP (left), AOP (result)) &&
7963 AOP_SIZE (result) > 1)
7966 size = AOP_SIZE (result);
7968 _startLazyDPSEvaluation ();
7971 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7972 if (*l == '@' && (IS_AOP_PREG (result)))
7975 emitcode ("mov", "a,%s", l);
7976 aopPut (AOP (result), "a", offset);
7979 aopPut (AOP (result), l, offset);
7982 _endLazyDPSEvaluation ();
7985 tlbl = newiTempLabel (NULL);
7986 size = AOP_SIZE (result);
7988 tlbl1 = newiTempLabel (NULL);
7990 /* if it is only one byte then */
7993 symbol *tlbl1 = newiTempLabel (NULL);
7995 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7997 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
7998 emitcode ("", "!tlabeldef", tlbl->key + 100);
7999 emitcode ("add", "a,acc");
8000 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8001 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8002 aopPut (AOP (result), "a", 0);
8006 reAdjustPreg (AOP (result));
8008 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8009 emitcode ("", "!tlabeldef", tlbl->key + 100);
8010 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8012 emitcode ("add", "a,acc");
8013 aopPut (AOP (result), "a", offset++);
8014 _startLazyDPSEvaluation ();
8017 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8019 emitcode ("rlc", "a");
8020 aopPut (AOP (result), "a", offset++);
8022 _endLazyDPSEvaluation ();
8023 reAdjustPreg (AOP (result));
8025 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8026 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8028 freeAsmop (left, NULL, ic, TRUE);
8029 freeAsmop (result, NULL, ic, TRUE);
8032 #ifdef BETTER_LITERAL_SHIFT
8033 /*-----------------------------------------------------------------*/
8034 /* genrshOne - right shift a one byte quantity by known count */
8035 /*-----------------------------------------------------------------*/
8037 genrshOne (operand * result, operand * left,
8038 int shCount, int sign)
8040 D (emitcode (";", "genrshOne"););
8041 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8045 #ifdef BETTER_LITERAL_SHIFT
8046 /*-----------------------------------------------------------------*/
8047 /* genrshTwo - right shift two bytes by known amount != 0 */
8048 /*-----------------------------------------------------------------*/
8050 genrshTwo (operand * result, operand * left,
8051 int shCount, int sign)
8053 D (emitcode (";", "genrshTwo"););
8055 /* if shCount >= 8 */
8059 _startLazyDPSEvaluation();
8062 shiftR1Left2Result (left, MSB16, result, LSB,
8067 movLeft2Result (left, MSB16, result, LSB, sign);
8069 addSign (result, MSB16, sign);
8070 _endLazyDPSEvaluation();
8073 /* 1 <= shCount <= 7 */
8076 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8083 /*-----------------------------------------------------------------*/
8084 /* shiftRLong - shift right one long from left to result */
8085 /* offl = LSB or MSB16 */
8086 /*-----------------------------------------------------------------*/
8088 shiftRLong (operand * left, int offl,
8089 operand * result, int sign)
8091 int isSameRegs=sameRegs(AOP(left),AOP(result));
8093 if (isSameRegs && offl>1) {
8094 // we are in big trouble, but this shouldn't happen
8095 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8098 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8103 emitcode ("rlc", "a");
8104 emitcode ("subb", "a,acc");
8105 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8107 aopPut (AOP(result), zero, MSB32);
8112 emitcode ("clr", "c");
8114 emitcode ("mov", "c,acc.7");
8117 emitcode ("rrc", "a");
8119 if (isSameRegs && offl==MSB16) {
8120 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8122 aopPut (AOP (result), "a", MSB32);
8123 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8126 emitcode ("rrc", "a");
8127 if (isSameRegs && offl==1) {
8128 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8130 aopPut (AOP (result), "a", MSB24);
8131 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8133 emitcode ("rrc", "a");
8134 aopPut (AOP (result), "a", MSB16 - offl);
8138 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8139 emitcode ("rrc", "a");
8140 aopPut (AOP (result), "a", LSB);
8147 /*-----------------------------------------------------------------*/
8148 /* genrshFour - shift four byte by a known amount != 0 */
8149 /*-----------------------------------------------------------------*/
8151 genrshFour (operand * result, operand * left,
8152 int shCount, int sign)
8154 D (emitcode (";", "genrshFour");
8157 /* if shifting more that 3 bytes */
8162 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8164 movLeft2Result (left, MSB32, result, LSB, sign);
8165 addSign (result, MSB16, sign);
8167 else if (shCount >= 16)
8171 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8174 movLeft2Result (left, MSB24, result, LSB, 0);
8175 movLeft2Result (left, MSB32, result, MSB16, sign);
8177 addSign (result, MSB24, sign);
8179 else if (shCount >= 8)
8183 shiftRLong (left, MSB16, result, sign);
8184 else if (shCount == 0)
8186 movLeft2Result (left, MSB16, result, LSB, 0);
8187 movLeft2Result (left, MSB24, result, MSB16, 0);
8188 movLeft2Result (left, MSB32, result, MSB24, sign);
8189 addSign (result, MSB32, sign);
8193 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8194 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8195 /* the last shift is signed */
8196 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8197 addSign (result, MSB32, sign);
8201 { /* 1 <= shCount <= 7 */
8204 shiftRLong (left, LSB, result, sign);
8206 shiftRLong (result, LSB, result, sign);
8210 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8211 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8212 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8218 #ifdef BETTER_LITERAL_SHIFT
8219 /*-----------------------------------------------------------------*/
8220 /* genRightShiftLiteral - right shifting by known count */
8221 /*-----------------------------------------------------------------*/
8223 genRightShiftLiteral (operand * left,
8229 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8232 size = getSize (operandType (result));
8234 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8236 /* We only handle certain easy cases so far. */
8238 && (shCount < (size * 8))
8242 D(emitcode (";", "genRightShiftLiteral wimping out"););
8246 freeAsmop (right, NULL, ic, TRUE);
8248 aopOp (left, ic, FALSE, FALSE);
8249 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8252 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8256 /* test the LEFT size !!! */
8258 /* I suppose that the left size >= result size */
8261 size = getDataSize (result);
8262 _startLazyDPSEvaluation();
8265 movLeft2Result (left, size, result, size, 0);
8267 _endLazyDPSEvaluation();
8269 else if (shCount >= (size * 8))
8273 /* get sign in acc.7 */
8274 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8276 addSign (result, LSB, sign);
8283 genrshOne (result, left, shCount, sign);
8287 genrshTwo (result, left, shCount, sign);
8291 genrshFour (result, left, shCount, sign);
8298 freeAsmop (left, NULL, ic, TRUE);
8299 freeAsmop (result, NULL, ic, TRUE);
8305 /*-----------------------------------------------------------------*/
8306 /* genSignedRightShift - right shift of signed number */
8307 /*-----------------------------------------------------------------*/
8309 genSignedRightShift (iCode * ic)
8311 operand *right, *left, *result;
8314 symbol *tlbl, *tlbl1;
8316 D (emitcode (";", "genSignedRightShift "););
8318 /* we do it the hard way put the shift count in b
8319 and loop thru preserving the sign */
8321 right = IC_RIGHT (ic);
8322 left = IC_LEFT (ic);
8323 result = IC_RESULT (ic);
8325 aopOp (right, ic, FALSE, FALSE);
8327 #ifdef BETTER_LITERAL_SHIFT
8328 if (AOP_TYPE (right) == AOP_LIT)
8330 if (genRightShiftLiteral (left, right, result, ic, 1))
8336 /* shift count is unknown then we have to form
8337 a loop get the loop count in B : Note: we take
8338 only the lower order byte since shifting
8339 more that 32 bits make no sense anyway, ( the
8340 largest size of an object can be only 32 bits ) */
8342 if (AOP_TYPE (right) == AOP_LIT)
8344 /* Really should be handled by genRightShiftLiteral,
8345 * but since I'm too lazy to fix that today, at least we can make
8346 * some small improvement.
8348 emitcode("mov", "b,#!constbyte",
8349 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8353 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8354 emitcode ("inc", "b");
8356 freeAsmop (right, NULL, ic, TRUE);
8357 aopOp (left, ic, FALSE, FALSE);
8358 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8360 /* now move the left to the result if they are not the
8362 if (!sameRegs (AOP (left), AOP (result)) &&
8363 AOP_SIZE (result) > 1)
8366 size = AOP_SIZE (result);
8368 _startLazyDPSEvaluation ();
8371 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8372 if (*l == '@' && IS_AOP_PREG (result))
8375 emitcode ("mov", "a,%s", l);
8376 aopPut (AOP (result), "a", offset);
8379 aopPut (AOP (result), l, offset);
8382 _endLazyDPSEvaluation ();
8385 /* mov the highest order bit to OVR */
8386 tlbl = newiTempLabel (NULL);
8387 tlbl1 = newiTempLabel (NULL);
8389 size = AOP_SIZE (result);
8391 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8392 emitcode ("rlc", "a");
8393 emitcode ("mov", "ov,c");
8394 /* if it is only one byte then */
8397 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8399 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8400 emitcode ("", "!tlabeldef", tlbl->key + 100);
8401 emitcode ("mov", "c,ov");
8402 emitcode ("rrc", "a");
8403 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8404 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8405 aopPut (AOP (result), "a", 0);
8409 reAdjustPreg (AOP (result));
8410 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8411 emitcode ("", "!tlabeldef", tlbl->key + 100);
8412 emitcode ("mov", "c,ov");
8413 _startLazyDPSEvaluation ();
8416 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8418 emitcode ("rrc", "a");
8419 aopPut (AOP (result), "a", offset--);
8421 _endLazyDPSEvaluation ();
8422 reAdjustPreg (AOP (result));
8423 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8424 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8427 freeAsmop (left, NULL, ic, TRUE);
8428 freeAsmop (result, NULL, ic, TRUE);
8431 /*-----------------------------------------------------------------*/
8432 /* genRightShift - generate code for right shifting */
8433 /*-----------------------------------------------------------------*/
8435 genRightShift (iCode * ic)
8437 operand *right, *left, *result;
8441 symbol *tlbl, *tlbl1;
8443 D (emitcode (";", "genRightShift "););
8445 /* if signed then we do it the hard way preserve the
8446 sign bit moving it inwards */
8447 retype = getSpec (operandType (IC_RESULT (ic)));
8449 if (!SPEC_USIGN (retype))
8451 genSignedRightShift (ic);
8455 /* signed & unsigned types are treated the same : i.e. the
8456 signed is NOT propagated inwards : quoting from the
8457 ANSI - standard : "for E1 >> E2, is equivalent to division
8458 by 2**E2 if unsigned or if it has a non-negative value,
8459 otherwise the result is implementation defined ", MY definition
8460 is that the sign does not get propagated */
8462 right = IC_RIGHT (ic);
8463 left = IC_LEFT (ic);
8464 result = IC_RESULT (ic);
8466 aopOp (right, ic, FALSE, FALSE);
8468 #ifdef BETTER_LITERAL_SHIFT
8469 /* if the shift count is known then do it
8470 as efficiently as possible */
8471 if (AOP_TYPE (right) == AOP_LIT)
8473 if (genRightShiftLiteral (left, right, result, ic, 0))
8480 /* shift count is unknown then we have to form
8481 a loop get the loop count in B : Note: we take
8482 only the lower order byte since shifting
8483 more that 32 bits make no sense anyway, ( the
8484 largest size of an object can be only 32 bits ) */
8486 if (AOP_TYPE (right) == AOP_LIT)
8488 /* Really should be handled by genRightShiftLiteral,
8489 * but since I'm too lazy to fix that today, at least we can make
8490 * some small improvement.
8492 emitcode("mov", "b,#!constbyte",
8493 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8497 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8498 emitcode ("inc", "b");
8500 freeAsmop (right, NULL, ic, TRUE);
8501 aopOp (left, ic, FALSE, FALSE);
8502 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8504 /* now move the left to the result if they are not the
8506 if (!sameRegs (AOP (left), AOP (result)) &&
8507 AOP_SIZE (result) > 1)
8510 size = AOP_SIZE (result);
8512 _startLazyDPSEvaluation ();
8515 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8516 if (*l == '@' && IS_AOP_PREG (result))
8519 emitcode ("mov", "a,%s", l);
8520 aopPut (AOP (result), "a", offset);
8523 aopPut (AOP (result), l, offset);
8526 _endLazyDPSEvaluation ();
8529 tlbl = newiTempLabel (NULL);
8530 tlbl1 = newiTempLabel (NULL);
8531 size = AOP_SIZE (result);
8534 /* if it is only one byte then */
8537 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8539 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8540 emitcode ("", "!tlabeldef", tlbl->key + 100);
8542 emitcode ("rrc", "a");
8543 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8544 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8545 aopPut (AOP (result), "a", 0);
8549 reAdjustPreg (AOP (result));
8550 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8551 emitcode ("", "!tlabeldef", tlbl->key + 100);
8553 _startLazyDPSEvaluation ();
8556 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8558 emitcode ("rrc", "a");
8559 aopPut (AOP (result), "a", offset--);
8561 _endLazyDPSEvaluation ();
8562 reAdjustPreg (AOP (result));
8564 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8565 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8568 freeAsmop (left, NULL, ic, TRUE);
8569 freeAsmop (result, NULL, ic, TRUE);
8572 /*-----------------------------------------------------------------*/
8573 /* genUnpackBits - generates code for unpacking bits */
8574 /*-----------------------------------------------------------------*/
8576 genUnpackBits (operand * result, char *rname, int ptype)
8583 D (emitcode (";", "genUnpackBits ");
8586 etype = getSpec (operandType (result));
8588 /* read the first byte */
8594 emitcode ("mov", "a,@%s", rname);
8598 emitcode ("movx", "a,@%s", rname);
8602 emitcode ("movx", "a,@dptr");
8606 emitcode ("clr", "a");
8607 emitcode ("movc", "a,@a+dptr");
8611 emitcode ("lcall", "__gptrget");
8615 /* if we have bitdisplacement then it fits */
8616 /* into this byte completely or if length is */
8617 /* less than a byte */
8618 if ((shCnt = SPEC_BSTR (etype)) ||
8619 (SPEC_BLEN (etype) <= 8))
8622 /* shift right acc */
8625 emitcode ("anl", "a,#!constbyte",
8626 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8627 aopPut (AOP (result), "a", offset);
8631 /* bit field did not fit in a byte */
8632 rlen = SPEC_BLEN (etype) - 8;
8633 aopPut (AOP (result), "a", offset++);
8642 emitcode ("inc", "%s", rname);
8643 emitcode ("mov", "a,@%s", rname);
8647 emitcode ("inc", "%s", rname);
8648 emitcode ("movx", "a,@%s", rname);
8652 emitcode ("inc", "dptr");
8653 emitcode ("movx", "a,@dptr");
8657 emitcode ("clr", "a");
8658 emitcode ("inc", "dptr");
8659 emitcode ("movc", "a,@a+dptr");
8663 emitcode ("inc", "dptr");
8664 emitcode ("lcall", "__gptrget");
8669 /* if we are done */
8673 aopPut (AOP (result), "a", offset++);
8679 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8680 aopPut (AOP (result), "a", offset);
8687 /*-----------------------------------------------------------------*/
8688 /* genDataPointerGet - generates code when ptr offset is known */
8689 /*-----------------------------------------------------------------*/
8691 genDataPointerGet (operand * left,
8697 int size, offset = 0;
8698 aopOp (result, ic, TRUE, FALSE);
8700 /* get the string representation of the name */
8701 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8702 size = AOP_SIZE (result);
8703 _startLazyDPSEvaluation ();
8707 sprintf (buffer, "(%s + %d)", l + 1, offset);
8709 sprintf (buffer, "%s", l + 1);
8710 aopPut (AOP (result), buffer, offset++);
8712 _endLazyDPSEvaluation ();
8714 freeAsmop (left, NULL, ic, TRUE);
8715 freeAsmop (result, NULL, ic, TRUE);
8718 /*-----------------------------------------------------------------*/
8719 /* genNearPointerGet - emitcode for near pointer fetch */
8720 /*-----------------------------------------------------------------*/
8722 genNearPointerGet (operand * left,
8730 sym_link *rtype, *retype, *letype;
8731 sym_link *ltype = operandType (left);
8734 rtype = operandType (result);
8735 retype = getSpec (rtype);
8736 letype = getSpec (ltype);
8738 aopOp (left, ic, FALSE, FALSE);
8740 /* if left is rematerialisable and
8741 result is not bit variable type and
8742 the left is pointer to data space i.e
8743 lower 128 bytes of space */
8744 if (AOP_TYPE (left) == AOP_IMMD &&
8745 !IS_BITVAR (retype) &&
8746 !IS_BITVAR (letype) &&
8747 DCL_TYPE (ltype) == POINTER)
8749 genDataPointerGet (left, result, ic);
8753 /* if the value is already in a pointer register
8754 then don't need anything more */
8755 if (!AOP_INPREG (AOP (left)))
8757 /* otherwise get a free pointer register */
8759 preg = getFreePtr (ic, &aop, FALSE);
8760 emitcode ("mov", "%s,%s",
8762 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8766 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8768 freeAsmop (left, NULL, ic, TRUE);
8769 aopOp (result, ic, FALSE, FALSE);
8771 /* if bitfield then unpack the bits */
8772 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8773 genUnpackBits (result, rname, POINTER);
8776 /* we have can just get the values */
8777 int size = AOP_SIZE (result);
8782 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8785 emitcode ("mov", "a,@%s", rname);
8786 aopPut (AOP (result), "a", offset);
8790 sprintf (buffer, "@%s", rname);
8791 aopPut (AOP (result), buffer, offset);
8795 emitcode ("inc", "%s", rname);
8799 /* now some housekeeping stuff */
8802 /* we had to allocate for this iCode */
8803 if (pi) { /* post increment present */
8804 aopPut(AOP ( left ),rname,0);
8806 freeAsmop (NULL, aop, ic, TRUE);
8810 /* we did not allocate which means left
8811 already in a pointer register, then
8812 if size > 0 && this could be used again
8813 we have to point it back to where it
8815 if (AOP_SIZE (result) > 1 &&
8816 !OP_SYMBOL (left)->remat &&
8817 (OP_SYMBOL (left)->liveTo > ic->seq ||
8821 int size = AOP_SIZE (result) - 1;
8823 emitcode ("dec", "%s", rname);
8828 freeAsmop (result, NULL, ic, TRUE);
8829 if (pi) pi->generated = 1;
8832 /*-----------------------------------------------------------------*/
8833 /* genPagedPointerGet - emitcode for paged pointer fetch */
8834 /*-----------------------------------------------------------------*/
8836 genPagedPointerGet (operand * left,
8844 sym_link *rtype, *retype, *letype;
8846 rtype = operandType (result);
8847 retype = getSpec (rtype);
8848 letype = getSpec (operandType (left));
8849 aopOp (left, ic, FALSE, FALSE);
8851 /* if the value is already in a pointer register
8852 then don't need anything more */
8853 if (!AOP_INPREG (AOP (left)))
8855 /* otherwise get a free pointer register */
8857 preg = getFreePtr (ic, &aop, FALSE);
8858 emitcode ("mov", "%s,%s",
8860 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8864 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8866 freeAsmop (left, NULL, ic, TRUE);
8867 aopOp (result, ic, FALSE, FALSE);
8869 /* if bitfield then unpack the bits */
8870 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8871 genUnpackBits (result, rname, PPOINTER);
8874 /* we have can just get the values */
8875 int size = AOP_SIZE (result);
8881 emitcode ("movx", "a,@%s", rname);
8882 aopPut (AOP (result), "a", offset);
8887 emitcode ("inc", "%s", rname);
8891 /* now some housekeeping stuff */
8894 /* we had to allocate for this iCode */
8895 if (pi) aopPut ( AOP (left), rname, 0);
8896 freeAsmop (NULL, aop, ic, TRUE);
8900 /* we did not allocate which means left
8901 already in a pointer register, then
8902 if size > 0 && this could be used again
8903 we have to point it back to where it
8905 if (AOP_SIZE (result) > 1 &&
8906 !OP_SYMBOL (left)->remat &&
8907 (OP_SYMBOL (left)->liveTo > ic->seq ||
8911 int size = AOP_SIZE (result) - 1;
8913 emitcode ("dec", "%s", rname);
8918 freeAsmop (result, NULL, ic, TRUE);
8919 if (pi) pi->generated = 1;
8922 /*-----------------------------------------------------------------*/
8923 /* genFarPointerGet - gget value from far space */
8924 /*-----------------------------------------------------------------*/
8926 genFarPointerGet (operand * left,
8927 operand * result, iCode * ic, iCode *pi)
8929 int size, offset, dopi=1;
8930 sym_link *retype = getSpec (operandType (result));
8931 sym_link *letype = getSpec (operandType (left));
8932 D (emitcode (";", "genFarPointerGet");
8935 aopOp (left, ic, FALSE, FALSE);
8937 /* if the operand is already in dptr
8938 then we do nothing else we move the value to dptr */
8939 if (AOP_TYPE (left) != AOP_STR)
8941 /* if this is remateriazable */
8942 if (AOP_TYPE (left) == AOP_IMMD)
8944 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8948 /* we need to get it byte by byte */
8949 _startLazyDPSEvaluation ();
8950 if (AOP_TYPE (left) != AOP_DPTR)
8952 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8953 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8954 if (options.model == MODEL_FLAT24)
8955 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8959 /* We need to generate a load to DPTR indirect through DPTR. */
8960 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8962 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8963 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8964 if (options.model == MODEL_FLAT24)
8965 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8966 emitcode ("pop", "dph");
8967 emitcode ("pop", "dpl");
8970 _endLazyDPSEvaluation ();
8973 /* so dptr know contains the address */
8974 aopOp (result, ic, FALSE, TRUE);
8976 /* if bit then unpack */
8977 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8978 genUnpackBits (result, "dptr", FPOINTER);
8981 size = AOP_SIZE (result);
8984 _startLazyDPSEvaluation ();
8991 emitcode ("movx", "a,@dptr");
8992 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
8993 emitcode ("inc", "dptr");
8995 aopPut (AOP (result), "a", offset++);
8997 _endLazyDPSEvaluation ();
8999 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9000 aopPut ( AOP (left), "dpl", 0);
9001 aopPut ( AOP (left), "dph", 1);
9002 if (options.model == MODEL_FLAT24)
9003 aopPut ( AOP (left), "dpx", 2);
9005 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9006 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9008 size = AOP_SIZE (result) - 1;
9009 while (size--) emitcode ("lcall","__decdptr");
9012 freeAsmop (left, NULL, ic, TRUE);
9013 freeAsmop (result, NULL, ic, TRUE);
9016 /*-----------------------------------------------------------------*/
9017 /* emitcodePointerGet - gget value from code space */
9018 /*-----------------------------------------------------------------*/
9020 emitcodePointerGet (operand * left,
9021 operand * result, iCode * ic, iCode *pi)
9023 int size, offset, dopi=1;
9024 sym_link *retype = getSpec (operandType (result));
9026 aopOp (left, ic, FALSE, FALSE);
9028 /* if the operand is already in dptr
9029 then we do nothing else we move the value to dptr */
9030 if (AOP_TYPE (left) != AOP_STR)
9032 /* if this is remateriazable */
9033 if (AOP_TYPE (left) == AOP_IMMD)
9035 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9038 { /* we need to get it byte by byte */
9039 _startLazyDPSEvaluation ();
9040 if (AOP_TYPE (left) != AOP_DPTR)
9042 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9043 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9044 if (options.model == MODEL_FLAT24)
9045 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9049 /* We need to generate a load to DPTR indirect through DPTR. */
9050 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9052 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9053 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9054 if (options.model == MODEL_FLAT24)
9055 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9056 emitcode ("pop", "dph");
9057 emitcode ("pop", "dpl");
9060 _endLazyDPSEvaluation ();
9063 /* so dptr know contains the address */
9064 aopOp (result, ic, FALSE, TRUE);
9066 /* if bit then unpack */
9067 if (IS_BITVAR (retype))
9068 genUnpackBits (result, "dptr", CPOINTER);
9071 size = AOP_SIZE (result);
9074 _startLazyDPSEvaluation ();
9080 emitcode ("clr", "a");
9081 emitcode ("movc", "a,@a+dptr");
9082 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9083 emitcode ("inc", "dptr");
9084 aopPut (AOP (result), "a", offset++);
9086 _endLazyDPSEvaluation ();
9088 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9089 aopPut ( AOP (left), "dpl", 0);
9090 aopPut ( AOP (left), "dph", 1);
9091 if (options.model == MODEL_FLAT24)
9092 aopPut ( AOP (left), "dpx", 2);
9094 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9095 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9097 size = AOP_SIZE (result) - 1;
9098 while (size--) emitcode ("lcall","__decdptr");
9101 freeAsmop (left, NULL, ic, TRUE);
9102 freeAsmop (result, NULL, ic, TRUE);
9105 /*-----------------------------------------------------------------*/
9106 /* genGenPointerGet - gget value from generic pointer space */
9107 /*-----------------------------------------------------------------*/
9109 genGenPointerGet (operand * left,
9110 operand * result, iCode * ic, iCode * pi)
9113 sym_link *retype = getSpec (operandType (result));
9114 sym_link *letype = getSpec (operandType (left));
9116 D (emitcode (";", "genGenPointerGet "); );
9118 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9120 /* if the operand is already in dptr
9121 then we do nothing else we move the value to dptr */
9122 if (AOP_TYPE (left) != AOP_STR)
9124 /* if this is remateriazable */
9125 if (AOP_TYPE (left) == AOP_IMMD)
9127 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9128 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9129 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9131 emitcode ("mov", "b,#%d", pointerCode (retype));
9134 { /* we need to get it byte by byte */
9135 _startLazyDPSEvaluation ();
9136 if (AOP(left)->type==AOP_DPTR2) {
9138 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9141 emitcode ("mov", "dpl,%s", l);
9142 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9145 emitcode ("mov", "dph,%s", l);
9146 if (options.model == MODEL_FLAT24) {
9147 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9150 emitcode ("mov", "dpx,%s", l);
9151 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9153 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9156 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9157 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9158 if (options.model == MODEL_FLAT24) {
9159 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9160 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9162 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9165 _endLazyDPSEvaluation ();
9168 /* so dptr know contains the address */
9169 aopOp (result, ic, FALSE, TRUE);
9171 /* if bit then unpack */
9172 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9173 genUnpackBits (result, "dptr", GPOINTER);
9176 size = AOP_SIZE (result);
9181 emitcode ("lcall", "__gptrget");
9182 aopPut (AOP (result), "a", offset++);
9183 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9184 emitcode ("inc", "dptr");
9188 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9189 aopPut ( AOP (left), "dpl", 0);
9190 aopPut ( AOP (left), "dph", 1);
9191 if (options.model == MODEL_FLAT24) {
9192 aopPut ( AOP (left), "dpx", 2);
9193 aopPut ( AOP (left), "b", 3);
9194 } else aopPut ( AOP (left), "b", 2);
9196 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9197 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9199 size = AOP_SIZE (result) - 1;
9200 while (size--) emitcode ("lcall","__decdptr");
9203 freeAsmop (left, NULL, ic, TRUE);
9204 freeAsmop (result, NULL, ic, TRUE);
9207 /*-----------------------------------------------------------------*/
9208 /* genPointerGet - generate code for pointer get */
9209 /*-----------------------------------------------------------------*/
9211 genPointerGet (iCode * ic, iCode *pi)
9213 operand *left, *result;
9214 sym_link *type, *etype;
9217 D (emitcode (";", "genPointerGet ");
9220 left = IC_LEFT (ic);
9221 result = IC_RESULT (ic);
9223 /* depending on the type of pointer we need to
9224 move it to the correct pointer register */
9225 type = operandType (left);
9226 etype = getSpec (type);
9227 /* if left is of type of pointer then it is simple */
9228 if (IS_PTR (type) && !IS_FUNC (type->next))
9229 p_type = DCL_TYPE (type);
9232 /* we have to go by the storage class */
9233 p_type = PTR_TYPE (SPEC_OCLS (etype));
9235 /* special case when cast remat */
9236 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9237 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9238 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9239 type = type = operandType (left);
9240 p_type = DCL_TYPE (type);
9242 /* now that we have the pointer type we assign
9243 the pointer values */
9249 genNearPointerGet (left, result, ic, pi);
9253 genPagedPointerGet (left, result, ic, pi);
9257 genFarPointerGet (left, result, ic, pi);
9261 emitcodePointerGet (left, result, ic, pi);
9265 genGenPointerGet (left, result, ic, pi);
9271 /*-----------------------------------------------------------------*/
9272 /* genPackBits - generates code for packed bit storage */
9273 /*-----------------------------------------------------------------*/
9275 genPackBits (sym_link * etype,
9277 char *rname, int p_type)
9285 blen = SPEC_BLEN (etype);
9286 bstr = SPEC_BSTR (etype);
9288 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9291 /* if the bit lenth is less than or */
9292 /* it exactly fits a byte then */
9293 if (SPEC_BLEN (etype) <= 8)
9295 shCount = SPEC_BSTR (etype);
9297 /* shift left acc */
9300 if (SPEC_BLEN (etype) < 8)
9301 { /* if smaller than a byte */
9307 emitcode ("mov", "b,a");
9308 emitcode ("mov", "a,@%s", rname);
9312 emitcode ("mov", "b,a");
9313 emitcode ("movx", "a,@dptr");
9317 emitcode ("push", "b");
9318 emitcode ("push", "acc");
9319 emitcode ("lcall", "__gptrget");
9320 emitcode ("pop", "b");
9324 emitcode ("anl", "a,#!constbyte", (unsigned char)
9325 ((unsigned char) (0xFF << (blen + bstr)) |
9326 (unsigned char) (0xFF >> (8 - bstr))));
9327 emitcode ("orl", "a,b");
9328 if (p_type == GPOINTER)
9329 emitcode ("pop", "b");
9336 emitcode ("mov", "@%s,a", rname);
9340 emitcode ("movx", "@dptr,a");
9344 emitcode ("lcall", "__gptrput");
9349 if (SPEC_BLEN (etype) <= 8)
9352 emitcode ("inc", "%s", rname);
9353 rLen = SPEC_BLEN (etype);
9355 /* now generate for lengths greater than one byte */
9359 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9371 emitcode ("mov", "@%s,a", rname);
9374 emitcode ("mov", "@%s,%s", rname, l);
9379 emitcode ("movx", "@dptr,a");
9384 emitcode ("lcall", "__gptrput");
9387 emitcode ("inc", "%s", rname);
9392 /* last last was not complete */
9395 /* save the byte & read byte */
9399 emitcode ("mov", "b,a");
9400 emitcode ("mov", "a,@%s", rname);
9404 emitcode ("mov", "b,a");
9405 emitcode ("movx", "a,@dptr");
9409 emitcode ("push", "b");
9410 emitcode ("push", "acc");
9411 emitcode ("lcall", "__gptrget");
9412 emitcode ("pop", "b");
9416 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9417 emitcode ("orl", "a,b");
9420 if (p_type == GPOINTER)
9421 emitcode ("pop", "b");
9427 emitcode ("mov", "@%s,a", rname);
9431 emitcode ("movx", "@dptr,a");
9435 emitcode ("lcall", "__gptrput");
9439 /*-----------------------------------------------------------------*/
9440 /* genDataPointerSet - remat pointer to data space */
9441 /*-----------------------------------------------------------------*/
9443 genDataPointerSet (operand * right,
9447 int size, offset = 0;
9448 char *l, buffer[256];
9450 aopOp (right, ic, FALSE, FALSE);
9452 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9453 size = AOP_SIZE (right);
9457 sprintf (buffer, "(%s + %d)", l + 1, offset);
9459 sprintf (buffer, "%s", l + 1);
9460 emitcode ("mov", "%s,%s", buffer,
9461 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9464 freeAsmop (right, NULL, ic, TRUE);
9465 freeAsmop (result, NULL, ic, TRUE);
9468 /*-----------------------------------------------------------------*/
9469 /* genNearPointerSet - emitcode for near pointer put */
9470 /*-----------------------------------------------------------------*/
9472 genNearPointerSet (operand * right,
9480 sym_link *retype, *letype;
9481 sym_link *ptype = operandType (result);
9483 retype = getSpec (operandType (right));
9484 letype = getSpec (ptype);
9486 aopOp (result, ic, FALSE, FALSE);
9488 /* if the result is rematerializable &
9489 in data space & not a bit variable */
9490 if (AOP_TYPE (result) == AOP_IMMD &&
9491 DCL_TYPE (ptype) == POINTER &&
9492 !IS_BITVAR (retype) &&
9493 !IS_BITVAR (letype))
9495 genDataPointerSet (right, result, ic);
9499 /* if the value is already in a pointer register
9500 then don't need anything more */
9501 if (!AOP_INPREG (AOP (result)))
9503 /* otherwise get a free pointer register */
9505 preg = getFreePtr (ic, &aop, FALSE);
9506 emitcode ("mov", "%s,%s",
9508 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9512 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9514 aopOp (right, ic, FALSE, FALSE);
9516 /* if bitfield then unpack the bits */
9517 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9518 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9521 /* we have can just get the values */
9522 int size = AOP_SIZE (right);
9527 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9531 emitcode ("mov", "@%s,a", rname);
9534 emitcode ("mov", "@%s,%s", rname, l);
9536 emitcode ("inc", "%s", rname);
9541 /* now some housekeeping stuff */
9544 /* we had to allocate for this iCode */
9545 if (pi) aopPut (AOP (result),rname,0);
9546 freeAsmop (NULL, aop, ic, TRUE);
9550 /* we did not allocate which means left
9551 already in a pointer register, then
9552 if size > 0 && this could be used again
9553 we have to point it back to where it
9555 if (AOP_SIZE (right) > 1 &&
9556 !OP_SYMBOL (result)->remat &&
9557 (OP_SYMBOL (result)->liveTo > ic->seq ||
9561 int size = AOP_SIZE (right) - 1;
9563 emitcode ("dec", "%s", rname);
9568 if (pi) pi->generated = 1;
9569 freeAsmop (result, NULL, ic, TRUE);
9570 freeAsmop (right, NULL, ic, TRUE);
9575 /*-----------------------------------------------------------------*/
9576 /* genPagedPointerSet - emitcode for Paged pointer put */
9577 /*-----------------------------------------------------------------*/
9579 genPagedPointerSet (operand * right,
9587 sym_link *retype, *letype;
9589 retype = getSpec (operandType (right));
9590 letype = getSpec (operandType (result));
9592 aopOp (result, ic, FALSE, FALSE);
9594 /* if the value is already in a pointer register
9595 then don't need anything more */
9596 if (!AOP_INPREG (AOP (result)))
9598 /* otherwise get a free pointer register */
9600 preg = getFreePtr (ic, &aop, FALSE);
9601 emitcode ("mov", "%s,%s",
9603 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9607 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9609 aopOp (right, ic, FALSE, FALSE);
9611 /* if bitfield then unpack the bits */
9612 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9613 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9616 /* we have can just get the values */
9617 int size = AOP_SIZE (right);
9622 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9625 emitcode ("movx", "@%s,a", rname);
9628 emitcode ("inc", "%s", rname);
9634 /* now some housekeeping stuff */
9637 if (pi) aopPut (AOP (result),rname,0);
9638 /* we had to allocate for this iCode */
9639 freeAsmop (NULL, aop, ic, TRUE);
9643 /* we did not allocate which means left
9644 already in a pointer register, then
9645 if size > 0 && this could be used again
9646 we have to point it back to where it
9648 if (AOP_SIZE (right) > 1 &&
9649 !OP_SYMBOL (result)->remat &&
9650 (OP_SYMBOL (result)->liveTo > ic->seq ||
9654 int size = AOP_SIZE (right) - 1;
9656 emitcode ("dec", "%s", rname);
9661 if (pi) pi->generated = 1;
9662 freeAsmop (result, NULL, ic, TRUE);
9663 freeAsmop (right, NULL, ic, TRUE);
9668 /*-----------------------------------------------------------------*/
9669 /* genFarPointerSet - set value from far space */
9670 /*-----------------------------------------------------------------*/
9672 genFarPointerSet (operand * right,
9673 operand * result, iCode * ic, iCode *pi)
9675 int size, offset, dopi=1;
9676 sym_link *retype = getSpec (operandType (right));
9677 sym_link *letype = getSpec (operandType (result));
9679 aopOp (result, ic, FALSE, FALSE);
9681 /* if the operand is already in dptr
9682 then we do nothing else we move the value to dptr */
9683 if (AOP_TYPE (result) != AOP_STR)
9685 /* if this is remateriazable */
9686 if (AOP_TYPE (result) == AOP_IMMD)
9687 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9690 /* we need to get it byte by byte */
9691 _startLazyDPSEvaluation ();
9692 if (AOP_TYPE (result) != AOP_DPTR)
9694 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9695 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9696 if (options.model == MODEL_FLAT24)
9697 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9701 /* We need to generate a load to DPTR indirect through DPTR. */
9702 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9704 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9705 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9706 if (options.model == MODEL_FLAT24)
9707 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9708 emitcode ("pop", "dph");
9709 emitcode ("pop", "dpl");
9712 _endLazyDPSEvaluation ();
9715 /* so dptr know contains the address */
9716 aopOp (right, ic, FALSE, TRUE);
9718 /* if bit then unpack */
9719 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9720 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9723 size = AOP_SIZE (right);
9726 _startLazyDPSEvaluation ();
9729 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9735 emitcode ("movx", "@dptr,a");
9736 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9737 emitcode ("inc", "dptr");
9739 _endLazyDPSEvaluation ();
9742 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9743 aopPut (AOP(result),"dpl",0);
9744 aopPut (AOP(result),"dph",1);
9745 if (options.model == MODEL_FLAT24)
9746 aopPut (AOP(result),"dpx",2);
9748 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9749 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9751 size = AOP_SIZE (right) - 1;
9752 while (size--) emitcode ("lcall","__decdptr");
9754 freeAsmop (result, NULL, ic, TRUE);
9755 freeAsmop (right, NULL, ic, TRUE);
9758 /*-----------------------------------------------------------------*/
9759 /* genGenPointerSet - set value from generic pointer space */
9760 /*-----------------------------------------------------------------*/
9762 genGenPointerSet (operand * right,
9763 operand * result, iCode * ic, iCode *pi)
9766 sym_link *retype = getSpec (operandType (right));
9767 sym_link *letype = getSpec (operandType (result));
9769 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9771 /* if the operand is already in dptr
9772 then we do nothing else we move the value to dptr */
9773 if (AOP_TYPE (result) != AOP_STR)
9775 _startLazyDPSEvaluation ();
9776 /* if this is remateriazable */
9777 if (AOP_TYPE (result) == AOP_IMMD)
9779 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9780 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9781 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9783 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9786 { /* we need to get it byte by byte */
9787 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9788 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9789 if (options.model == MODEL_FLAT24) {
9790 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9791 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9793 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9796 _endLazyDPSEvaluation ();
9798 /* so dptr know contains the address */
9799 aopOp (right, ic, FALSE, TRUE);
9801 /* if bit then unpack */
9802 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9803 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9806 size = AOP_SIZE (right);
9809 _startLazyDPSEvaluation ();
9812 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9818 emitcode ("lcall", "__gptrput");
9819 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9820 emitcode ("inc", "dptr");
9822 _endLazyDPSEvaluation ();
9825 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9826 aopPut (AOP(result),"dpl",0);
9827 aopPut (AOP(result),"dph",1);
9828 if (options.model == MODEL_FLAT24) {
9829 aopPut (AOP(result),"dpx",2);
9830 aopPut (AOP(result),"b",3);
9832 aopPut (AOP(result),"b",2);
9835 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9836 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9838 size = AOP_SIZE (right) - 1;
9839 while (size--) emitcode ("lcall","__decdptr");
9841 freeAsmop (result, NULL, ic, TRUE);
9842 freeAsmop (right, NULL, ic, TRUE);
9845 /*-----------------------------------------------------------------*/
9846 /* genPointerSet - stores the value into a pointer location */
9847 /*-----------------------------------------------------------------*/
9849 genPointerSet (iCode * ic, iCode *pi)
9851 operand *right, *result;
9852 sym_link *type, *etype;
9855 D (emitcode (";", "genPointerSet ");
9858 right = IC_RIGHT (ic);
9859 result = IC_RESULT (ic);
9861 /* depending on the type of pointer we need to
9862 move it to the correct pointer register */
9863 type = operandType (result);
9864 etype = getSpec (type);
9865 /* if left is of type of pointer then it is simple */
9866 if (IS_PTR (type) && !IS_FUNC (type->next))
9868 p_type = DCL_TYPE (type);
9872 /* we have to go by the storage class */
9873 p_type = PTR_TYPE (SPEC_OCLS (etype));
9875 /* special case when cast remat */
9876 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9877 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9878 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9879 type = type = operandType (result);
9880 p_type = DCL_TYPE (type);
9883 /* now that we have the pointer type we assign
9884 the pointer values */
9890 genNearPointerSet (right, result, ic, pi);
9894 genPagedPointerSet (right, result, ic, pi);
9898 genFarPointerSet (right, result, ic, pi);
9902 genGenPointerSet (right, result, ic, pi);
9908 /*-----------------------------------------------------------------*/
9909 /* genIfx - generate code for Ifx statement */
9910 /*-----------------------------------------------------------------*/
9912 genIfx (iCode * ic, iCode * popIc)
9914 operand *cond = IC_COND (ic);
9917 D (emitcode (";", "genIfx "););
9919 aopOp (cond, ic, FALSE, FALSE);
9921 /* get the value into acc */
9922 if (AOP_TYPE (cond) != AOP_CRY)
9926 /* the result is now in the accumulator */
9927 freeAsmop (cond, NULL, ic, TRUE);
9929 /* if there was something to be popped then do it */
9933 /* if the condition is a bit variable */
9934 if (isbit && IS_ITEMP (cond) &&
9936 genIfxJump (ic, SPIL_LOC (cond)->rname);
9937 else if (isbit && !IS_ITEMP (cond))
9938 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9940 genIfxJump (ic, "a");
9945 /*-----------------------------------------------------------------*/
9946 /* genAddrOf - generates code for address of */
9947 /*-----------------------------------------------------------------*/
9949 genAddrOf (iCode * ic)
9951 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9954 D (emitcode (";", "genAddrOf ");
9957 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9959 /* if the operand is on the stack then we
9960 need to get the stack offset of this
9964 /* if 10 bit stack */
9965 if (options.stack10bit) {
9967 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
9968 /* if it has an offset then we need to compute it */
9969 emitcode ("subb", "a,#!constbyte",
9970 -((sym->stack < 0) ?
9971 ((short) (sym->stack - _G.nRegsSaved)) :
9972 ((short) sym->stack)) & 0xff);
9973 emitcode ("mov","b,a");
9974 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
9975 ((short) (sym->stack - _G.nRegsSaved)) :
9976 ((short) sym->stack)) >> 8) & 0xff);
9978 emitcode ("mov", "a,_bpx");
9979 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
9980 ((char) (sym->stack - _G.nRegsSaved)) :
9981 ((char) sym->stack )) & 0xff);
9982 emitcode ("mov", "b,a");
9983 emitcode ("mov", "a,_bpx+1");
9984 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
9985 ((short) (sym->stack - _G.nRegsSaved)) :
9986 ((short) sym->stack )) >> 8) & 0xff);
9987 aopPut (AOP (IC_RESULT (ic)), "b", 0);
9988 aopPut (AOP (IC_RESULT (ic)), "a", 1);
9989 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9991 /* we can just move _bp */
9992 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9993 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9994 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9997 /* if it has an offset then we need to compute it */
9999 emitcode ("mov", "a,_bp");
10000 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10001 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10003 /* we can just move _bp */
10004 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10006 /* fill the result with zero */
10007 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10010 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10012 "*** warning: pointer to stack var truncated.\n");
10017 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10023 /* object not on stack then we need the name */
10024 size = AOP_SIZE (IC_RESULT (ic));
10029 char s[SDCC_NAME_MAX];
10033 tsprintf(s,"!his",sym->rname);
10036 tsprintf(s,"!hihis",sym->rname);
10039 tsprintf(s,"!hihihis",sym->rname);
10041 default: /* should not need this (just in case) */
10042 sprintf (s, "#(%s >> %d)",
10047 sprintf (s, "#%s", sym->rname);
10048 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10052 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10056 /*-----------------------------------------------------------------*/
10057 /* genArrayInit - generates code for address of */
10058 /*-----------------------------------------------------------------*/
10060 genArrayInit (iCode * ic)
10062 literalList *iLoop;
10064 int elementSize = 0, eIndex;
10065 unsigned val, lastVal;
10067 operand *left=IC_LEFT(ic);
10069 D (emitcode (";", "genArrayInit "););
10071 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10073 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10075 // Load immediate value into DPTR.
10076 emitcode("mov", "dptr, %s",
10077 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10079 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10082 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10083 "Unexpected operand to genArrayInit.\n");
10086 // a regression because of SDCCcse.c:1.52
10087 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10088 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10089 if (options.model == MODEL_FLAT24)
10090 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10094 type = operandType(IC_LEFT(ic));
10096 if (type && type->next)
10098 elementSize = getSize(type->next);
10102 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10103 "can't determine element size in genArrayInit.\n");
10107 iLoop = IC_ARRAYILIST(ic);
10112 bool firstpass = TRUE;
10114 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10115 iLoop->count, (int)iLoop->literalValue, elementSize);
10121 symbol *tlbl = NULL;
10123 count = ix > 256 ? 256 : ix;
10127 tlbl = newiTempLabel (NULL);
10128 if (firstpass || (count & 0xff))
10130 emitcode("mov", "b, #!constbyte", count & 0xff);
10133 emitcode ("", "!tlabeldef", tlbl->key + 100);
10138 for (eIndex = 0; eIndex < elementSize; eIndex++)
10140 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10141 if (val != lastVal)
10143 emitcode("mov", "a, #!constbyte", val);
10147 emitcode("movx", "@dptr, a");
10148 emitcode("inc", "dptr");
10153 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10159 iLoop = iLoop->next;
10162 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10165 /*-----------------------------------------------------------------*/
10166 /* genFarFarAssign - assignment when both are in far space */
10167 /*-----------------------------------------------------------------*/
10169 genFarFarAssign (operand * result, operand * right, iCode * ic)
10171 int size = AOP_SIZE (right);
10173 symbol *rSym = NULL;
10177 /* quick & easy case. */
10178 D(emitcode(";","genFarFarAssign (1 byte case)"););
10179 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10180 freeAsmop (right, NULL, ic, FALSE);
10181 /* now assign DPTR to result */
10183 aopOp(result, ic, FALSE, FALSE);
10185 aopPut(AOP(result), "a", 0);
10186 freeAsmop(result, NULL, ic, FALSE);
10190 /* See if we've got an underlying symbol to abuse. */
10191 if (IS_SYMOP(result) && OP_SYMBOL(result))
10193 if (IS_TRUE_SYMOP(result))
10195 rSym = OP_SYMBOL(result);
10197 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10199 rSym = OP_SYMBOL(result)->usl.spillLoc;
10203 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10205 /* We can use the '390 auto-toggle feature to good effect here. */
10207 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10208 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10209 emitcode ("mov", "dptr,#%s", rSym->rname);
10210 /* DP2 = result, DP1 = right, DP1 is current. */
10213 emitcode("movx", "a,@dptr");
10214 emitcode("movx", "@dptr,a");
10217 emitcode("inc", "dptr");
10218 emitcode("inc", "dptr");
10221 emitcode("mov", "dps,#0");
10222 freeAsmop (right, NULL, ic, FALSE);
10224 some alternative code for processors without auto-toggle
10225 no time to test now, so later well put in...kpb
10226 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10227 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10228 emitcode ("mov", "dptr,#%s", rSym->rname);
10229 /* DP2 = result, DP1 = right, DP1 is current. */
10233 emitcode("movx", "a,@dptr");
10235 emitcode("inc", "dptr");
10236 emitcode("inc", "dps");
10237 emitcode("movx", "@dptr,a");
10239 emitcode("inc", "dptr");
10240 emitcode("inc", "dps");
10242 emitcode("mov", "dps,#0");
10243 freeAsmop (right, NULL, ic, FALSE);
10248 D (emitcode (";", "genFarFarAssign"););
10249 aopOp (result, ic, TRUE, TRUE);
10251 _startLazyDPSEvaluation ();
10255 aopPut (AOP (result),
10256 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10259 _endLazyDPSEvaluation ();
10260 freeAsmop (result, NULL, ic, FALSE);
10261 freeAsmop (right, NULL, ic, FALSE);
10265 /*-----------------------------------------------------------------*/
10266 /* genAssign - generate code for assignment */
10267 /*-----------------------------------------------------------------*/
10269 genAssign (iCode * ic)
10271 operand *result, *right;
10273 unsigned long lit = 0L;
10275 D (emitcode (";", "genAssign ");
10278 result = IC_RESULT (ic);
10279 right = IC_RIGHT (ic);
10281 /* if they are the same */
10282 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10285 aopOp (right, ic, FALSE, FALSE);
10287 emitcode (";", "genAssign: resultIsFar = %s",
10288 isOperandInFarSpace (result) ?
10291 /* special case both in far space */
10292 if ((AOP_TYPE (right) == AOP_DPTR ||
10293 AOP_TYPE (right) == AOP_DPTR2) &&
10294 /* IS_TRUE_SYMOP(result) && */
10295 isOperandInFarSpace (result))
10297 genFarFarAssign (result, right, ic);
10301 aopOp (result, ic, TRUE, FALSE);
10303 /* if they are the same registers */
10304 if (sameRegs (AOP (right), AOP (result)))
10307 /* if the result is a bit */
10308 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10310 /* if the right size is a literal then
10311 we know what the value is */
10312 if (AOP_TYPE (right) == AOP_LIT)
10314 if (((int) operandLitValue (right)))
10315 aopPut (AOP (result), one, 0);
10317 aopPut (AOP (result), zero, 0);
10321 /* the right is also a bit variable */
10322 if (AOP_TYPE (right) == AOP_CRY)
10324 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10325 aopPut (AOP (result), "c", 0);
10329 /* we need to or */
10331 aopPut (AOP (result), "a", 0);
10335 /* bit variables done */
10337 size = AOP_SIZE (result);
10339 if (AOP_TYPE (right) == AOP_LIT)
10340 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10343 (AOP_TYPE (result) != AOP_REG) &&
10344 (AOP_TYPE (right) == AOP_LIT) &&
10345 !IS_FLOAT (operandType (right)))
10347 _startLazyDPSEvaluation ();
10348 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10350 aopPut (AOP (result),
10351 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10356 /* And now fill the rest with zeros. */
10359 emitcode ("clr", "a");
10363 aopPut (AOP (result), "a", offset++);
10365 _endLazyDPSEvaluation ();
10369 _startLazyDPSEvaluation ();
10372 aopPut (AOP (result),
10373 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10377 _endLazyDPSEvaluation ();
10381 freeAsmop (right, NULL, ic, FALSE);
10382 freeAsmop (result, NULL, ic, TRUE);
10385 /*-----------------------------------------------------------------*/
10386 /* genJumpTab - generates code for jump table */
10387 /*-----------------------------------------------------------------*/
10389 genJumpTab (iCode * ic)
10394 D (emitcode (";", "genJumpTab ");
10397 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10398 /* get the condition into accumulator */
10399 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10401 /* multiply by four! */
10402 emitcode ("add", "a,acc");
10403 emitcode ("add", "a,acc");
10404 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10406 jtab = newiTempLabel (NULL);
10407 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10408 emitcode ("jmp", "@a+dptr");
10409 emitcode ("", "!tlabeldef", jtab->key + 100);
10410 /* now generate the jump labels */
10411 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10412 jtab = setNextItem (IC_JTLABELS (ic)))
10413 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10417 /*-----------------------------------------------------------------*/
10418 /* genCast - gen code for casting */
10419 /*-----------------------------------------------------------------*/
10421 genCast (iCode * ic)
10423 operand *result = IC_RESULT (ic);
10424 sym_link *ctype = operandType (IC_LEFT (ic));
10425 sym_link *rtype = operandType (IC_RIGHT (ic));
10426 operand *right = IC_RIGHT (ic);
10429 D (emitcode (";", "genCast ");
10432 /* if they are equivalent then do nothing */
10433 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10436 aopOp (right, ic, FALSE, FALSE);
10437 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10439 /* if the result is a bit */
10440 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10441 if (IS_BITVAR(OP_SYMBOL(result)->type))
10443 /* if the right size is a literal then
10444 we know what the value is */
10445 if (AOP_TYPE (right) == AOP_LIT)
10447 if (((int) operandLitValue (right)))
10448 aopPut (AOP (result), one, 0);
10450 aopPut (AOP (result), zero, 0);
10455 /* the right is also a bit variable */
10456 if (AOP_TYPE (right) == AOP_CRY)
10458 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10459 aopPut (AOP (result), "c", 0);
10463 /* we need to or */
10465 aopPut (AOP (result), "a", 0);
10469 /* if they are the same size : or less */
10470 if (AOP_SIZE (result) <= AOP_SIZE (right))
10473 /* if they are in the same place */
10474 if (sameRegs (AOP (right), AOP (result)))
10477 /* if they in different places then copy */
10478 size = AOP_SIZE (result);
10480 _startLazyDPSEvaluation ();
10483 aopPut (AOP (result),
10484 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10488 _endLazyDPSEvaluation ();
10493 /* if the result is of type pointer */
10494 if (IS_PTR (ctype))
10498 sym_link *type = operandType (right);
10500 /* pointer to generic pointer */
10501 if (IS_GENPTR (ctype))
10507 p_type = DCL_TYPE (type);
10511 #if OLD_CAST_BEHAVIOR
10512 /* KV: we are converting a non-pointer type to
10513 * a generic pointer. This (ifdef'd out) code
10514 * says that the resulting generic pointer
10515 * should have the same class as the storage
10516 * location of the non-pointer variable.
10518 * For example, converting an int (which happens
10519 * to be stored in DATA space) to a pointer results
10520 * in a DATA generic pointer; if the original int
10521 * in XDATA space, so will be the resulting pointer.
10523 * I don't like that behavior, and thus this change:
10524 * all such conversions will be forced to XDATA and
10525 * throw a warning. If you want some non-XDATA
10526 * type, or you want to suppress the warning, you
10527 * must go through an intermediate cast, like so:
10529 * char _generic *gp = (char _xdata *)(intVar);
10531 sym_link *etype = getSpec (type);
10533 /* we have to go by the storage class */
10534 if (SPEC_OCLS (etype) != generic)
10536 p_type = PTR_TYPE (SPEC_OCLS (etype));
10541 /* Converting unknown class (i.e. register variable)
10542 * to generic pointer. This is not good, but
10543 * we'll make a guess (and throw a warning).
10546 werror (W_INT_TO_GEN_PTR_CAST);
10550 /* the first two bytes are known */
10551 size = GPTRSIZE - 1;
10553 _startLazyDPSEvaluation ();
10556 aopPut (AOP (result),
10557 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10561 _endLazyDPSEvaluation ();
10563 /* the last byte depending on type */
10581 /* this should never happen */
10582 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10583 "got unknown pointer type");
10586 aopPut (AOP (result), l, GPTRSIZE - 1);
10590 /* just copy the pointers */
10591 size = AOP_SIZE (result);
10593 _startLazyDPSEvaluation ();
10596 aopPut (AOP (result),
10597 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10601 _endLazyDPSEvaluation ();
10605 /* so we now know that the size of destination is greater
10606 than the size of the source */
10607 /* we move to result for the size of source */
10608 size = AOP_SIZE (right);
10610 _startLazyDPSEvaluation ();
10613 aopPut (AOP (result),
10614 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10618 _endLazyDPSEvaluation ();
10620 /* now depending on the sign of the source && destination */
10621 size = AOP_SIZE (result) - AOP_SIZE (right);
10622 /* if unsigned or not an integral type */
10623 /* also, if the source is a bit, we don't need to sign extend, because
10624 * it can't possibly have set the sign bit.
10626 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10630 aopPut (AOP (result), zero, offset++);
10635 /* we need to extend the sign :{ */
10636 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10637 FALSE, FALSE, TRUE);
10639 emitcode ("rlc", "a");
10640 emitcode ("subb", "a,acc");
10642 aopPut (AOP (result), "a", offset++);
10645 /* we are done hurray !!!! */
10648 freeAsmop (right, NULL, ic, TRUE);
10649 freeAsmop (result, NULL, ic, TRUE);
10653 /*-----------------------------------------------------------------*/
10654 /* genDjnz - generate decrement & jump if not zero instrucion */
10655 /*-----------------------------------------------------------------*/
10657 genDjnz (iCode * ic, iCode * ifx)
10659 symbol *lbl, *lbl1;
10663 /* if the if condition has a false label
10664 then we cannot save */
10665 if (IC_FALSE (ifx))
10668 /* if the minus is not of the form
10670 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10671 !IS_OP_LITERAL (IC_RIGHT (ic)))
10674 if (operandLitValue (IC_RIGHT (ic)) != 1)
10677 /* if the size of this greater than one then no
10679 if (getSize (operandType (IC_RESULT (ic))) > 1)
10682 /* otherwise we can save BIG */
10683 D(emitcode(";", "genDjnz"););
10685 lbl = newiTempLabel (NULL);
10686 lbl1 = newiTempLabel (NULL);
10688 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10690 if (AOP_NEEDSACC(IC_RESULT(ic)))
10692 /* If the result is accessed indirectly via
10693 * the accumulator, we must explicitly write
10694 * it back after the decrement.
10696 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10698 if (strcmp(rByte, "a"))
10700 /* Something is hopelessly wrong */
10701 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10702 __FILE__, __LINE__);
10703 /* We can just give up; the generated code will be inefficient,
10704 * but what the hey.
10706 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10709 emitcode ("dec", "%s", rByte);
10710 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10711 emitcode ("jnz", "!tlabel", lbl->key + 100);
10713 else if (IS_AOP_PREG (IC_RESULT (ic)))
10715 emitcode ("dec", "%s",
10716 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10717 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10718 emitcode ("jnz", "!tlabel", lbl->key + 100);
10722 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10725 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10726 emitcode ("", "!tlabeldef", lbl->key + 100);
10727 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10728 emitcode ("", "!tlabeldef", lbl1->key + 100);
10730 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10731 ifx->generated = 1;
10735 /*-----------------------------------------------------------------*/
10736 /* genReceive - generate code for a receive iCode */
10737 /*-----------------------------------------------------------------*/
10739 genReceive (iCode * ic)
10742 D (emitcode (";", "genReceive ");
10745 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10746 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10747 IS_TRUE_SYMOP (IC_RESULT (ic))))
10749 int size = getSize (operandType (IC_RESULT (ic)));
10750 int offset = fReturnSizeDS390 - size;
10753 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10754 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10757 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10758 size = AOP_SIZE (IC_RESULT (ic));
10762 emitcode ("pop", "acc");
10763 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10770 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10772 assignResultValue (IC_RESULT (ic));
10775 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10778 /*-----------------------------------------------------------------*/
10779 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10780 /*-----------------------------------------------------------------*/
10781 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10783 operand *from , *to , *count;
10786 /* we know it has to be 3 parameters */
10787 assert (nparms == 3);
10793 aopOp (from, ic->next, FALSE, FALSE);
10795 /* get from into DPTR1 */
10796 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10797 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10798 if (options.model == MODEL_FLAT24) {
10799 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10802 freeAsmop (from, NULL, ic, FALSE);
10803 aopOp (to, ic, FALSE, FALSE);
10804 /* get "to" into DPTR */
10805 /* if the operand is already in dptr
10806 then we do nothing else we move the value to dptr */
10807 if (AOP_TYPE (to) != AOP_STR) {
10808 /* if already in DPTR then we need to push */
10809 if (AOP_TYPE(to) == AOP_DPTR) {
10810 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10811 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10812 if (options.model == MODEL_FLAT24)
10813 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10814 emitcode ("pop", "dph");
10815 emitcode ("pop", "dpl");
10817 _startLazyDPSEvaluation ();
10818 /* if this is remateriazable */
10819 if (AOP_TYPE (to) == AOP_IMMD) {
10820 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10821 } else { /* we need to get it byte by byte */
10822 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10823 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10824 if (options.model == MODEL_FLAT24) {
10825 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10828 _endLazyDPSEvaluation ();
10831 freeAsmop (to, NULL, ic, FALSE);
10833 aopOp (count, ic->next->next, FALSE,FALSE);
10834 lbl =newiTempLabel(NULL);
10836 /* now for the actual copy */
10837 if (AOP_TYPE(count) == AOP_LIT &&
10838 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10839 emitcode (";","OH JOY auto increment with djnz (very fast)");
10840 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10841 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10842 emitcode ("","!tlabeldef",lbl->key+100);
10844 emitcode ("clr","a");
10845 emitcode ("movc", "a,@a+dptr");
10847 emitcode ("movx", "a,@dptr");
10848 emitcode ("movx", "@dptr,a");
10849 emitcode ("inc", "dptr");
10850 emitcode ("inc", "dptr");
10851 emitcode ("djnz","b,!tlabel",lbl->key+100);
10853 symbol *lbl1 = newiTempLabel(NULL);
10855 emitcode (";"," Auto increment but no djnz");
10856 emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10857 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10858 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10859 emitcode ("","!tlabeldef",lbl->key+100);
10861 emitcode ("clr","a");
10862 emitcode ("movc", "a,@a+dptr");
10864 emitcode ("movx", "a,@dptr");
10865 emitcode ("movx", "@dptr,a");
10866 emitcode ("inc", "dptr");
10867 emitcode ("inc", "dptr");
10868 emitcode ("mov","a,b");
10869 emitcode ("orl","a,ap");
10870 emitcode ("jz","!tlabel",lbl1->key+100);
10871 emitcode ("mov","a,ap");
10872 emitcode ("add","a,#!constbyte",0xFF);
10873 emitcode ("mov","ap,a");
10874 emitcode ("mov","a,b");
10875 emitcode ("addc","a,#!constbyte",0xFF);
10876 emitcode ("mov","b,a");
10877 emitcode ("sjmp","!tlabel",lbl->key+100);
10878 emitcode ("","!tlabeldef",lbl1->key+100);
10880 emitcode ("mov", "dps,#0");
10881 freeAsmop (count, NULL, ic, FALSE);
10885 /*-----------------------------------------------------------------*/
10886 /* genMemsetX - gencode for memSetX data */
10887 /*-----------------------------------------------------------------*/
10888 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10890 operand *to , *val , *count;
10893 /* we know it has to be 3 parameters */
10894 assert (nparms == 3);
10900 aopOp (to, ic, FALSE, FALSE);
10901 /* get "to" into DPTR */
10902 /* if the operand is already in dptr
10903 then we do nothing else we move the value to dptr */
10904 if (AOP_TYPE (to) != AOP_STR) {
10905 /* if already in DPTR then we need to push */
10906 if (AOP_TYPE(to) == AOP_DPTR) {
10907 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10908 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10909 if (options.model == MODEL_FLAT24)
10910 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10911 emitcode ("pop", "dph");
10912 emitcode ("pop", "dpl");
10914 _startLazyDPSEvaluation ();
10915 /* if this is remateriazable */
10916 if (AOP_TYPE (to) == AOP_IMMD) {
10917 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10918 } else { /* we need to get it byte by byte */
10919 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10920 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10921 if (options.model == MODEL_FLAT24) {
10922 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10925 _endLazyDPSEvaluation ();
10928 freeAsmop (to, NULL, ic, FALSE);
10930 aopOp (val, ic->next->next, FALSE,FALSE);
10931 aopOp (count, ic->next->next, FALSE,FALSE);
10932 lbl =newiTempLabel(NULL);
10933 /* now for the actual copy */
10934 if (AOP_TYPE(count) == AOP_LIT &&
10935 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10936 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10937 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10939 emitcode ("","!tlabeldef",lbl->key+100);
10940 emitcode ("movx", "@dptr,a");
10941 emitcode ("inc", "dptr");
10942 emitcode ("djnz","b,!tlabel",lbl->key+100);
10944 symbol *lbl1 = newiTempLabel(NULL);
10946 emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10947 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10948 emitcode ("","!tlabeldef",lbl->key+100);
10949 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10951 emitcode ("movx", "a,@dptr");
10952 emitcode ("inc", "dptr");
10953 emitcode ("mov","a,b");
10954 emitcode ("orl","a,ap");
10955 emitcode ("jz","!tlabel",lbl1->key+100);
10956 emitcode ("mov","a,ap");
10957 emitcode ("add","a,#!constbyte",0xFF);
10958 emitcode ("mov","ap,a");
10959 emitcode ("mov","a,b");
10960 emitcode ("addc","a,#!constbyte",0xFF);
10961 emitcode ("mov","b,a");
10962 emitcode ("sjmp","!tlabel",lbl->key+100);
10963 emitcode ("","!tlabeldef",lbl1->key+100);
10965 freeAsmop (count, NULL, ic, FALSE);
10968 /*-----------------------------------------------------------------*/
10969 /* genBuiltIn - calls the appropriate function to generating code */
10970 /* for a built in function */
10971 /*-----------------------------------------------------------------*/
10972 static void genBuiltIn (iCode *ic)
10974 operand *bi_parms[MAX_BUILTIN_ARGS];
10979 /* get all the arguments for a built in function */
10980 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
10982 /* which function is it */
10983 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
10984 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
10985 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
10986 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
10987 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
10988 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
10989 genMemsetX(bi_iCode,nbi_parms,bi_parms);
10991 werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n");
10997 /*-----------------------------------------------------------------*/
10998 /* gen390Code - generate code for Dallas 390 based controllers */
10999 /*-----------------------------------------------------------------*/
11001 gen390Code (iCode * lic)
11006 lineHead = lineCurr = NULL;
11008 if (options.model == MODEL_FLAT24) {
11009 fReturnSizeDS390 = 5;
11010 fReturn = fReturn24;
11012 fReturnSizeDS390 = 4;
11013 fReturn = fReturn16;
11014 options.stack10bit=0;
11018 /* print the allocation information */
11020 printAllocInfo (currFunc, codeOutFile);
11022 /* if debug information required */
11023 if (options.debug && currFunc)
11025 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11027 if (IS_STATIC (currFunc->etype))
11028 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11030 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11033 /* stack pointer name */
11034 if (options.useXstack)
11040 for (ic = lic; ic; ic = ic->next)
11043 if (cln != ic->lineno)
11048 emitcode ("", "C$%s$%d$%d$%d ==.",
11049 FileBaseName (ic->filename), ic->lineno,
11050 ic->level, ic->block);
11053 emitcode (";", "%s %d", ic->filename, ic->lineno);
11056 /* if the result is marked as
11057 spilt and rematerializable or code for
11058 this has already been generated then
11060 if (resultRemat (ic) || ic->generated)
11063 /* depending on the operation */
11083 /* IPOP happens only when trying to restore a
11084 spilt live range, if there is an ifx statement
11085 following this pop then the if statement might
11086 be using some of the registers being popped which
11087 would destory the contents of the register so
11088 we need to check for this condition and handle it */
11090 ic->next->op == IFX &&
11091 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11092 genIfx (ic->next, ic);
11110 genEndFunction (ic);
11130 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11147 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11151 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11158 /* note these two are xlated by algebraic equivalence
11159 during parsing SDCC.y */
11160 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11161 "got '>=' or '<=' shouldn't have come here");
11165 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11177 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11181 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11185 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11209 genRightShift (ic);
11212 case GET_VALUE_AT_ADDRESS:
11213 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11217 if (POINTER_SET (ic))
11218 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11244 if (ic->builtinSEND) genBuiltIn(ic);
11245 else addSet (&_G.sendSet, ic);
11258 /* now we are ready to call the
11259 peep hole optimizer */
11260 if (!options.nopeep)
11261 peepHole (&lineHead);
11263 /* now do the actual printing */
11264 printLine (lineHead, codeOutFile);