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, #0x00");
302 emitcode ("mov", "dps, #0x01");
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 sym->aop = op->aop = aop =
831 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
832 aop->size = getSize (sym->type);
836 /* must be in a register */
837 sym->aop = op->aop = aop = newAsmop (AOP_REG);
838 aop->size = sym->nRegs;
839 for (i = 0; i < sym->nRegs; i++)
840 aop->aopu.aop_reg[i] = sym->regs[i];
843 /*-----------------------------------------------------------------*/
844 /* freeAsmop - free up the asmop given to an operand */
845 /*----------------------------------------------------------------*/
847 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
864 /* depending on the asmop type only three cases need work AOP_RO
865 , AOP_R1 && AOP_STK */
873 emitcode ("pop", "ar0");
877 bitVectUnSetBit (ic->rUsed, R0_IDX);
885 emitcode ("pop", "ar1");
889 bitVectUnSetBit (ic->rUsed, R1_IDX);
895 int stk = aop->aopu.aop_stk + aop->size;
896 bitVectUnSetBit (ic->rUsed, R0_IDX);
897 bitVectUnSetBit (ic->rUsed, R1_IDX);
899 getFreePtr (ic, &aop, FALSE);
901 if (options.stack10bit)
903 /* I'm not sure what to do here yet... */
906 "*** Warning: probably generating bad code for "
907 "10 bit stack mode.\n");
912 emitcode ("mov", "a,_bp");
913 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
914 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
918 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
923 emitcode ("pop", "acc");
924 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
927 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
930 freeAsmop (op, NULL, ic, TRUE);
933 emitcode ("pop", "ar0");
939 emitcode ("pop", "ar1");
946 /* all other cases just dealloc */
952 OP_SYMBOL (op)->aop = NULL;
953 /* if the symbol has a spill */
955 SPIL_LOC (op)->aop = NULL;
960 /*------------------------------------------------------------------*/
961 /* aopGet - for fetching value of the aop */
963 /* Set canClobberACC if you are sure it is OK to clobber the value */
964 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
965 /* just less efficient. */
966 /*------------------------------------------------------------------*/
978 /* offset is greater than
980 if (offset > (aop->size - 1) &&
981 aop->type != AOP_LIT)
984 /* depending on type */
990 /* if we need to increment it */
991 while (offset > aop->coff)
993 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
997 while (offset < aop->coff)
999 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1006 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1007 return (dname ? "acc" : "a");
1009 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1010 rs = Safe_calloc (1, strlen (s) + 1);
1017 if (aop->type == AOP_DPTR2)
1023 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1029 while (offset > aop->coff)
1031 emitcode ("inc", "dptr");
1035 while (offset < aop->coff)
1037 emitcode ("lcall", "__decdptr");
1044 emitcode ("clr", "a");
1045 emitcode ("movc", "a,@a+dptr");
1049 emitcode ("movx", "a,@dptr");
1052 if (aop->type == AOP_DPTR2)
1058 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1059 return DP2_RESULT_REG;
1062 return (dname ? "acc" : "a");
1065 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1066 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1068 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1072 tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1075 tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1078 tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1080 default: /* should not need this (just in case) */
1081 sprintf (s, "#(%s >> %d)",
1082 aop->aopu.aop_immd.aop_immd1,
1088 aop->aopu.aop_immd.aop_immd1);
1089 rs = Safe_calloc (1, strlen (s) + 1);
1095 sprintf (s, "(%s + %d)",
1099 sprintf (s, "%s", aop->aopu.aop_dir);
1100 rs = Safe_calloc (1, strlen (s) + 1);
1106 return aop->aopu.aop_reg[offset]->dname;
1108 return aop->aopu.aop_reg[offset]->name;
1111 emitcode ("clr", "a");
1112 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1113 emitcode ("rlc", "a");
1114 return (dname ? "acc" : "a");
1117 if (!offset && dname)
1119 return aop->aopu.aop_str[offset];
1122 return aopLiteral (aop->aopu.aop_lit, offset);
1126 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1130 return aop->aopu.aop_str[offset];
1134 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1135 "aopget got unsupported aop->type");
1138 /*-----------------------------------------------------------------*/
1139 /* aopPut - puts a string for a aop */
1140 /*-----------------------------------------------------------------*/
1142 aopPut (asmop * aop, char *s, int offset)
1146 if (aop->size && offset > (aop->size - 1))
1148 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1149 "aopPut got offset > aop->size");
1153 /* will assign value to value */
1154 /* depending on where it is ofcourse */
1159 sprintf (d, "(%s + %d)",
1160 aop->aopu.aop_dir, offset);
1162 sprintf (d, "%s", aop->aopu.aop_dir);
1165 emitcode ("mov", "%s,%s", d, s);
1170 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1171 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1174 strcmp (s, "r0") == 0 ||
1175 strcmp (s, "r1") == 0 ||
1176 strcmp (s, "r2") == 0 ||
1177 strcmp (s, "r3") == 0 ||
1178 strcmp (s, "r4") == 0 ||
1179 strcmp (s, "r5") == 0 ||
1180 strcmp (s, "r6") == 0 ||
1181 strcmp (s, "r7") == 0)
1182 emitcode ("mov", "%s,%s",
1183 aop->aopu.aop_reg[offset]->dname, s);
1185 emitcode ("mov", "%s,%s",
1186 aop->aopu.aop_reg[offset]->name, s);
1193 if (aop->type == AOP_DPTR2)
1201 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1202 "aopPut writting to code space");
1206 while (offset > aop->coff)
1209 emitcode ("inc", "dptr");
1212 while (offset < aop->coff)
1215 emitcode ("lcall", "__decdptr");
1220 /* if not in accumulater */
1223 emitcode ("movx", "@dptr,a");
1225 if (aop->type == AOP_DPTR2)
1233 while (offset > aop->coff)
1236 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1238 while (offset < aop->coff)
1241 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1248 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1254 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1256 else if (strcmp (s, "r0") == 0 ||
1257 strcmp (s, "r1") == 0 ||
1258 strcmp (s, "r2") == 0 ||
1259 strcmp (s, "r3") == 0 ||
1260 strcmp (s, "r4") == 0 ||
1261 strcmp (s, "r5") == 0 ||
1262 strcmp (s, "r6") == 0 ||
1263 strcmp (s, "r7") == 0)
1266 sprintf (buffer, "a%s", s);
1267 emitcode ("mov", "@%s,%s",
1268 aop->aopu.aop_ptr->name, buffer);
1271 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1276 if (strcmp (s, "a") == 0)
1277 emitcode ("push", "acc");
1281 emitcode ("push", "acc");
1283 emitcode ("push", s);
1289 /* if bit variable */
1290 if (!aop->aopu.aop_dir)
1292 emitcode ("clr", "a");
1293 emitcode ("rlc", "a");
1298 emitcode ("clr", "%s", aop->aopu.aop_dir);
1300 emitcode ("setb", "%s", aop->aopu.aop_dir);
1301 else if (!strcmp (s, "c"))
1302 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1305 if (strcmp (s, "a"))
1310 symbol *lbl = newiTempLabel (NULL);
1311 emitcode ("clr", "c");
1312 emitcode ("jz", "!tlabel", lbl->key + 100);
1313 emitcode ("cpl", "c");
1314 emitcode ("", "!tlabeldef", lbl->key + 100);
1315 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1323 if (strcmp (aop->aopu.aop_str[offset], s))
1324 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1329 if (!offset && (strcmp (s, "acc") == 0))
1332 if (strcmp (aop->aopu.aop_str[offset], s))
1333 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1337 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1338 "aopPut got unsupported aop->type");
1345 /*--------------------------------------------------------------------*/
1346 /* reAdjustPreg - points a register back to where it should (coff==0) */
1347 /*--------------------------------------------------------------------*/
1349 reAdjustPreg (asmop * aop)
1351 if ((aop->coff==0) || (aop->size <= 1)) {
1360 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1364 if (aop->type == AOP_DPTR2)
1371 emitcode ("lcall", "__decdptr");
1374 if (aop->type == AOP_DPTR2)
1384 #define AOP(op) op->aop
1385 #define AOP_TYPE(op) AOP(op)->type
1386 #define AOP_SIZE(op) AOP(op)->size
1387 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1388 AOP_TYPE(x) == AOP_R0))
1390 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1391 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1394 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1395 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1396 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1398 /* Workaround for DS80C390 bug: div ab may return bogus results
1399 * if A is accessed in instruction immediately before the div.
1401 * Will be fixed in B4 rev of processor, Dallas claims.
1404 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1405 if (!AOP_NEEDSACC(RIGHT)) \
1407 /* We can load A first, then B, since \
1408 * B (the RIGHT operand) won't clobber A, \
1409 * thus avoiding touching A right before the div. \
1411 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1412 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1414 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1418 /* Just stuff in a nop after loading A. */ \
1419 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1420 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1422 emitcode("nop", "; workaround for DS80C390 div bug."); \
1425 /*-----------------------------------------------------------------*/
1426 /* genNotFloat - generates not for float operations */
1427 /*-----------------------------------------------------------------*/
1429 genNotFloat (operand * op, operand * res)
1435 D (emitcode (";", "genNotFloat ");
1438 /* we will put 127 in the first byte of
1440 aopPut (AOP (res), "#127", 0);
1441 size = AOP_SIZE (op) - 1;
1444 _startLazyDPSEvaluation ();
1445 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1450 emitcode ("orl", "a,%s",
1452 offset++, FALSE, FALSE, FALSE));
1454 _endLazyDPSEvaluation ();
1456 tlbl = newiTempLabel (NULL);
1457 aopPut (res->aop, one, 1);
1458 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1459 aopPut (res->aop, zero, 1);
1460 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1462 size = res->aop->size - 2;
1464 /* put zeros in the rest */
1466 aopPut (res->aop, zero, offset++);
1469 /*-----------------------------------------------------------------*/
1470 /* opIsGptr: returns non-zero if the passed operand is */
1471 /* a generic pointer type. */
1472 /*-----------------------------------------------------------------*/
1474 opIsGptr (operand * op)
1476 sym_link *type = operandType (op);
1478 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1485 /*-----------------------------------------------------------------*/
1486 /* getDataSize - get the operand data size */
1487 /*-----------------------------------------------------------------*/
1489 getDataSize (operand * op)
1492 size = AOP_SIZE (op);
1493 if (size == GPTRSIZE)
1495 sym_link *type = operandType (op);
1496 if (IS_GENPTR (type))
1498 /* generic pointer; arithmetic operations
1499 * should ignore the high byte (pointer type).
1507 /*-----------------------------------------------------------------*/
1508 /* outAcc - output Acc */
1509 /*-----------------------------------------------------------------*/
1511 outAcc (operand * result)
1514 size = getDataSize (result);
1517 aopPut (AOP (result), "a", 0);
1520 /* unsigned or positive */
1523 aopPut (AOP (result), zero, offset++);
1528 /*-----------------------------------------------------------------*/
1529 /* outBitC - output a bit C */
1530 /*-----------------------------------------------------------------*/
1532 outBitC (operand * result)
1534 /* if the result is bit */
1535 if (AOP_TYPE (result) == AOP_CRY)
1537 aopPut (AOP (result), "c", 0);
1541 emitcode ("clr", "a");
1542 emitcode ("rlc", "a");
1547 /*-----------------------------------------------------------------*/
1548 /* toBoolean - emit code for orl a,operator(sizeop) */
1549 /*-----------------------------------------------------------------*/
1551 toBoolean (operand * oper)
1553 int size = AOP_SIZE (oper) - 1;
1557 /* The generic part of a generic pointer should
1558 * not participate in it's truth value.
1560 * i.e. 0x10000000 is zero.
1562 if (opIsGptr (oper))
1564 D (emitcode (";", "toBoolean: generic ptr special case.");
1569 _startLazyDPSEvaluation ();
1570 if (AOP_NEEDSACC (oper) && size)
1573 emitcode ("push", "b");
1574 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1578 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1584 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1588 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1591 _endLazyDPSEvaluation ();
1595 emitcode ("mov", "a,b");
1596 emitcode ("pop", "b");
1601 /*-----------------------------------------------------------------*/
1602 /* genNot - generate code for ! operation */
1603 /*-----------------------------------------------------------------*/
1608 sym_link *optype = operandType (IC_LEFT (ic));
1610 D (emitcode (";", "genNot ");
1613 /* assign asmOps to operand & result */
1614 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1615 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1617 /* if in bit space then a special case */
1618 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1620 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1621 emitcode ("cpl", "c");
1622 outBitC (IC_RESULT (ic));
1626 /* if type float then do float */
1627 if (IS_FLOAT (optype))
1629 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1633 toBoolean (IC_LEFT (ic));
1635 tlbl = newiTempLabel (NULL);
1636 emitcode ("cjne", "a,#0x01,!tlabel", tlbl->key + 100);
1637 emitcode ("", "!tlabeldef", tlbl->key + 100);
1638 outBitC (IC_RESULT (ic));
1641 /* release the aops */
1642 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1643 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1647 /*-----------------------------------------------------------------*/
1648 /* genCpl - generate code for complement */
1649 /*-----------------------------------------------------------------*/
1656 D (emitcode (";", "genCpl ");
1660 /* assign asmOps to operand & result */
1661 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1662 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1664 /* if both are in bit space then
1666 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1667 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1670 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1671 emitcode ("cpl", "c");
1672 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1676 size = AOP_SIZE (IC_RESULT (ic));
1677 _startLazyDPSEvaluation ();
1680 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1682 emitcode ("cpl", "a");
1683 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1685 _endLazyDPSEvaluation ();
1689 /* release the aops */
1690 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1691 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1694 /*-----------------------------------------------------------------*/
1695 /* genUminusFloat - unary minus for floating points */
1696 /*-----------------------------------------------------------------*/
1698 genUminusFloat (operand * op, operand * result)
1700 int size, offset = 0;
1702 /* for this we just need to flip the
1703 first it then copy the rest in place */
1704 D (emitcode (";", "genUminusFloat");
1707 _startLazyDPSEvaluation ();
1708 size = AOP_SIZE (op) - 1;
1709 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1712 emitcode ("cpl", "acc.7");
1713 aopPut (AOP (result), "a", 3);
1717 aopPut (AOP (result),
1718 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1722 _endLazyDPSEvaluation ();
1725 /*-----------------------------------------------------------------*/
1726 /* genUminus - unary minus code generation */
1727 /*-----------------------------------------------------------------*/
1729 genUminus (iCode * ic)
1732 sym_link *optype, *rtype;
1734 D (emitcode (";", "genUminus ");
1739 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1740 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1742 /* if both in bit space then special
1744 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1745 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1748 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1749 emitcode ("cpl", "c");
1750 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1754 optype = operandType (IC_LEFT (ic));
1755 rtype = operandType (IC_RESULT (ic));
1757 /* if float then do float stuff */
1758 if (IS_FLOAT (optype))
1760 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1764 /* otherwise subtract from zero */
1765 size = AOP_SIZE (IC_LEFT (ic));
1767 _startLazyDPSEvaluation ();
1770 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1771 if (!strcmp (l, "a"))
1775 emitcode ("cpl", "a");
1776 emitcode ("addc", "a,#0");
1782 emitcode ("clr", "a");
1783 emitcode ("subb", "a,%s", l);
1785 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1787 _endLazyDPSEvaluation ();
1789 /* if any remaining bytes in the result */
1790 /* we just need to propagate the sign */
1791 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1793 emitcode ("rlc", "a");
1794 emitcode ("subb", "a,acc");
1796 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1800 /* release the aops */
1801 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1802 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1805 /*-----------------------------------------------------------------*/
1806 /* saveRegisters - will look for a call and save the registers */
1807 /*-----------------------------------------------------------------*/
1809 saveRegisters (iCode * lic)
1817 for (ic = lic; ic; ic = ic->next)
1818 if (ic->op == CALL || ic->op == PCALL)
1823 fprintf (stderr, "found parameter push with no function call\n");
1827 /* if the registers have been saved already then
1829 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1831 /* special case if DPTR alive across a function call then must save it
1832 even though callee saves */
1833 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1835 rsave = newBitVect(ic->rMask->size);
1836 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1837 if (bitVectBitValue(ic->rMask,i))
1838 rsave = bitVectSetBit(rsave,i);
1841 /* find the registers in use at this time
1842 and push them away to safety */
1843 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1847 if (options.useXstack)
1849 if (bitVectBitValue (rsave, R0_IDX))
1850 emitcode ("mov", "b,r0");
1851 emitcode ("mov", "r0,%s", spname);
1852 for (i = 0; i < ds390_nRegs; i++)
1854 if (bitVectBitValue (rsave, i))
1857 emitcode ("mov", "a,b");
1859 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1860 emitcode ("movx", "@r0,a");
1861 emitcode ("inc", "r0");
1864 emitcode ("mov", "%s,r0", spname);
1865 if (bitVectBitValue (rsave, R0_IDX))
1866 emitcode ("mov", "r0,b");
1869 for (i = 0; i < ds390_nRegs; i++)
1871 if (bitVectBitValue (rsave, i))
1872 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1875 detype = getSpec (operandType (IC_LEFT (ic)));
1878 /*-----------------------------------------------------------------*/
1879 /* unsaveRegisters - pop the pushed registers */
1880 /*-----------------------------------------------------------------*/
1882 unsaveRegisters (iCode * ic)
1887 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1889 rsave = newBitVect(ic->rMask->size);
1890 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1891 if (bitVectBitValue(ic->rMask,i))
1892 rsave = bitVectSetBit(rsave,i);
1895 /* find the registers in use at this time
1896 and push them away to safety */
1897 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1900 if (options.useXstack)
1902 emitcode ("mov", "r0,%s", spname);
1903 for (i = ds390_nRegs; i >= 0; i--)
1905 if (bitVectBitValue (rsave, i))
1907 emitcode ("dec", "r0");
1908 emitcode ("movx", "a,@r0");
1910 emitcode ("mov", "b,a");
1912 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1916 emitcode ("mov", "%s,r0", spname);
1917 if (bitVectBitValue (rsave, R0_IDX))
1918 emitcode ("mov", "r0,b");
1921 for (i = ds390_nRegs; i >= 0; i--)
1923 if (bitVectBitValue (rsave, i))
1924 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1930 /*-----------------------------------------------------------------*/
1932 /*-----------------------------------------------------------------*/
1934 pushSide (operand * oper, int size)
1937 _startLazyDPSEvaluation ();
1940 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1941 if (AOP_TYPE (oper) != AOP_REG &&
1942 AOP_TYPE (oper) != AOP_DIR &&
1945 emitcode ("mov", "a,%s", l);
1946 emitcode ("push", "acc");
1949 emitcode ("push", "%s", l);
1951 _endLazyDPSEvaluation ();
1954 /*-----------------------------------------------------------------*/
1955 /* assignResultValue - */
1956 /*-----------------------------------------------------------------*/
1958 assignResultValue (operand * oper)
1961 int size = AOP_SIZE (oper);
1963 _startLazyDPSEvaluation ();
1966 aopPut (AOP (oper), fReturn[offset], offset);
1969 _endLazyDPSEvaluation ();
1973 /*-----------------------------------------------------------------*/
1974 /* genXpush - pushes onto the external stack */
1975 /*-----------------------------------------------------------------*/
1977 genXpush (iCode * ic)
1979 asmop *aop = newAsmop (0);
1981 int size, offset = 0;
1983 D (emitcode (";", "genXpush ");
1986 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1987 r = getFreePtr (ic, &aop, FALSE);
1990 emitcode ("mov", "%s,_spx", r->name);
1992 size = AOP_SIZE (IC_LEFT (ic));
1993 _startLazyDPSEvaluation ();
1997 char *l = aopGet (AOP (IC_LEFT (ic)),
1998 offset++, FALSE, FALSE, TRUE);
2000 emitcode ("movx", "@%s,a", r->name);
2001 emitcode ("inc", "%s", r->name);
2004 _endLazyDPSEvaluation ();
2007 emitcode ("mov", "_spx,%s", r->name);
2009 freeAsmop (NULL, aop, ic, TRUE);
2010 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2013 /*-----------------------------------------------------------------*/
2014 /* genIpush - genrate code for pushing this gets a little complex */
2015 /*-----------------------------------------------------------------*/
2017 genIpush (iCode * ic)
2019 int size, offset = 0;
2022 D (emitcode (";", "genIpush ");
2025 /* if this is not a parm push : ie. it is spill push
2026 and spill push is always done on the local stack */
2030 /* and the item is spilt then do nothing */
2031 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2034 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2035 size = AOP_SIZE (IC_LEFT (ic));
2036 /* push it on the stack */
2037 _startLazyDPSEvaluation ();
2040 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2046 emitcode ("push", "%s", l);
2048 _endLazyDPSEvaluation ();
2052 /* this is a paramter push: in this case we call
2053 the routine to find the call and save those
2054 registers that need to be saved */
2057 /* if use external stack then call the external
2058 stack pushing routine */
2059 if (options.useXstack)
2065 /* then do the push */
2066 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2068 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2069 size = AOP_SIZE (IC_LEFT (ic));
2071 _startLazyDPSEvaluation ();
2074 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2075 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2076 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2079 emitcode ("mov", "a,%s", l);
2080 emitcode ("push", "acc");
2083 emitcode ("push", "%s", l);
2085 _endLazyDPSEvaluation ();
2087 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2090 /*-----------------------------------------------------------------*/
2091 /* genIpop - recover the registers: can happen only for spilling */
2092 /*-----------------------------------------------------------------*/
2094 genIpop (iCode * ic)
2098 D (emitcode (";", "genIpop ");
2102 /* if the temp was not pushed then */
2103 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2106 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2107 size = AOP_SIZE (IC_LEFT (ic));
2108 offset = (size - 1);
2109 _startLazyDPSEvaluation ();
2112 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2113 FALSE, TRUE, TRUE));
2115 _endLazyDPSEvaluation ();
2117 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2120 /*-----------------------------------------------------------------*/
2121 /* unsaveRBank - restores the resgister bank from stack */
2122 /*-----------------------------------------------------------------*/
2124 unsaveRBank (int bank, iCode * ic, bool popPsw)
2130 if (options.useXstack)
2134 /* Assume r0 is available for use. */
2135 r = ds390_regWithIdx (R0_IDX);;
2140 r = getFreePtr (ic, &aop, FALSE);
2142 emitcode ("mov", "%s,_spx", r->name);
2147 if (options.useXstack)
2149 emitcode ("movx", "a,@%s", r->name);
2150 emitcode ("mov", "psw,a");
2151 emitcode ("dec", "%s", r->name);
2155 emitcode ("pop", "psw");
2159 for (i = (ds390_nRegs - 1); i >= 0; i--)
2161 if (options.useXstack)
2163 emitcode ("movx", "a,@%s", r->name);
2164 emitcode ("mov", "(%s+%d),a",
2165 regs390[i].base, 8 * bank + regs390[i].offset);
2166 emitcode ("dec", "%s", r->name);
2170 emitcode ("pop", "(%s+%d)",
2171 regs390[i].base, 8 * bank + regs390[i].offset);
2174 if (options.useXstack)
2176 emitcode ("mov", "_spx,%s", r->name);
2181 freeAsmop (NULL, aop, ic, TRUE);
2185 /*-----------------------------------------------------------------*/
2186 /* saveRBank - saves an entire register bank on the stack */
2187 /*-----------------------------------------------------------------*/
2189 saveRBank (int bank, iCode * ic, bool pushPsw)
2195 if (options.useXstack)
2199 /* Assume r0 is available for use. */
2200 r = ds390_regWithIdx (R0_IDX);;
2205 r = getFreePtr (ic, &aop, FALSE);
2207 emitcode ("mov", "%s,_spx", r->name);
2210 for (i = 0; i < ds390_nRegs; i++)
2212 if (options.useXstack)
2214 emitcode ("inc", "%s", r->name);
2215 emitcode ("mov", "a,(%s+%d)",
2216 regs390[i].base, 8 * bank + regs390[i].offset);
2217 emitcode ("movx", "@%s,a", r->name);
2220 emitcode ("push", "(%s+%d)",
2221 regs390[i].base, 8 * bank + regs390[i].offset);
2226 if (options.useXstack)
2228 emitcode ("mov", "a,psw");
2229 emitcode ("movx", "@%s,a", r->name);
2230 emitcode ("inc", "%s", r->name);
2231 emitcode ("mov", "_spx,%s", r->name);
2235 emitcode ("push", "psw");
2238 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2243 freeAsmop (NULL, aop, ic, TRUE);
2252 /*-----------------------------------------------------------------*/
2253 /* genCall - generates a call statement */
2254 /*-----------------------------------------------------------------*/
2256 genCall (iCode * ic)
2259 bool restoreBank = FALSE;
2260 bool swapBanks = FALSE;
2262 D (emitcode (";", "genCall "););
2264 /* if we are calling a not _naked function that is not using
2265 the same register bank then we need to save the
2266 destination registers on the stack */
2267 dtype = operandType (IC_LEFT (ic));
2268 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2269 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2270 IFFUNC_ISISR (currFunc->type))
2274 /* This is unexpected; the bank should have been saved in
2277 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2283 /* if caller saves & we have not saved then */
2287 /* if send set is not empty the assign */
2288 /* We've saved all the registers we care about;
2289 * therefore, we may clobber any register not used
2290 * in the calling convention (i.e. anything not in
2297 for (sic = setFirstItem (_G.sendSet); sic;
2298 sic = setNextItem (_G.sendSet))
2300 int size, offset = 0;
2303 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2304 size = AOP_SIZE (IC_LEFT (sic));
2306 _startLazyDPSEvaluation ();
2309 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2310 FALSE, FALSE, TRUE);
2311 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2313 emitcode("mov", "%s,%s", regs390[offset].name, l);
2315 else if (strcmp (l, fReturn[offset]))
2317 emitcode ("mov", "%s,%s",
2323 _endLazyDPSEvaluation ();
2324 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2326 size = AOP_SIZE (IC_LEFT (sic));
2334 emitcode("mov", "%s,%s",
2335 fReturn[size], regs390[size].name);
2339 // we know that dpl(hxb) is the result, so
2340 _startLazyDPSEvaluation ();
2341 size=getSize(operandType(IC_LEFT(sic)));
2343 aopOp (IC_LEFT (sic), sic, FALSE,
2344 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2346 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2350 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2351 FALSE, FALSE, TRUE);
2352 if (strcmp (l, fReturn[offset]))
2354 emitcode ("mov", "%s,%s",
2360 _endLazyDPSEvaluation ();
2362 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2369 emitcode ("mov", "psw,#!constbyte",
2370 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2374 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2375 OP_SYMBOL (IC_LEFT (ic))->rname :
2376 OP_SYMBOL (IC_LEFT (ic))->name));
2380 emitcode ("mov", "psw,#!constbyte",
2381 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2384 /* if we need assign a result value */
2385 if ((IS_ITEMP (IC_RESULT (ic)) &&
2386 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2387 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2388 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2389 IS_TRUE_SYMOP (IC_RESULT (ic)))
2391 if (isOperandInFarSpace (IC_RESULT (ic))
2392 && getSize (operandType (IC_RESULT (ic))) <= 2)
2394 int size = getSize (operandType (IC_RESULT (ic)));
2396 /* Special case for 1 or 2 byte return in far space. */
2400 emitcode ("mov", "b,%s", fReturn[1]);
2403 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2404 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2408 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2410 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2415 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2418 assignResultValue (IC_RESULT (ic));
2420 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2424 /* adjust the stack for parameters if
2426 if (ic->parmBytes) {
2427 if (options.stack10bit) {
2428 emitcode ("clr","c");
2429 emitcode ("mov","a,sp");
2430 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2431 emitcode ("mov","sp,a");
2432 emitcode ("mov","a,esp");
2433 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2434 emitcode ("mov","esp,a");
2437 if (ic->parmBytes > 3) {
2438 emitcode ("mov", "a,%s", spname);
2439 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2440 emitcode ("mov", "%s,a", spname);
2442 for (i = 0; i < ic->parmBytes; i++)
2443 emitcode ("dec", "%s", spname);
2447 /* if we hade saved some registers then unsave them */
2449 unsaveRegisters (ic);
2451 /* if register bank was saved then pop them */
2453 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2456 /*-----------------------------------------------------------------*/
2457 /* genPcall - generates a call by pointer statement */
2458 /*-----------------------------------------------------------------*/
2460 genPcall (iCode * ic)
2463 symbol *rlbl = newiTempLabel (NULL);
2464 bool restoreBank=FALSE;
2466 D (emitcode (";", "genPcall ");
2470 /* if caller saves & we have not saved then */
2474 /* if we are calling a function that is not using
2475 the same register bank then we need to save the
2476 destination registers on the stack */
2477 dtype = operandType (IC_LEFT (ic));
2478 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2479 IFFUNC_ISISR (currFunc->type) &&
2480 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2481 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2485 /* push the return address on to the stack */
2486 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2487 emitcode ("push", "acc");
2488 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2489 emitcode ("push", "acc");
2491 if (options.model == MODEL_FLAT24)
2493 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2494 emitcode ("push", "acc");
2497 /* now push the calling address */
2498 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2500 pushSide (IC_LEFT (ic), FPTRSIZE);
2502 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2504 /* if send set is not empty the assign */
2509 for (sic = setFirstItem (_G.sendSet); sic;
2510 sic = setNextItem (_G.sendSet))
2512 int size, offset = 0;
2514 // we know that dpl(hxb) is the result, so
2515 _startLazyDPSEvaluation ();
2516 size=getSize(operandType(IC_LEFT(sic)));
2518 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2520 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2524 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2525 FALSE, FALSE, TRUE);
2526 if (strcmp (l, fReturn[offset]))
2528 emitcode ("mov", "%s,%s",
2534 _endLazyDPSEvaluation ();
2535 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2540 emitcode ("ret", "");
2541 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2544 /* if we need assign a result value */
2545 if ((IS_ITEMP (IC_RESULT (ic)) &&
2546 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2547 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2548 IS_TRUE_SYMOP (IC_RESULT (ic)))
2552 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2555 assignResultValue (IC_RESULT (ic));
2557 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2560 /* adjust the stack for parameters if
2565 if (ic->parmBytes > 3)
2567 emitcode ("mov", "a,%s", spname);
2568 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2569 emitcode ("mov", "%s,a", spname);
2572 for (i = 0; i < ic->parmBytes; i++)
2573 emitcode ("dec", "%s", spname);
2577 /* if register bank was saved then unsave them */
2579 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2581 /* if we hade saved some registers then
2584 unsaveRegisters (ic);
2588 /*-----------------------------------------------------------------*/
2589 /* resultRemat - result is rematerializable */
2590 /*-----------------------------------------------------------------*/
2592 resultRemat (iCode * ic)
2594 if (SKIP_IC (ic) || ic->op == IFX)
2597 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2599 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2600 if (sym->remat && !POINTER_SET (ic))
2607 #if defined(__BORLANDC__) || defined(_MSC_VER)
2608 #define STRCASECMP stricmp
2610 #define STRCASECMP strcasecmp
2613 /*-----------------------------------------------------------------*/
2614 /* inExcludeList - return 1 if the string is in exclude Reg list */
2615 /*-----------------------------------------------------------------*/
2617 inExcludeList (char *s)
2621 if (options.excludeRegs[i] &&
2622 STRCASECMP (options.excludeRegs[i], "none") == 0)
2625 for (i = 0; options.excludeRegs[i]; i++)
2627 if (options.excludeRegs[i] &&
2628 STRCASECMP (s, options.excludeRegs[i]) == 0)
2634 /*-----------------------------------------------------------------*/
2635 /* genFunction - generated code for function entry */
2636 /*-----------------------------------------------------------------*/
2638 genFunction (iCode * ic)
2642 bool switchedPSW = FALSE;
2644 D (emitcode (";", "genFunction "););
2647 /* create the function header */
2648 emitcode (";", "-----------------------------------------");
2649 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2650 emitcode (";", "-----------------------------------------");
2652 emitcode ("", "%s:", sym->rname);
2653 ftype = operandType (IC_LEFT (ic));
2655 if (IFFUNC_ISNAKED(ftype))
2657 emitcode(";", "naked function: no prologue.");
2661 if (options.stack_probe)
2662 emitcode ("lcall","__stack_probe");
2663 /* if critical function then turn interrupts off */
2664 if (IFFUNC_ISCRITICAL (ftype))
2665 emitcode ("clr", "ea");
2667 /* here we need to generate the equates for the
2668 register bank if required */
2669 if (FUNC_REGBANK (ftype) != rbank)
2673 rbank = FUNC_REGBANK (ftype);
2674 for (i = 0; i < ds390_nRegs; i++)
2676 if (regs390[i].print) {
2677 if (strcmp (regs390[i].base, "0") == 0)
2678 emitcode ("", "%s = !constbyte",
2680 8 * rbank + regs390[i].offset);
2682 emitcode ("", "%s = %s + !constbyte",
2685 8 * rbank + regs390[i].offset);
2690 /* if this is an interrupt service routine then
2691 save acc, b, dpl, dph */
2692 if (IFFUNC_ISISR (sym->type))
2695 if (!inExcludeList ("acc"))
2696 emitcode ("push", "acc");
2697 if (!inExcludeList ("b"))
2698 emitcode ("push", "b");
2699 if (!inExcludeList ("dpl"))
2700 emitcode ("push", "dpl");
2701 if (!inExcludeList ("dph"))
2702 emitcode ("push", "dph");
2703 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2705 emitcode ("push", "dpx");
2706 /* Make sure we're using standard DPTR */
2707 emitcode ("push", "dps");
2708 emitcode ("mov", "dps, #0x00");
2709 if (options.stack10bit)
2711 /* This ISR could conceivably use DPTR2. Better save it. */
2712 emitcode ("push", "dpl1");
2713 emitcode ("push", "dph1");
2714 emitcode ("push", "dpx1");
2715 emitcode ("push", DP2_RESULT_REG);
2718 /* if this isr has no bank i.e. is going to
2719 run with bank 0 , then we need to save more
2721 if (!FUNC_REGBANK (sym->type))
2724 /* if this function does not call any other
2725 function then we can be economical and
2726 save only those registers that are used */
2727 if (!IFFUNC_HASFCALL(sym->type))
2731 /* if any registers used */
2734 /* save the registers used */
2735 for (i = 0; i < sym->regsUsed->size; i++)
2737 if (bitVectBitValue (sym->regsUsed, i) ||
2738 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2739 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2746 /* this function has a function call cannot
2747 determines register usage so we will have to push the
2749 saveRBank (0, ic, FALSE);
2754 /* This ISR uses a non-zero bank.
2756 * We assume that the bank is available for our
2759 * However, if this ISR calls a function which uses some
2760 * other bank, we must save that bank entirely.
2762 unsigned long banksToSave = 0;
2764 if (IFFUNC_HASFCALL(sym->type))
2767 #define MAX_REGISTER_BANKS 4
2772 for (i = ic; i; i = i->next)
2774 if (i->op == ENDFUNCTION)
2776 /* we got to the end OK. */
2784 dtype = operandType (IC_LEFT(i));
2786 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2788 /* Mark this bank for saving. */
2789 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2791 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2795 banksToSave |= (1 << FUNC_REGBANK(dtype));
2798 /* And note that we don't need to do it in
2806 /* This is a mess; we have no idea what
2807 * register bank the called function might
2810 * The only thing I can think of to do is
2811 * throw a warning and hope.
2813 werror(W_FUNCPTR_IN_USING_ISR);
2817 if (banksToSave && options.useXstack)
2819 /* Since we aren't passing it an ic,
2820 * saveRBank will assume r0 is available to abuse.
2822 * So switch to our (trashable) bank now, so
2823 * the caller's R0 isn't trashed.
2825 emitcode ("push", "psw");
2826 emitcode ("mov", "psw,#!constbyte",
2827 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2831 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2833 if (banksToSave & (1 << ix))
2835 saveRBank(ix, NULL, FALSE);
2839 // jwk: this needs a closer look
2840 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2845 /* if callee-save to be used for this function
2846 then save the registers being used in this function */
2847 if (IFFUNC_CALLEESAVES(sym->type))
2851 /* if any registers used */
2854 /* save the registers used */
2855 for (i = 0; i < sym->regsUsed->size; i++)
2857 if (bitVectBitValue (sym->regsUsed, i) ||
2858 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2860 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2868 /* set the register bank to the desired value */
2869 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2872 emitcode ("push", "psw");
2873 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2876 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2877 if (options.stack10bit) {
2878 emitcode ("push","_bpx");
2879 emitcode ("push","_bpx+1");
2880 emitcode ("mov","_bpx,%s",spname);
2881 emitcode ("mov","_bpx+1,esp");
2882 emitcode ("anl","_bpx+1,#3");
2884 if (options.useXstack) {
2885 emitcode ("mov", "r0,%s", spname);
2886 emitcode ("mov", "a,_bp");
2887 emitcode ("movx", "@r0,a");
2888 emitcode ("inc", "%s", spname);
2890 /* set up the stack */
2891 emitcode ("push", "_bp"); /* save the callers stack */
2893 emitcode ("mov", "_bp,%s", spname);
2897 /* adjust the stack for the function */
2900 if (options.stack10bit) {
2901 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2902 assert (sym->recvSize <= 4);
2903 emitcode ("mov","a,sp");
2904 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2905 emitcode ("mov","sp,a");
2906 emitcode ("mov","a,esp");
2907 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2908 emitcode ("mov","esp,a");
2911 werror (W_STACK_OVERFLOW, sym->name);
2913 if (i > 3 && sym->recvSize < 4) {
2915 emitcode ("mov", "a,sp");
2916 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2917 emitcode ("mov", "sp,a");
2921 emitcode ("inc", "sp");
2928 emitcode ("mov", "a,_spx");
2929 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2930 emitcode ("mov", "_spx,a");
2935 /*-----------------------------------------------------------------*/
2936 /* genEndFunction - generates epilogue for functions */
2937 /*-----------------------------------------------------------------*/
2939 genEndFunction (iCode * ic)
2941 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2943 D (emitcode (";", "genEndFunction "););
2945 if (IFFUNC_ISNAKED(sym->type))
2947 emitcode(";", "naked function: no epilogue.");
2951 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2952 if (options.stack10bit) {
2953 emitcode ("mov", "sp,_bpx", spname);
2954 emitcode ("mov", "esp,_bpx+1", spname);
2956 emitcode ("mov", "%s,_bp", spname);
2960 /* if use external stack but some variables were
2961 added to the local stack then decrement the
2963 if (options.useXstack && sym->stack) {
2964 emitcode ("mov", "a,sp");
2965 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2966 emitcode ("mov", "sp,a");
2970 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2971 if (options.useXstack) {
2972 emitcode ("mov", "r0,%s", spname);
2973 emitcode ("movx", "a,@r0");
2974 emitcode ("mov", "_bp,a");
2975 emitcode ("dec", "%s", spname);
2977 if (options.stack10bit) {
2978 emitcode ("pop", "_bpx+1");
2979 emitcode ("pop", "_bpx");
2981 emitcode ("pop", "_bp");
2986 /* restore the register bank */
2987 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2989 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2990 || !options.useXstack)
2992 /* Special case of ISR using non-zero bank with useXstack
2995 emitcode ("pop", "psw");
2999 if (IFFUNC_ISISR (sym->type))
3002 /* now we need to restore the registers */
3003 /* if this isr has no bank i.e. is going to
3004 run with bank 0 , then we need to save more
3006 if (!FUNC_REGBANK (sym->type))
3008 /* if this function does not call any other
3009 function then we can be economical and
3010 save only those registers that are used */
3011 if (!IFFUNC_HASFCALL(sym->type))
3015 /* if any registers used */
3018 /* save the registers used */
3019 for (i = sym->regsUsed->size; i >= 0; i--)
3021 if (bitVectBitValue (sym->regsUsed, i) ||
3022 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3023 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3030 /* this function has a function call cannot
3031 determines register usage so we will have to pop the
3033 unsaveRBank (0, ic, FALSE);
3038 /* This ISR uses a non-zero bank.
3040 * Restore any register banks saved by genFunction
3043 // jwk: this needs a closer look
3044 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3047 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3049 if (savedBanks & (1 << ix))
3051 unsaveRBank(ix, NULL, FALSE);
3055 if (options.useXstack)
3057 /* Restore bank AFTER calling unsaveRBank,
3058 * since it can trash r0.
3060 emitcode ("pop", "psw");
3064 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3066 if (options.stack10bit)
3068 emitcode ("pop", DP2_RESULT_REG);
3069 emitcode ("pop", "dpx1");
3070 emitcode ("pop", "dph1");
3071 emitcode ("pop", "dpl1");
3073 emitcode ("pop", "dps");
3074 emitcode ("pop", "dpx");
3076 if (!inExcludeList ("dph"))
3077 emitcode ("pop", "dph");
3078 if (!inExcludeList ("dpl"))
3079 emitcode ("pop", "dpl");
3080 if (!inExcludeList ("b"))
3081 emitcode ("pop", "b");
3082 if (!inExcludeList ("acc"))
3083 emitcode ("pop", "acc");
3085 if (IFFUNC_ISCRITICAL (sym->type))
3086 emitcode ("setb", "ea");
3088 /* if debug then send end of function */
3089 if (options.debug && currFunc) {
3091 emitcode ("", "C$%s$%d$%d$%d ==.",
3092 FileBaseName (ic->filename), currFunc->lastLine,
3093 ic->level, ic->block);
3094 if (IS_STATIC (currFunc->etype))
3095 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3097 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3101 emitcode ("reti", "");
3105 if (IFFUNC_ISCRITICAL (sym->type))
3106 emitcode ("setb", "ea");
3108 if (IFFUNC_CALLEESAVES(sym->type))
3112 /* if any registers used */
3115 /* save the registers used */
3116 for (i = sym->regsUsed->size; i >= 0; i--)
3118 if (bitVectBitValue (sym->regsUsed, i) ||
3119 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3120 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3126 /* if debug then send end of function */
3127 if (options.debug && currFunc)
3130 emitcode ("", "C$%s$%d$%d$%d ==.",
3131 FileBaseName (ic->filename), currFunc->lastLine,
3132 ic->level, ic->block);
3133 if (IS_STATIC (currFunc->etype))
3134 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3136 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3140 emitcode ("ret", "");
3145 /*-----------------------------------------------------------------*/
3146 /* genRet - generate code for return statement */
3147 /*-----------------------------------------------------------------*/
3151 int size, offset = 0, pushed = 0;
3153 D (emitcode (";", "genRet ");
3156 /* if we have no return value then
3157 just generate the "ret" */
3161 /* we have something to return then
3162 move the return value into place */
3163 aopOp (IC_LEFT (ic), ic, FALSE,
3164 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3165 size = AOP_SIZE (IC_LEFT (ic));
3167 _startLazyDPSEvaluation ();
3171 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3173 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3174 FALSE, TRUE, FALSE);
3175 emitcode ("push", "%s", l);
3180 /* Since A is the last element of fReturn,
3181 * is is OK to clobber it in the aopGet.
3183 l = aopGet (AOP (IC_LEFT (ic)), offset,
3184 FALSE, FALSE, TRUE);
3185 if (strcmp (fReturn[offset], l))
3186 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3189 _endLazyDPSEvaluation ();
3196 if (strcmp (fReturn[pushed], "a"))
3197 emitcode ("pop", fReturn[pushed]);
3199 emitcode ("pop", "acc");
3202 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3205 /* generate a jump to the return label
3206 if the next is not the return statement */
3207 if (!(ic->next && ic->next->op == LABEL &&
3208 IC_LABEL (ic->next) == returnLabel))
3210 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3214 /*-----------------------------------------------------------------*/
3215 /* genLabel - generates a label */
3216 /*-----------------------------------------------------------------*/
3218 genLabel (iCode * ic)
3220 /* special case never generate */
3221 if (IC_LABEL (ic) == entryLabel)
3224 D (emitcode (";", "genLabel ");
3227 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3230 /*-----------------------------------------------------------------*/
3231 /* genGoto - generates a ljmp */
3232 /*-----------------------------------------------------------------*/
3234 genGoto (iCode * ic)
3236 D (emitcode (";", "genGoto ");
3238 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3241 /*-----------------------------------------------------------------*/
3242 /* findLabelBackwards: walks back through the iCode chain looking */
3243 /* for the given label. Returns number of iCode instructions */
3244 /* between that label and given ic. */
3245 /* Returns zero if label not found. */
3246 /*-----------------------------------------------------------------*/
3248 findLabelBackwards (iCode * ic, int key)
3257 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3259 /* printf("findLabelBackwards = %d\n", count); */
3267 /*-----------------------------------------------------------------*/
3268 /* genPlusIncr :- does addition with increment if possible */
3269 /*-----------------------------------------------------------------*/
3271 genPlusIncr (iCode * ic)
3273 unsigned int icount;
3274 unsigned int size = getDataSize (IC_RESULT (ic));
3276 /* will try to generate an increment */
3277 /* if the right side is not a literal
3279 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3282 /* if the literal value of the right hand side
3283 is greater than 4 then it is not worth it */
3284 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3287 /* if increment 16 bits in register */
3289 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3290 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3291 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3299 /* If the next instruction is a goto and the goto target
3300 * is <= 5 instructions previous to this, we can generate
3301 * jumps straight to that target.
3303 if (ic->next && ic->next->op == GOTO
3304 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3307 emitcode (";", "tail increment optimized (range %d)", labelRange);
3308 tlbl = IC_LABEL (ic->next);
3313 tlbl = newiTempLabel (NULL);
3316 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3317 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3318 IS_AOP_PREG (IC_RESULT (ic)))
3319 emitcode ("cjne", "%s,#0x00,!tlabel"
3320 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3324 emitcode ("clr", "a");
3325 emitcode ("cjne", "a,%s,!tlabel"
3326 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3330 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3333 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3334 IS_AOP_PREG (IC_RESULT (ic)))
3335 emitcode ("cjne", "%s,#0x00,!tlabel"
3336 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3339 emitcode ("cjne", "a,%s,!tlabel"
3340 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3343 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3347 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3348 IS_AOP_PREG (IC_RESULT (ic)))
3349 emitcode ("cjne", "%s,#0x00,!tlabel"
3350 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3354 emitcode ("cjne", "a,%s,!tlabel"
3355 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3358 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3363 emitcode ("", "!tlabeldef", tlbl->key + 100);
3368 /* if the sizes are greater than 1 then we cannot */
3369 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3370 AOP_SIZE (IC_LEFT (ic)) > 1)
3373 /* we can if the aops of the left & result match or
3374 if they are in registers and the registers are the
3377 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3378 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3379 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3384 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3385 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3386 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3391 _startLazyDPSEvaluation ();
3394 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3396 _endLazyDPSEvaluation ();
3405 /*-----------------------------------------------------------------*/
3406 /* outBitAcc - output a bit in acc */
3407 /*-----------------------------------------------------------------*/
3409 outBitAcc (operand * result)
3411 symbol *tlbl = newiTempLabel (NULL);
3412 /* if the result is a bit */
3413 if (AOP_TYPE (result) == AOP_CRY)
3415 aopPut (AOP (result), "a", 0);
3419 emitcode ("jz", "!tlabel", tlbl->key + 100);
3420 emitcode ("mov", "a,%s", one);
3421 emitcode ("", "!tlabeldef", tlbl->key + 100);
3426 /*-----------------------------------------------------------------*/
3427 /* genPlusBits - generates code for addition of two bits */
3428 /*-----------------------------------------------------------------*/
3430 genPlusBits (iCode * ic)
3432 D (emitcode (";", "genPlusBits ");
3434 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3436 symbol *lbl = newiTempLabel (NULL);
3437 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3438 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3439 emitcode ("cpl", "c");
3440 emitcode ("", "!tlabeldef", (lbl->key + 100));
3441 outBitC (IC_RESULT (ic));
3445 emitcode ("clr", "a");
3446 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3447 emitcode ("rlc", "a");
3448 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3449 emitcode ("addc", "a,#0x00");
3450 outAcc (IC_RESULT (ic));
3455 adjustArithmeticResult (iCode * ic)
3457 if (opIsGptr (IC_RESULT (ic)) &&
3458 opIsGptr (IC_LEFT (ic)) &&
3459 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3461 aopPut (AOP (IC_RESULT (ic)),
3462 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3466 if (opIsGptr (IC_RESULT (ic)) &&
3467 opIsGptr (IC_RIGHT (ic)) &&
3468 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3470 aopPut (AOP (IC_RESULT (ic)),
3471 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3475 if (opIsGptr (IC_RESULT (ic)) &&
3476 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3477 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3478 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3479 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3482 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3483 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3487 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3488 // Please don't bring it back without a really good reason.
3489 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3490 // (because all three operands are in far space).
3491 #define AOP_OP_3(ic) \
3492 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3493 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3494 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3495 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3496 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3497 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3499 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3501 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3505 // Macro to aopOp all three operands of an ic. If this cannot be done,
3506 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3507 // will be set TRUE. The caller must then handle the case specially, noting
3508 // that the IC_RESULT operand is not aopOp'd.
3509 #define AOP_OP_3_NOFATAL(ic, rc) \
3510 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3511 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3512 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3513 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3514 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3516 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3521 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3522 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3524 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3525 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3527 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3529 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3533 // aopOp the left & right operands of an ic.
3534 #define AOP_OP_2(ic) \
3535 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3536 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3538 // convienience macro.
3539 #define AOP_SET_LOCALS(ic) \
3540 left = IC_LEFT(ic); \
3541 right = IC_RIGHT(ic); \
3542 result = IC_RESULT(ic);
3545 // Given an integer value of pushedSize bytes on the stack,
3546 // adjust it to be resultSize bytes, either by discarding
3547 // the most significant bytes or by zero-padding.
3549 // On exit from this macro, pushedSize will have been adjusted to
3550 // equal resultSize, and ACC may be trashed.
3551 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3552 /* If the pushed data is bigger than the result, \
3553 * simply discard unused bytes. Icky, but works. \
3555 while (pushedSize > resultSize) \
3557 D (emitcode (";", "discarding unused result byte."););\
3558 emitcode ("pop", "acc"); \
3561 if (pushedSize < resultSize) \
3563 emitcode ("clr", "a"); \
3564 /* Conversly, we haven't pushed enough here. \
3565 * just zero-pad, and all is well. \
3567 while (pushedSize < resultSize) \
3569 emitcode("push", "acc"); \
3573 assert(pushedSize == resultSize);
3575 /*-----------------------------------------------------------------*/
3576 /* genPlus - generates code for addition */
3577 /*-----------------------------------------------------------------*/
3579 genPlus (iCode * ic)
3581 int size, offset = 0;
3582 bool pushResult = FALSE;
3585 D (emitcode (";", "genPlus "););
3587 /* special cases :- */
3588 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3589 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3590 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3591 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3593 while (size--) emitcode ("inc","dptr");
3595 emitcode ("mov","a,dpl");
3596 emitcode ("add","a,#!constbyte",size & 0xff);
3597 emitcode ("mov","dpl,a");
3598 emitcode ("mov","a,dph");
3599 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3600 emitcode ("mov","dph,a");
3601 emitcode ("mov","a,dpx");
3602 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3603 emitcode ("mov","dpx,a");
3605 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3608 if ( IS_SYMOP(IC_LEFT(ic)) &&
3609 OP_SYMBOL(IC_LEFT(ic))->remat &&
3610 isOperandInFarSpace(IC_RIGHT(ic))) {
3611 operand *op = IC_RIGHT(ic);
3612 IC_RIGHT(ic) = IC_LEFT(ic);
3616 AOP_OP_3_NOFATAL (ic, pushResult);
3619 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3624 /* if literal, literal on the right or
3625 if left requires ACC or right is already
3627 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3628 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3629 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3631 operand *t = IC_RIGHT (ic);
3632 IC_RIGHT (ic) = IC_LEFT (ic);
3634 emitcode (";", "Swapped plus args.");
3637 /* if both left & right are in bit
3639 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3640 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3646 /* if left in bit space & right literal */
3647 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3648 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3650 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3651 /* if result in bit space */
3652 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3654 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3655 emitcode ("cpl", "c");
3656 outBitC (IC_RESULT (ic));
3660 size = getDataSize (IC_RESULT (ic));
3661 _startLazyDPSEvaluation ();
3664 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3665 emitcode ("addc", "a,#00");
3666 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3668 _endLazyDPSEvaluation ();
3673 /* if I can do an increment instead
3674 of add then GOOD for ME */
3675 if (genPlusIncr (ic) == TRUE)
3677 emitcode (";", "did genPlusIncr");
3682 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3684 _startLazyDPSEvaluation ();
3687 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3689 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3691 emitcode ("add", "a,%s",
3692 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3694 emitcode ("addc", "a,%s",
3695 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3699 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3701 /* right is going to use ACC or we would have taken the
3704 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3706 D(emitcode(";", "+ AOP_ACC special case."););
3707 emitcode("xch", "a, %s", DP2_RESULT_REG);
3709 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3712 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3715 emitcode("add", "a, %s", DP2_RESULT_REG);
3719 emitcode ("add", "a,%s",
3720 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3725 emitcode ("addc", "a,%s",
3726 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3731 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3735 emitcode ("push", "acc");
3739 _endLazyDPSEvaluation ();
3743 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3745 size = getDataSize (IC_LEFT (ic));
3746 rSize = getDataSize (IC_RESULT (ic));
3748 ADJUST_PUSHED_RESULT(size, rSize);
3750 _startLazyDPSEvaluation ();
3753 emitcode ("pop", "acc");
3754 aopPut (AOP (IC_RESULT (ic)), "a", size);
3756 _endLazyDPSEvaluation ();
3759 adjustArithmeticResult (ic);
3762 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3763 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3764 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3767 /*-----------------------------------------------------------------*/
3768 /* genMinusDec :- does subtraction with deccrement if possible */
3769 /*-----------------------------------------------------------------*/
3771 genMinusDec (iCode * ic)
3773 unsigned int icount;
3774 unsigned int size = getDataSize (IC_RESULT (ic));
3776 /* will try to generate an increment */
3777 /* if the right side is not a literal
3779 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3782 /* if the literal value of the right hand side
3783 is greater than 4 then it is not worth it */
3784 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3787 /* if decrement 16 bits in register */
3788 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3789 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3790 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3798 /* If the next instruction is a goto and the goto target
3799 * is <= 5 instructions previous to this, we can generate
3800 * jumps straight to that target.
3802 if (ic->next && ic->next->op == GOTO
3803 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3806 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3807 tlbl = IC_LABEL (ic->next);
3812 tlbl = newiTempLabel (NULL);
3816 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3817 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3818 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3819 IS_AOP_PREG (IC_RESULT (ic)))
3820 emitcode ("cjne", "%s,#0xff,!tlabel"
3821 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3825 emitcode ("mov", "a,#0xff");
3826 emitcode ("cjne", "a,%s,!tlabel"
3827 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3830 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3833 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3834 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3835 IS_AOP_PREG (IC_RESULT (ic)))
3836 emitcode ("cjne", "%s,#0xff,!tlabel"
3837 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3841 emitcode ("cjne", "a,%s,!tlabel"
3842 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3845 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3849 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3850 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3851 IS_AOP_PREG (IC_RESULT (ic)))
3852 emitcode ("cjne", "%s,#0xff,!tlabel"
3853 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3857 emitcode ("cjne", "a,%s,!tlabel"
3858 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3861 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3865 emitcode ("", "!tlabeldef", tlbl->key + 100);
3870 /* if the sizes are greater than 1 then we cannot */
3871 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3872 AOP_SIZE (IC_LEFT (ic)) > 1)
3875 /* we can if the aops of the left & result match or
3876 if they are in registers and the registers are the
3879 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3880 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3881 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3884 _startLazyDPSEvaluation ();
3887 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3889 _endLazyDPSEvaluation ();
3897 /*-----------------------------------------------------------------*/
3898 /* addSign - complete with sign */
3899 /*-----------------------------------------------------------------*/
3901 addSign (operand * result, int offset, int sign)
3903 int size = (getDataSize (result) - offset);
3906 _startLazyDPSEvaluation();
3909 emitcode ("rlc", "a");
3910 emitcode ("subb", "a,acc");
3913 aopPut (AOP (result), "a", offset++);
3920 aopPut (AOP (result), zero, offset++);
3923 _endLazyDPSEvaluation();
3927 /*-----------------------------------------------------------------*/
3928 /* genMinusBits - generates code for subtraction of two bits */
3929 /*-----------------------------------------------------------------*/
3931 genMinusBits (iCode * ic)
3933 symbol *lbl = newiTempLabel (NULL);
3935 D (emitcode (";", "genMinusBits "););
3937 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3939 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3940 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3941 emitcode ("cpl", "c");
3942 emitcode ("", "!tlabeldef", (lbl->key + 100));
3943 outBitC (IC_RESULT (ic));
3947 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3948 emitcode ("subb", "a,acc");
3949 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3950 emitcode ("inc", "a");
3951 emitcode ("", "!tlabeldef", (lbl->key + 100));
3952 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3953 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3957 /*-----------------------------------------------------------------*/
3958 /* genMinus - generates code for subtraction */
3959 /*-----------------------------------------------------------------*/
3961 genMinus (iCode * ic)
3963 int size, offset = 0;
3965 unsigned long lit = 0L;
3966 bool pushResult = FALSE;
3968 D (emitcode (";", "genMinus "););
3970 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3971 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3972 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3973 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3979 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3981 /* special cases :- */
3982 /* if both left & right are in bit space */
3983 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3984 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3990 /* if I can do an decrement instead
3991 of subtract then GOOD for ME */
3992 if (genMinusDec (ic) == TRUE)
3997 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3999 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4005 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4010 /* if literal, add a,#-lit, else normal subb */
4011 _startLazyDPSEvaluation ();
4014 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4015 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4016 emitcode ("subb", "a,%s",
4017 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4020 /* first add without previous c */
4022 if (!size && lit==-1) {
4023 emitcode ("dec", "a");
4025 emitcode ("add", "a,#!constbyte",
4026 (unsigned int) (lit & 0x0FFL));
4029 emitcode ("addc", "a,#!constbyte",
4030 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4036 emitcode ("push", "acc");
4040 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4044 _endLazyDPSEvaluation ();
4048 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4050 size = getDataSize (IC_LEFT (ic));
4051 rSize = getDataSize (IC_RESULT (ic));
4053 ADJUST_PUSHED_RESULT(size, rSize);
4055 _startLazyDPSEvaluation ();
4058 emitcode ("pop", "acc");
4059 aopPut (AOP (IC_RESULT (ic)), "a", size);
4061 _endLazyDPSEvaluation ();
4064 adjustArithmeticResult (ic);
4067 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4068 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4069 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4073 /*-----------------------------------------------------------------*/
4074 /* genMultbits :- multiplication of bits */
4075 /*-----------------------------------------------------------------*/
4077 genMultbits (operand * left,
4082 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4083 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4084 aopOp(result, ic, TRUE, FALSE);
4089 /*-----------------------------------------------------------------*/
4090 /* genMultOneByte : 8*8=8/16 bit multiplication */
4091 /*-----------------------------------------------------------------*/
4093 genMultOneByte (operand * left,
4098 sym_link *opetype = operandType (result);
4102 /* (if two literals: the value is computed before) */
4103 /* if one literal, literal on the right */
4104 if (AOP_TYPE (left) == AOP_LIT)
4109 emitcode (";", "swapped left and right");
4112 if (SPEC_USIGN(opetype)
4113 // ignore the sign of left and right, what else can we do?
4114 || (SPEC_USIGN(operandType(left)) &&
4115 SPEC_USIGN(operandType(right)))) {
4116 // just an unsigned 8*8=8/16 multiply
4117 //emitcode (";","unsigned");
4118 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4119 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4120 emitcode ("mul", "ab");
4122 _G.accInUse++; _G.bInUse++;
4123 aopOp(result, ic, TRUE, FALSE);
4125 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4127 // this should never happen
4128 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4129 AOP_SIZE(result), __FILE__, lineno);
4133 aopPut (AOP (result), "a", 0);
4134 _G.accInUse--; _G.bInUse--;
4135 if (AOP_SIZE(result)==2)
4137 aopPut (AOP (result), "b", 1);
4142 // we have to do a signed multiply
4144 emitcode (";", "signed");
4145 emitcode ("clr", "F0"); // reset sign flag
4146 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4148 lbl=newiTempLabel(NULL);
4149 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4150 // left side is negative, 8-bit two's complement, this fails for -128
4151 emitcode ("setb", "F0"); // set sign flag
4152 emitcode ("cpl", "a");
4153 emitcode ("inc", "a");
4155 emitcode ("", "!tlabeldef", lbl->key+100);
4158 if (AOP_TYPE(right)==AOP_LIT) {
4159 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4160 /* AND literal negative */
4161 if ((int) val < 0) {
4162 emitcode ("cpl", "F0"); // complement sign flag
4163 emitcode ("mov", "b,#!constbyte", -val);
4165 emitcode ("mov", "b,#!constbyte", val);
4168 lbl=newiTempLabel(NULL);
4169 emitcode ("mov", "b,a");
4170 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4171 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4172 // right side is negative, 8-bit two's complement
4173 emitcode ("cpl", "F0"); // complement sign flag
4174 emitcode ("cpl", "a");
4175 emitcode ("inc", "a");
4176 emitcode ("", "!tlabeldef", lbl->key+100);
4178 emitcode ("mul", "ab");
4180 _G.accInUse++;_G.bInUse++;
4181 aopOp(result, ic, TRUE, FALSE);
4183 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4185 // this should never happen
4186 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4187 AOP_SIZE(result), __FILE__, lineno);
4191 lbl=newiTempLabel(NULL);
4192 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4193 // only ONE op was negative, we have to do a 8/16-bit two's complement
4194 emitcode ("cpl", "a"); // lsb
4195 if (AOP_SIZE(result)==1) {
4196 emitcode ("inc", "a");
4198 emitcode ("add", "a,#1");
4199 emitcode ("xch", "a,b");
4200 emitcode ("cpl", "a"); // msb
4201 emitcode ("addc", "a,#0");
4202 emitcode ("xch", "a,b");
4205 emitcode ("", "!tlabeldef", lbl->key+100);
4206 aopPut (AOP (result), "a", 0);
4207 _G.accInUse--;_G.bInUse--;
4208 if (AOP_SIZE(result)==2) {
4209 aopPut (AOP (result), "b", 1);
4213 /*-----------------------------------------------------------------*/
4214 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4215 /*-----------------------------------------------------------------*/
4216 static void genMultTwoByte (operand *left, operand *right,
4217 operand *result, iCode *ic)
4219 sym_link *retype = getSpec(operandType(right));
4220 sym_link *letype = getSpec(operandType(left));
4221 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4224 if (AOP_TYPE (left) == AOP_LIT) {
4229 /* save EA bit in F1 */
4230 lbl = newiTempLabel(NULL);
4231 emitcode ("setb","F1");
4232 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4233 emitcode ("clr","F1");
4234 emitcode("","!tlabeldef",lbl->key+100);
4236 /* load up MB with right */
4238 emitcode("clr","F0");
4239 if (AOP_TYPE(right) == AOP_LIT) {
4240 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4242 emitcode("setb","F0");
4245 emitcode ("mov","mb,#!constbyte",val & 0xff);
4246 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4248 lbl = newiTempLabel(NULL);
4249 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4250 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4251 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4252 emitcode ("xch", "a,b");
4253 emitcode ("cpl","a");
4254 emitcode ("add", "a,#1");
4255 emitcode ("xch", "a,b");
4256 emitcode ("cpl", "a"); // msb
4257 emitcode ("addc", "a,#0");
4258 emitcode ("setb","F0");
4259 emitcode ("","!tlabeldef",lbl->key+100);
4260 emitcode ("mov","mb,b");
4261 emitcode ("mov","mb,a");
4264 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4265 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4267 /* load up MA with left */
4269 lbl = newiTempLabel(NULL);
4270 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4271 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4272 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4273 emitcode ("xch", "a,b");
4274 emitcode ("cpl","a");
4275 emitcode ("add", "a,#1");
4276 emitcode ("xch", "a,b");
4277 emitcode ("cpl", "a"); // msb
4278 emitcode ("addc","a,#0");
4279 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4280 emitcode ("setb","F0");
4281 emitcode ("","!tlabeldef",lbl->key+100);
4282 emitcode ("mov","ma,b");
4283 emitcode ("mov","ma,a");
4285 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4286 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4288 /* wait for multiplication to finish */
4289 lbl = newiTempLabel(NULL);
4290 emitcode("","!tlabeldef", lbl->key+100);
4291 emitcode("mov","a,mcnt1");
4292 emitcode("anl","a,#0x80");
4293 emitcode("jnz","!tlabel",lbl->key+100);
4295 freeAsmop (left, NULL, ic, TRUE);
4296 freeAsmop (right, NULL, ic,TRUE);
4297 aopOp(result, ic, TRUE, FALSE);
4299 /* if unsigned then simple */
4301 emitcode ("mov","a,ma");
4302 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4303 emitcode ("mov","a,ma");
4304 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4305 aopPut(AOP(result),"ma",1);
4306 aopPut(AOP(result),"ma",0);
4308 emitcode("push","ma");
4309 emitcode("push","ma");
4310 emitcode("push","ma");
4312 /* negate result if needed */
4313 lbl = newiTempLabel(NULL);
4314 emitcode("jnb","F0,!tlabel",lbl->key+100);
4315 emitcode("cpl","a");
4316 emitcode("add","a,#1");
4317 emitcode("","!tlabeldef", lbl->key+100);
4318 if (AOP_TYPE(result) == AOP_ACC)
4320 D(emitcode(";", "ACC special case."););
4321 /* We know result is the only live aop, and
4322 * it's obviously not a DPTR2, so AP is available.
4324 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4328 aopPut(AOP(result),"a",0);
4331 emitcode("pop","acc");
4332 lbl = newiTempLabel(NULL);
4333 emitcode("jnb","F0,!tlabel",lbl->key+100);
4334 emitcode("cpl","a");
4335 emitcode("addc","a,#0");
4336 emitcode("","!tlabeldef", lbl->key+100);
4337 aopPut(AOP(result),"a",1);
4338 emitcode("pop","acc");
4339 if (AOP_SIZE(result) >= 3) {
4340 lbl = newiTempLabel(NULL);
4341 emitcode("jnb","F0,!tlabel",lbl->key+100);
4342 emitcode("cpl","a");
4343 emitcode("addc","a,#0");
4344 emitcode("","!tlabeldef", lbl->key+100);
4345 aopPut(AOP(result),"a",2);
4347 emitcode("pop","acc");
4348 if (AOP_SIZE(result) >= 4) {
4349 lbl = newiTempLabel(NULL);
4350 emitcode("jnb","F0,!tlabel",lbl->key+100);
4351 emitcode("cpl","a");
4352 emitcode("addc","a,#0");
4353 emitcode("","!tlabeldef", lbl->key+100);
4354 aopPut(AOP(result),"a",3);
4356 if (AOP_TYPE(result) == AOP_ACC)
4358 /* We stashed the result away above. */
4359 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4363 freeAsmop (result, NULL, ic, TRUE);
4365 /* restore EA bit in F1 */
4366 lbl = newiTempLabel(NULL);
4367 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4368 emitcode ("setb","EA");
4369 emitcode("","!tlabeldef",lbl->key+100);
4373 /*-----------------------------------------------------------------*/
4374 /* genMult - generates code for multiplication */
4375 /*-----------------------------------------------------------------*/
4377 genMult (iCode * ic)
4379 operand *left = IC_LEFT (ic);
4380 operand *right = IC_RIGHT (ic);
4381 operand *result = IC_RESULT (ic);
4383 D (emitcode (";", "genMult "););
4385 /* assign the amsops */
4388 /* special cases first */
4390 if (AOP_TYPE (left) == AOP_CRY &&
4391 AOP_TYPE (right) == AOP_CRY)
4393 genMultbits (left, right, result, ic);
4397 /* if both are of size == 1 */
4398 if (AOP_SIZE (left) == 1 &&
4399 AOP_SIZE (right) == 1)
4401 genMultOneByte (left, right, result, ic);
4405 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4406 /* use the ds390 ARITHMETIC accel UNIT */
4407 genMultTwoByte (left, right, result, ic);
4410 /* should have been converted to function call */
4414 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4415 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4416 freeAsmop (result, NULL, ic, TRUE);
4419 /*-----------------------------------------------------------------*/
4420 /* genDivbits :- division of bits */
4421 /*-----------------------------------------------------------------*/
4423 genDivbits (operand * left,
4431 /* the result must be bit */
4432 LOAD_AB_FOR_DIV (left, right, l);
4433 emitcode ("div", "ab");
4434 emitcode ("rrc", "a");
4435 aopOp(result, ic, TRUE, FALSE);
4437 aopPut (AOP (result), "c", 0);
4440 /*-----------------------------------------------------------------*/
4441 /* genDivOneByte : 8 bit division */
4442 /*-----------------------------------------------------------------*/
4444 genDivOneByte (operand * left,
4449 sym_link *opetype = operandType (result);
4455 /* signed or unsigned */
4456 if (SPEC_USIGN (opetype))
4458 /* unsigned is easy */
4459 LOAD_AB_FOR_DIV (left, right, l);
4460 emitcode ("div", "ab");
4463 aopOp(result, ic, TRUE, FALSE);
4464 aopPut (AOP (result), "a", 0);
4467 size = AOP_SIZE (result) - 1;
4471 aopPut (AOP (result), zero, offset++);
4476 /* signed is a little bit more difficult */
4478 /* save the signs of the operands */
4479 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4481 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4482 emitcode ("push", "acc"); /* save it on the stack */
4484 /* now sign adjust for both left & right */
4485 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4487 lbl = newiTempLabel (NULL);
4488 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4489 emitcode ("cpl", "a");
4490 emitcode ("inc", "a");
4491 emitcode ("", "!tlabeldef", (lbl->key + 100));
4492 emitcode ("mov", "b,a");
4494 /* sign adjust left side */
4495 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4498 lbl = newiTempLabel (NULL);
4499 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4500 emitcode ("cpl", "a");
4501 emitcode ("inc", "a");
4502 emitcode ("", "!tlabeldef", (lbl->key + 100));
4504 /* now the division */
4505 emitcode ("nop", "; workaround for DS80C390 div bug.");
4506 emitcode ("div", "ab");
4507 /* we are interested in the lower order
4509 emitcode ("mov", "b,a");
4510 lbl = newiTempLabel (NULL);
4511 emitcode ("pop", "acc");
4512 /* if there was an over flow we don't
4513 adjust the sign of the result */
4514 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4515 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4517 emitcode ("clr", "a");
4518 emitcode ("subb", "a,b");
4519 emitcode ("mov", "b,a");
4520 emitcode ("", "!tlabeldef", (lbl->key + 100));
4522 /* now we are done */
4523 _G.accInUse++; _G.bInUse++;
4524 aopOp(result, ic, TRUE, FALSE);
4526 aopPut (AOP (result), "b", 0);
4528 size = AOP_SIZE (result) - 1;
4532 emitcode ("mov", "c,b.7");
4533 emitcode ("subb", "a,acc");
4537 aopPut (AOP (result), "a", offset++);
4539 _G.accInUse--; _G.bInUse--;
4543 /*-----------------------------------------------------------------*/
4544 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4545 /*-----------------------------------------------------------------*/
4546 static void genDivTwoByte (operand *left, operand *right,
4547 operand *result, iCode *ic)
4549 sym_link *retype = getSpec(operandType(right));
4550 sym_link *letype = getSpec(operandType(left));
4551 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4554 /* save EA bit in F1 */
4555 lbl = newiTempLabel(NULL);
4556 emitcode ("setb","F1");
4557 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4558 emitcode ("clr","F1");
4559 emitcode("","!tlabeldef",lbl->key+100);
4561 /* load up MA with left */
4563 emitcode("clr","F0");
4564 lbl = newiTempLabel(NULL);
4565 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4566 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4567 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4568 emitcode ("xch", "a,b");
4569 emitcode ("cpl","a");
4570 emitcode ("add", "a,#1");
4571 emitcode ("xch", "a,b");
4572 emitcode ("cpl", "a"); // msb
4573 emitcode ("addc","a,#0");
4574 emitcode ("setb","F0");
4575 emitcode ("","!tlabeldef",lbl->key+100);
4576 emitcode ("mov","ma,b");
4577 emitcode ("mov","ma,a");
4579 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4580 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4583 /* load up MB with right */
4585 if (AOP_TYPE(right) == AOP_LIT) {
4586 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4588 lbl = newiTempLabel(NULL);
4589 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4590 emitcode("setb","F0");
4591 emitcode ("","!tlabeldef",lbl->key+100);
4594 emitcode ("mov","mb,#!constbyte",val & 0xff);
4595 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4597 lbl = newiTempLabel(NULL);
4598 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4599 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4600 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4601 emitcode ("xch", "a,b");
4602 emitcode ("cpl","a");
4603 emitcode ("add", "a,#1");
4604 emitcode ("xch", "a,b");
4605 emitcode ("cpl", "a"); // msb
4606 emitcode ("addc", "a,#0");
4607 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4608 emitcode ("setb","F0");
4609 emitcode ("","!tlabeldef",lbl->key+100);
4610 emitcode ("mov","mb,b");
4611 emitcode ("mov","mb,a");
4614 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4615 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4618 /* wait for multiplication to finish */
4619 lbl = newiTempLabel(NULL);
4620 emitcode("","!tlabeldef", lbl->key+100);
4621 emitcode("mov","a,mcnt1");
4622 emitcode("anl","a,#0x80");
4623 emitcode("jnz","!tlabel",lbl->key+100);
4625 freeAsmop (left, NULL, ic, TRUE);
4626 freeAsmop (right, NULL, ic,TRUE);
4627 aopOp(result, ic, TRUE, FALSE);
4629 /* if unsigned then simple */
4631 aopPut(AOP(result),"ma",1);
4632 aopPut(AOP(result),"ma",0);
4634 emitcode("push","ma");
4636 /* negate result if needed */
4637 lbl = newiTempLabel(NULL);
4638 emitcode("jnb","F0,!tlabel",lbl->key+100);
4639 emitcode("cpl","a");
4640 emitcode("add","a,#1");
4641 emitcode("","!tlabeldef", lbl->key+100);
4642 aopPut(AOP(result),"a",0);
4643 emitcode("pop","acc");
4644 lbl = newiTempLabel(NULL);
4645 emitcode("jnb","F0,!tlabel",lbl->key+100);
4646 emitcode("cpl","a");
4647 emitcode("addc","a,#0");
4648 emitcode("","!tlabeldef", lbl->key+100);
4649 aopPut(AOP(result),"a",1);
4651 freeAsmop (result, NULL, ic, TRUE);
4652 /* restore EA bit in F1 */
4653 lbl = newiTempLabel(NULL);
4654 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4655 emitcode ("setb","EA");
4656 emitcode("","!tlabeldef",lbl->key+100);
4660 /*-----------------------------------------------------------------*/
4661 /* genDiv - generates code for division */
4662 /*-----------------------------------------------------------------*/
4666 operand *left = IC_LEFT (ic);
4667 operand *right = IC_RIGHT (ic);
4668 operand *result = IC_RESULT (ic);
4670 D (emitcode (";", "genDiv "););
4672 /* assign the amsops */
4675 /* special cases first */
4677 if (AOP_TYPE (left) == AOP_CRY &&
4678 AOP_TYPE (right) == AOP_CRY)
4680 genDivbits (left, right, result, ic);
4684 /* if both are of size == 1 */
4685 if (AOP_SIZE (left) == 1 &&
4686 AOP_SIZE (right) == 1)
4688 genDivOneByte (left, right, result, ic);
4692 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4693 /* use the ds390 ARITHMETIC accel UNIT */
4694 genDivTwoByte (left, right, result, ic);
4697 /* should have been converted to function call */
4700 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4701 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4702 freeAsmop (result, NULL, ic, TRUE);
4705 /*-----------------------------------------------------------------*/
4706 /* genModbits :- modulus of bits */
4707 /*-----------------------------------------------------------------*/
4709 genModbits (operand * left,
4717 /* the result must be bit */
4718 LOAD_AB_FOR_DIV (left, right, l);
4719 emitcode ("div", "ab");
4720 emitcode ("mov", "a,b");
4721 emitcode ("rrc", "a");
4722 aopOp(result, ic, TRUE, FALSE);
4723 aopPut (AOP (result), "c", 0);
4726 /*-----------------------------------------------------------------*/
4727 /* genModOneByte : 8 bit modulus */
4728 /*-----------------------------------------------------------------*/
4730 genModOneByte (operand * left,
4735 sym_link *opetype = operandType (result);
4739 /* signed or unsigned */
4740 if (SPEC_USIGN (opetype))
4742 /* unsigned is easy */
4743 LOAD_AB_FOR_DIV (left, right, l);
4744 emitcode ("div", "ab");
4745 aopOp(result, ic, TRUE, FALSE);
4746 aopPut (AOP (result), "b", 0);
4750 /* signed is a little bit more difficult */
4752 /* save the signs of the operands */
4753 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4756 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4757 emitcode ("push", "acc"); /* save it on the stack */
4759 /* now sign adjust for both left & right */
4760 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4763 lbl = newiTempLabel (NULL);
4764 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4765 emitcode ("cpl", "a");
4766 emitcode ("inc", "a");
4767 emitcode ("", "!tlabeldef", (lbl->key + 100));
4768 emitcode ("mov", "b,a");
4770 /* sign adjust left side */
4771 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4774 lbl = newiTempLabel (NULL);
4775 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4776 emitcode ("cpl", "a");
4777 emitcode ("inc", "a");
4778 emitcode ("", "!tlabeldef", (lbl->key + 100));
4780 /* now the multiplication */
4781 emitcode ("nop", "; workaround for DS80C390 div bug.");
4782 emitcode ("div", "ab");
4783 /* we are interested in the lower order
4785 lbl = newiTempLabel (NULL);
4786 emitcode ("pop", "acc");
4787 /* if there was an over flow we don't
4788 adjust the sign of the result */
4789 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4790 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4792 emitcode ("clr", "a");
4793 emitcode ("subb", "a,b");
4794 emitcode ("mov", "b,a");
4795 emitcode ("", "!tlabeldef", (lbl->key + 100));
4798 /* now we are done */
4799 aopOp(result, ic, TRUE, FALSE);
4800 aopPut (AOP (result), "b", 0);
4805 /*-----------------------------------------------------------------*/
4806 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4807 /*-----------------------------------------------------------------*/
4808 static void genModTwoByte (operand *left, operand *right,
4809 operand *result, iCode *ic)
4811 sym_link *retype = getSpec(operandType(right));
4812 sym_link *letype = getSpec(operandType(left));
4813 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4816 /* load up MA with left */
4817 /* save EA bit in F1 */
4818 lbl = newiTempLabel(NULL);
4819 emitcode ("setb","F1");
4820 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4821 emitcode ("clr","F1");
4822 emitcode("","!tlabeldef",lbl->key+100);
4825 lbl = newiTempLabel(NULL);
4826 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4827 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4828 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4829 emitcode ("xch", "a,b");
4830 emitcode ("cpl","a");
4831 emitcode ("add", "a,#1");
4832 emitcode ("xch", "a,b");
4833 emitcode ("cpl", "a"); // msb
4834 emitcode ("addc","a,#0");
4835 emitcode ("","!tlabeldef",lbl->key+100);
4836 emitcode ("mov","ma,b");
4837 emitcode ("mov","ma,a");
4839 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4840 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4843 /* load up MB with right */
4845 if (AOP_TYPE(right) == AOP_LIT) {
4846 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4850 emitcode ("mov","mb,#!constbyte",val & 0xff);
4851 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4853 lbl = newiTempLabel(NULL);
4854 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4855 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4856 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4857 emitcode ("xch", "a,b");
4858 emitcode ("cpl","a");
4859 emitcode ("add", "a,#1");
4860 emitcode ("xch", "a,b");
4861 emitcode ("cpl", "a"); // msb
4862 emitcode ("addc", "a,#0");
4863 emitcode ("","!tlabeldef",lbl->key+100);
4864 emitcode ("mov","mb,b");
4865 emitcode ("mov","mb,a");
4868 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4869 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4872 /* wait for multiplication to finish */
4873 lbl = newiTempLabel(NULL);
4874 emitcode("","!tlabeldef", lbl->key+100);
4875 emitcode("mov","a,mcnt1");
4876 emitcode("anl","a,#0x80");
4877 emitcode("jnz","!tlabel",lbl->key+100);
4879 freeAsmop (left, NULL, ic, TRUE);
4880 freeAsmop (right, NULL, ic,TRUE);
4881 aopOp(result, ic, TRUE, FALSE);
4883 aopPut(AOP(result),"mb",1);
4884 aopPut(AOP(result),"mb",0);
4885 freeAsmop (result, NULL, ic, TRUE);
4887 /* restore EA bit in F1 */
4888 lbl = newiTempLabel(NULL);
4889 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4890 emitcode ("setb","EA");
4891 emitcode("","!tlabeldef",lbl->key+100);
4895 /*-----------------------------------------------------------------*/
4896 /* genMod - generates code for division */
4897 /*-----------------------------------------------------------------*/
4901 operand *left = IC_LEFT (ic);
4902 operand *right = IC_RIGHT (ic);
4903 operand *result = IC_RESULT (ic);
4905 D (emitcode (";", "genMod "); );
4907 /* assign the amsops */
4910 /* special cases first */
4912 if (AOP_TYPE (left) == AOP_CRY &&
4913 AOP_TYPE (right) == AOP_CRY)
4915 genModbits (left, right, result, ic);
4919 /* if both are of size == 1 */
4920 if (AOP_SIZE (left) == 1 &&
4921 AOP_SIZE (right) == 1)
4923 genModOneByte (left, right, result, ic);
4927 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4928 /* use the ds390 ARITHMETIC accel UNIT */
4929 genModTwoByte (left, right, result, ic);
4933 /* should have been converted to function call */
4937 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4939 freeAsmop (result, NULL, ic, TRUE);
4942 /*-----------------------------------------------------------------*/
4943 /* genIfxJump :- will create a jump depending on the ifx */
4944 /*-----------------------------------------------------------------*/
4946 genIfxJump (iCode * ic, char *jval)
4949 symbol *tlbl = newiTempLabel (NULL);
4952 D (emitcode (";", "genIfxJump ");
4955 /* if true label then we jump if condition
4959 jlbl = IC_TRUE (ic);
4960 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4961 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4965 /* false label is present */
4966 jlbl = IC_FALSE (ic);
4967 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4968 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4970 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4971 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
4973 emitcode (inst, "!tlabel", tlbl->key + 100);
4974 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
4975 emitcode ("", "!tlabeldef", tlbl->key + 100);
4977 /* mark the icode as generated */
4981 /*-----------------------------------------------------------------*/
4982 /* genCmp :- greater or less than comparison */
4983 /*-----------------------------------------------------------------*/
4985 genCmp (operand * left, operand * right,
4986 iCode * ic, iCode * ifx, int sign)
4988 int size, offset = 0;
4989 unsigned long lit = 0L;
4992 D (emitcode (";", "genCmp");
4995 result = IC_RESULT (ic);
4997 /* if left & right are bit variables */
4998 if (AOP_TYPE (left) == AOP_CRY &&
4999 AOP_TYPE (right) == AOP_CRY)
5001 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5002 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5006 /* subtract right from left if at the
5007 end the carry flag is set then we know that
5008 left is greater than right */
5009 size = max (AOP_SIZE (left), AOP_SIZE (right));
5011 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5012 if ((size == 1) && !sign &&
5013 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5015 symbol *lbl = newiTempLabel (NULL);
5016 emitcode ("cjne", "%s,%s,!tlabel",
5017 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5018 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5020 emitcode ("", "!tlabeldef", lbl->key + 100);
5024 if (AOP_TYPE (right) == AOP_LIT)
5026 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5027 /* optimize if(x < 0) or if(x >= 0) */
5036 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5038 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5039 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5041 aopOp (result, ic, FALSE, FALSE);
5043 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5045 freeAsmop (result, NULL, ic, TRUE);
5046 genIfxJump (ifx, "acc.7");
5051 emitcode ("rlc", "a");
5053 goto release_freedLR;
5061 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5062 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5063 emitcode (";", "genCmp #2");
5064 if (sign && (size == 0))
5066 emitcode (";", "genCmp #3");
5067 emitcode ("xrl", "a,#0x80");
5068 if (AOP_TYPE (right) == AOP_LIT)
5070 unsigned long lit = (unsigned long)
5071 floatFromVal (AOP (right)->aopu.aop_lit);
5072 emitcode (";", "genCmp #3.1");
5073 emitcode ("subb", "a,#!constbyte",
5074 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5078 emitcode (";", "genCmp #3.2");
5079 if (AOP_NEEDSACC (right))
5081 emitcode ("push", "acc");
5083 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5084 FALSE, FALSE, FALSE));
5085 emitcode ("xrl", "b,#0x80");
5086 if (AOP_NEEDSACC (right))
5088 emitcode ("pop", "acc");
5090 emitcode ("subb", "a,b");
5097 emitcode (";", "genCmp #4");
5098 if (AOP_NEEDSACC (right))
5101 emitcode (";", "genCmp #4.1");
5102 emitcode ("xch", "a, b");
5103 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5104 emitcode ("xch", "a, b");
5109 emitcode (";", "genCmp #4.2");
5110 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5113 emitcode ("subb", "a,%s", s);
5120 /* Don't need the left & right operands any more; do need the result. */
5121 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5124 aopOp (result, ic, FALSE, FALSE);
5128 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5134 /* if the result is used in the next
5135 ifx conditional branch then generate
5136 code a little differently */
5139 genIfxJump (ifx, "c");
5145 /* leave the result in acc */
5147 freeAsmop (result, NULL, ic, TRUE);
5150 /*-----------------------------------------------------------------*/
5151 /* genCmpGt :- greater than comparison */
5152 /*-----------------------------------------------------------------*/
5154 genCmpGt (iCode * ic, iCode * ifx)
5156 operand *left, *right;
5157 sym_link *letype, *retype;
5160 D (emitcode (";", "genCmpGt ");
5163 left = IC_LEFT (ic);
5164 right = IC_RIGHT (ic);
5166 letype = getSpec (operandType (left));
5167 retype = getSpec (operandType (right));
5168 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5170 /* assign the left & right amsops */
5173 genCmp (right, left, ic, ifx, sign);
5176 /*-----------------------------------------------------------------*/
5177 /* genCmpLt - less than comparisons */
5178 /*-----------------------------------------------------------------*/
5180 genCmpLt (iCode * ic, iCode * ifx)
5182 operand *left, *right;
5183 sym_link *letype, *retype;
5186 D (emitcode (";", "genCmpLt "););
5188 left = IC_LEFT (ic);
5189 right = IC_RIGHT (ic);
5191 letype = getSpec (operandType (left));
5192 retype = getSpec (operandType (right));
5193 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5195 /* assign the left & right amsops */
5198 genCmp (left, right, ic, ifx, sign);
5201 /*-----------------------------------------------------------------*/
5202 /* gencjneshort - compare and jump if not equal */
5203 /*-----------------------------------------------------------------*/
5205 gencjneshort (operand * left, operand * right, symbol * lbl)
5207 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5209 unsigned long lit = 0L;
5211 D (emitcode (";", "gencjneshort");
5214 /* if the left side is a literal or
5215 if the right is in a pointer register and left
5217 if ((AOP_TYPE (left) == AOP_LIT) ||
5218 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5225 if (AOP_TYPE (right) == AOP_LIT)
5226 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5228 if (opIsGptr (left) || opIsGptr (right))
5230 /* We are comparing a generic pointer to something.
5231 * Exclude the generic type byte from the comparison.
5234 D (emitcode (";", "cjneshort: generic ptr special case.");
5239 /* if the right side is a literal then anything goes */
5240 if (AOP_TYPE (right) == AOP_LIT &&
5241 AOP_TYPE (left) != AOP_DIR)
5245 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5247 emitcode ("cjne", "a,%s,!tlabel",
5248 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5254 /* if the right side is in a register or in direct space or
5255 if the left is a pointer register & right is not */
5256 else if (AOP_TYPE (right) == AOP_REG ||
5257 AOP_TYPE (right) == AOP_DIR ||
5258 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5259 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5263 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5264 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5265 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5266 emitcode ("jnz", "!tlabel", lbl->key + 100);
5268 emitcode ("cjne", "a,%s,!tlabel",
5269 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5276 /* right is a pointer reg need both a & b */
5279 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5280 if (strcmp (l, "b"))
5281 emitcode ("mov", "b,%s", l);
5282 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5283 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5289 /*-----------------------------------------------------------------*/
5290 /* gencjne - compare and jump if not equal */
5291 /*-----------------------------------------------------------------*/
5293 gencjne (operand * left, operand * right, symbol * lbl)
5295 symbol *tlbl = newiTempLabel (NULL);
5297 D (emitcode (";", "gencjne");
5300 gencjneshort (left, right, lbl);
5302 emitcode ("mov", "a,%s", one);
5303 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5304 emitcode ("", "!tlabeldef", lbl->key + 100);
5305 emitcode ("clr", "a");
5306 emitcode ("", "!tlabeldef", tlbl->key + 100);
5309 /*-----------------------------------------------------------------*/
5310 /* genCmpEq - generates code for equal to */
5311 /*-----------------------------------------------------------------*/
5313 genCmpEq (iCode * ic, iCode * ifx)
5315 operand *left, *right, *result;
5317 D (emitcode (";", "genCmpEq ");
5321 AOP_SET_LOCALS (ic);
5323 /* if literal, literal on the right or
5324 if the right is in a pointer register and left
5326 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5327 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5329 operand *t = IC_RIGHT (ic);
5330 IC_RIGHT (ic) = IC_LEFT (ic);
5334 if (ifx && /* !AOP_SIZE(result) */
5335 OP_SYMBOL (result) &&
5336 OP_SYMBOL (result)->regType == REG_CND)
5339 /* if they are both bit variables */
5340 if (AOP_TYPE (left) == AOP_CRY &&
5341 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5343 if (AOP_TYPE (right) == AOP_LIT)
5345 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5348 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5349 emitcode ("cpl", "c");
5353 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5357 emitcode ("clr", "c");
5359 /* AOP_TYPE(right) == AOP_CRY */
5363 symbol *lbl = newiTempLabel (NULL);
5364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5365 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5366 emitcode ("cpl", "c");
5367 emitcode ("", "!tlabeldef", (lbl->key + 100));
5369 /* if true label then we jump if condition
5371 tlbl = newiTempLabel (NULL);
5374 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5375 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5379 emitcode ("jc", "!tlabel", tlbl->key + 100);
5380 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5382 emitcode ("", "!tlabeldef", tlbl->key + 100);
5386 tlbl = newiTempLabel (NULL);
5387 gencjneshort (left, right, tlbl);
5390 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5391 emitcode ("", "!tlabeldef", tlbl->key + 100);
5395 symbol *lbl = newiTempLabel (NULL);
5396 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5397 emitcode ("", "!tlabeldef", tlbl->key + 100);
5398 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5399 emitcode ("", "!tlabeldef", lbl->key + 100);
5402 /* mark the icode as generated */
5405 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5406 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5410 /* if they are both bit variables */
5411 if (AOP_TYPE (left) == AOP_CRY &&
5412 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5414 if (AOP_TYPE (right) == AOP_LIT)
5416 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5419 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5420 emitcode ("cpl", "c");
5424 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5428 emitcode ("clr", "c");
5430 /* AOP_TYPE(right) == AOP_CRY */
5434 symbol *lbl = newiTempLabel (NULL);
5435 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5436 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5437 emitcode ("cpl", "c");
5438 emitcode ("", "!tlabeldef", (lbl->key + 100));
5441 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5442 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5444 aopOp (result, ic, TRUE, FALSE);
5447 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5454 genIfxJump (ifx, "c");
5457 /* if the result is used in an arithmetic operation
5458 then put the result in place */
5463 gencjne (left, right, newiTempLabel (NULL));
5465 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5466 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5468 aopOp (result, ic, TRUE, FALSE);
5470 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5472 aopPut (AOP (result), "a", 0);
5477 genIfxJump (ifx, "a");
5480 /* if the result is used in an arithmetic operation
5481 then put the result in place */
5482 if (AOP_TYPE (result) != AOP_CRY)
5484 /* leave the result in acc */
5488 freeAsmop (result, NULL, ic, TRUE);
5491 /*-----------------------------------------------------------------*/
5492 /* ifxForOp - returns the icode containing the ifx for operand */
5493 /*-----------------------------------------------------------------*/
5495 ifxForOp (operand * op, iCode * ic)
5497 /* if true symbol then needs to be assigned */
5498 if (IS_TRUE_SYMOP (op))
5501 /* if this has register type condition and
5502 the next instruction is ifx with the same operand
5503 and live to of the operand is upto the ifx only then */
5505 ic->next->op == IFX &&
5506 IC_COND (ic->next)->key == op->key &&
5507 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5512 /*-----------------------------------------------------------------*/
5513 /* hasInc - operand is incremented before any other use */
5514 /*-----------------------------------------------------------------*/
5516 hasInc (operand *op, iCode *ic)
5518 sym_link *type = operandType(op);
5519 sym_link *retype = getSpec (type);
5520 iCode *lic = ic->next;
5523 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5524 if (!IS_SYMOP(op)) return NULL;
5526 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5527 isize = getSize(type->next);
5529 /* if operand of the form op = op + <sizeof *op> */
5530 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5531 isOperandEqual(IC_RESULT(lic),op) &&
5532 isOperandLiteral(IC_RIGHT(lic)) &&
5533 operandLitValue(IC_RIGHT(lic)) == isize) {
5536 /* if the operand used or deffed */
5537 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5540 /* if GOTO or IFX */
5541 if (lic->op == IFX || lic->op == GOTO) break;
5547 /*-----------------------------------------------------------------*/
5548 /* genAndOp - for && operation */
5549 /*-----------------------------------------------------------------*/
5551 genAndOp (iCode * ic)
5553 operand *left, *right, *result;
5556 D (emitcode (";", "genAndOp "););
5558 /* note here that && operations that are in an
5559 if statement are taken away by backPatchLabels
5560 only those used in arthmetic operations remain */
5562 AOP_SET_LOCALS (ic);
5564 /* if both are bit variables */
5565 if (AOP_TYPE (left) == AOP_CRY &&
5566 AOP_TYPE (right) == AOP_CRY)
5568 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5569 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5573 aopOp (result,ic,FALSE, FALSE);
5578 tlbl = newiTempLabel (NULL);
5580 emitcode ("jz", "!tlabel", tlbl->key + 100);
5582 emitcode ("", "!tlabeldef", tlbl->key + 100);
5583 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5584 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5586 aopOp (result,ic,FALSE, FALSE);
5589 freeAsmop (result, NULL, ic, TRUE);
5593 /*-----------------------------------------------------------------*/
5594 /* genOrOp - for || operation */
5595 /*-----------------------------------------------------------------*/
5597 genOrOp (iCode * ic)
5599 operand *left, *right, *result;
5602 D (emitcode (";", "genOrOp "););
5604 /* note here that || operations that are in an
5605 if statement are taken away by backPatchLabels
5606 only those used in arthmetic operations remain */
5608 AOP_SET_LOCALS (ic);
5610 /* if both are bit variables */
5611 if (AOP_TYPE (left) == AOP_CRY &&
5612 AOP_TYPE (right) == AOP_CRY)
5614 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5615 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5616 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5617 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5619 aopOp (result,ic,FALSE, FALSE);
5625 tlbl = newiTempLabel (NULL);
5627 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5629 emitcode ("", "!tlabeldef", tlbl->key + 100);
5630 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5631 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5633 aopOp (result,ic,FALSE, FALSE);
5638 freeAsmop (result, NULL, ic, TRUE);
5641 /*-----------------------------------------------------------------*/
5642 /* isLiteralBit - test if lit == 2^n */
5643 /*-----------------------------------------------------------------*/
5645 isLiteralBit (unsigned long lit)
5647 unsigned long pw[32] =
5648 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5649 0x100L, 0x200L, 0x400L, 0x800L,
5650 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5651 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5652 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5653 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5654 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5657 for (idx = 0; idx < 32; idx++)
5663 /*-----------------------------------------------------------------*/
5664 /* continueIfTrue - */
5665 /*-----------------------------------------------------------------*/
5667 continueIfTrue (iCode * ic)
5670 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5674 /*-----------------------------------------------------------------*/
5676 /*-----------------------------------------------------------------*/
5678 jumpIfTrue (iCode * ic)
5681 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5685 /*-----------------------------------------------------------------*/
5686 /* jmpTrueOrFalse - */
5687 /*-----------------------------------------------------------------*/
5689 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5691 // ugly but optimized by peephole
5694 symbol *nlbl = newiTempLabel (NULL);
5695 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5696 emitcode ("", "!tlabeldef", tlbl->key + 100);
5697 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5698 emitcode ("", "!tlabeldef", nlbl->key + 100);
5702 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5703 emitcode ("", "!tlabeldef", tlbl->key + 100);
5708 // Generate code to perform a bit-wise logic operation
5709 // on two operands in far space (assumed to already have been
5710 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5711 // in far space. This requires pushing the result on the stack
5712 // then popping it into the result.
5714 genFarFarLogicOp(iCode *ic, char *logicOp)
5716 int size, resultSize, compSize;
5720 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5721 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5722 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5724 _startLazyDPSEvaluation();
5725 for (size = compSize; (size--); offset++)
5727 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5728 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5729 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5731 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5732 emitcode ("push", "acc");
5734 _endLazyDPSEvaluation();
5736 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5737 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5738 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5740 resultSize = AOP_SIZE(IC_RESULT(ic));
5742 ADJUST_PUSHED_RESULT(compSize, resultSize);
5744 _startLazyDPSEvaluation();
5747 emitcode ("pop", "acc");
5748 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5750 _endLazyDPSEvaluation();
5751 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5755 /*-----------------------------------------------------------------*/
5756 /* genAnd - code for and */
5757 /*-----------------------------------------------------------------*/
5759 genAnd (iCode * ic, iCode * ifx)
5761 operand *left, *right, *result;
5762 int size, offset = 0;
5763 unsigned long lit = 0L;
5768 D (emitcode (";", "genAnd "););
5770 AOP_OP_3_NOFATAL (ic, pushResult);
5771 AOP_SET_LOCALS (ic);
5775 genFarFarLogicOp(ic, "anl");
5780 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5782 AOP_TYPE (left), AOP_TYPE (right));
5783 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5785 AOP_SIZE (left), AOP_SIZE (right));
5788 /* if left is a literal & right is not then exchange them */
5789 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5790 #ifdef LOGIC_OPS_BROKEN
5791 || AOP_NEEDSACC (left)
5795 operand *tmp = right;
5800 /* if result = right then exchange them */
5801 if (sameRegs (AOP (result), AOP (right)))
5803 operand *tmp = right;
5808 /* if right is bit then exchange them */
5809 if (AOP_TYPE (right) == AOP_CRY &&
5810 AOP_TYPE (left) != AOP_CRY)
5812 operand *tmp = right;
5816 if (AOP_TYPE (right) == AOP_LIT)
5817 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5819 size = AOP_SIZE (result);
5822 // result = bit & yy;
5823 if (AOP_TYPE (left) == AOP_CRY)
5825 // c = bit & literal;
5826 if (AOP_TYPE (right) == AOP_LIT)
5830 if (size && sameRegs (AOP (result), AOP (left)))
5833 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5838 if (size && (AOP_TYPE (result) == AOP_CRY))
5840 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5843 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5848 emitcode ("clr", "c");
5853 if (AOP_TYPE (right) == AOP_CRY)
5856 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5857 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5862 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5864 emitcode ("rrc", "a");
5865 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5873 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5874 genIfxJump (ifx, "c");
5878 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5879 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5880 if ((AOP_TYPE (right) == AOP_LIT) &&
5881 (AOP_TYPE (result) == AOP_CRY) &&
5882 (AOP_TYPE (left) != AOP_CRY))
5884 int posbit = isLiteralBit (lit);
5889 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5892 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5898 sprintf (buffer, "acc.%d", posbit & 0x07);
5899 genIfxJump (ifx, buffer);
5906 symbol *tlbl = newiTempLabel (NULL);
5907 int sizel = AOP_SIZE (left);
5909 emitcode ("setb", "c");
5912 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5914 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5916 if ((posbit = isLiteralBit (bytelit)) != 0)
5917 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5920 if (bytelit != 0x0FFL)
5921 emitcode ("anl", "a,%s",
5922 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5923 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5928 // bit = left & literal
5931 emitcode ("clr", "c");
5932 emitcode ("", "!tlabeldef", tlbl->key + 100);
5934 // if(left & literal)
5938 jmpTrueOrFalse (ifx, tlbl);
5946 /* if left is same as result */
5947 if (sameRegs (AOP (result), AOP (left)))
5949 for (; size--; offset++)
5951 if (AOP_TYPE (right) == AOP_LIT)
5953 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5955 else if (bytelit == 0)
5956 aopPut (AOP (result), zero, offset);
5957 else if (IS_AOP_PREG (result))
5959 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5960 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5961 aopPut (AOP (result), "a", offset);
5964 emitcode ("anl", "%s,%s",
5965 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5966 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5970 if (AOP_TYPE (left) == AOP_ACC)
5971 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5974 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5975 if (IS_AOP_PREG (result))
5977 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5978 aopPut (AOP (result), "a", offset);
5982 emitcode ("anl", "%s,a",
5983 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5990 // left & result in different registers
5991 if (AOP_TYPE (result) == AOP_CRY)
5994 // if(size), result in bit
5995 // if(!size && ifx), conditional oper: if(left & right)
5996 symbol *tlbl = newiTempLabel (NULL);
5997 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5999 emitcode ("setb", "c");
6002 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6003 emitcode ("anl", "a,%s",
6004 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6006 if (AOP_TYPE(left)==AOP_ACC) {
6007 emitcode("mov", "b,a");
6008 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6009 emitcode("anl", "a,b");
6011 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6012 emitcode ("anl", "a,%s",
6013 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6016 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6022 emitcode ("", "!tlabeldef", tlbl->key + 100);
6026 jmpTrueOrFalse (ifx, tlbl);
6030 for (; (size--); offset++)
6033 // result = left & right
6034 if (AOP_TYPE (right) == AOP_LIT)
6036 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6038 aopPut (AOP (result),
6039 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6043 else if (bytelit == 0)
6045 aopPut (AOP (result), zero, offset);
6048 D (emitcode (";", "better literal AND."););
6049 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6050 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6051 FALSE, FALSE, FALSE));
6056 // faster than result <- left, anl result,right
6057 // and better if result is SFR
6058 if (AOP_TYPE (left) == AOP_ACC)
6060 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6061 FALSE, FALSE, FALSE));
6065 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6066 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6068 emitcode("mov", "b,a");
6072 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6073 emitcode ("anl", "a,%s", rOp);
6076 aopPut (AOP (result), "a", offset);
6082 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6083 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6084 freeAsmop (result, NULL, ic, TRUE);
6088 /*-----------------------------------------------------------------*/
6089 /* genOr - code for or */
6090 /*-----------------------------------------------------------------*/
6092 genOr (iCode * ic, iCode * ifx)
6094 operand *left, *right, *result;
6095 int size, offset = 0;
6096 unsigned long lit = 0L;
6099 D (emitcode (";", "genOr "););
6101 AOP_OP_3_NOFATAL (ic, pushResult);
6102 AOP_SET_LOCALS (ic);
6106 genFarFarLogicOp(ic, "orl");
6112 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6114 AOP_TYPE (left), AOP_TYPE (right));
6115 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6117 AOP_SIZE (left), AOP_SIZE (right));
6120 /* if left is a literal & right is not then exchange them */
6121 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6122 #ifdef LOGIC_OPS_BROKEN
6123 || AOP_NEEDSACC (left) // I think this is a net loss now.
6127 operand *tmp = right;
6132 /* if result = right then exchange them */
6133 if (sameRegs (AOP (result), AOP (right)))
6135 operand *tmp = right;
6140 /* if right is bit then exchange them */
6141 if (AOP_TYPE (right) == AOP_CRY &&
6142 AOP_TYPE (left) != AOP_CRY)
6144 operand *tmp = right;
6148 if (AOP_TYPE (right) == AOP_LIT)
6149 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6151 size = AOP_SIZE (result);
6155 if (AOP_TYPE (left) == AOP_CRY)
6157 if (AOP_TYPE (right) == AOP_LIT)
6159 // c = bit & literal;
6162 // lit != 0 => result = 1
6163 if (AOP_TYPE (result) == AOP_CRY)
6166 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6168 continueIfTrue (ifx);
6171 emitcode ("setb", "c");
6175 // lit == 0 => result = left
6176 if (size && sameRegs (AOP (result), AOP (left)))
6178 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6183 if (AOP_TYPE (right) == AOP_CRY)
6186 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6187 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6192 symbol *tlbl = newiTempLabel (NULL);
6193 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6194 emitcode ("setb", "c");
6195 emitcode ("jb", "%s,!tlabel",
6196 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6198 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6199 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6201 jmpTrueOrFalse (ifx, tlbl);
6207 emitcode ("", "!tlabeldef", tlbl->key + 100);
6216 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6217 genIfxJump (ifx, "c");
6221 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6222 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6223 if ((AOP_TYPE (right) == AOP_LIT) &&
6224 (AOP_TYPE (result) == AOP_CRY) &&
6225 (AOP_TYPE (left) != AOP_CRY))
6231 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6233 continueIfTrue (ifx);
6238 // lit = 0, result = boolean(left)
6240 emitcode ("setb", "c");
6244 symbol *tlbl = newiTempLabel (NULL);
6245 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6247 emitcode ("", "!tlabeldef", tlbl->key + 100);
6251 genIfxJump (ifx, "a");
6259 /* if left is same as result */
6260 if (sameRegs (AOP (result), AOP (left)))
6262 for (; size--; offset++)
6264 if (AOP_TYPE (right) == AOP_LIT)
6266 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6272 if (IS_AOP_PREG (left))
6274 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6275 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6276 aopPut (AOP (result), "a", offset);
6280 emitcode ("orl", "%s,%s",
6281 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6282 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6288 if (AOP_TYPE (left) == AOP_ACC)
6290 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6294 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6295 if (IS_AOP_PREG (left))
6297 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6298 aopPut (AOP (result), "a", offset);
6302 emitcode ("orl", "%s,a",
6303 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6311 // left & result in different registers
6312 if (AOP_TYPE (result) == AOP_CRY)
6315 // if(size), result in bit
6316 // if(!size && ifx), conditional oper: if(left | right)
6317 symbol *tlbl = newiTempLabel (NULL);
6318 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6320 emitcode ("setb", "c");
6323 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6324 emitcode ("orl", "a,%s",
6325 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6327 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6328 emitcode ("orl", "a,%s",
6329 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6331 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6337 emitcode ("", "!tlabeldef", tlbl->key + 100);
6341 jmpTrueOrFalse (ifx, tlbl);
6345 _startLazyDPSEvaluation();
6346 for (; (size--); offset++)
6349 // result = left & right
6350 if (AOP_TYPE (right) == AOP_LIT)
6352 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6354 aopPut (AOP (result),
6355 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6359 D (emitcode (";", "better literal OR."););
6360 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6361 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6362 FALSE, FALSE, FALSE));
6367 // faster than result <- left, anl result,right
6368 // and better if result is SFR
6369 if (AOP_TYPE (left) == AOP_ACC)
6371 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6372 FALSE, FALSE, FALSE));
6376 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6378 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6380 emitcode("mov", "b,a");
6384 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6385 emitcode ("orl", "a,%s", rOp);
6388 aopPut (AOP (result), "a", offset);
6390 _endLazyDPSEvaluation();
6395 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6396 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6397 freeAsmop (result, NULL, ic, TRUE);
6400 /*-----------------------------------------------------------------*/
6401 /* genXor - code for xclusive or */
6402 /*-----------------------------------------------------------------*/
6404 genXor (iCode * ic, iCode * ifx)
6406 operand *left, *right, *result;
6407 int size, offset = 0;
6408 unsigned long lit = 0L;
6411 D (emitcode (";", "genXor "););
6413 AOP_OP_3_NOFATAL (ic, pushResult);
6414 AOP_SET_LOCALS (ic);
6418 genFarFarLogicOp(ic, "xrl");
6423 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6425 AOP_TYPE (left), AOP_TYPE (right));
6426 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6428 AOP_SIZE (left), AOP_SIZE (right));
6431 /* if left is a literal & right is not ||
6432 if left needs acc & right does not */
6433 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6434 #ifdef LOGIC_OPS_BROKEN
6435 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6439 operand *tmp = right;
6444 /* if result = right then exchange them */
6445 if (sameRegs (AOP (result), AOP (right)))
6447 operand *tmp = right;
6452 /* if right is bit then exchange them */
6453 if (AOP_TYPE (right) == AOP_CRY &&
6454 AOP_TYPE (left) != AOP_CRY)
6456 operand *tmp = right;
6460 if (AOP_TYPE (right) == AOP_LIT)
6461 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6463 size = AOP_SIZE (result);
6467 if (AOP_TYPE (left) == AOP_CRY)
6469 if (AOP_TYPE (right) == AOP_LIT)
6471 // c = bit & literal;
6474 // lit>>1 != 0 => result = 1
6475 if (AOP_TYPE (result) == AOP_CRY)
6478 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6480 continueIfTrue (ifx);
6483 emitcode ("setb", "c");
6490 // lit == 0, result = left
6491 if (size && sameRegs (AOP (result), AOP (left)))
6493 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6497 // lit == 1, result = not(left)
6498 if (size && sameRegs (AOP (result), AOP (left)))
6500 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6505 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6506 emitcode ("cpl", "c");
6515 symbol *tlbl = newiTempLabel (NULL);
6516 if (AOP_TYPE (right) == AOP_CRY)
6519 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6523 int sizer = AOP_SIZE (right);
6525 // if val>>1 != 0, result = 1
6526 emitcode ("setb", "c");
6529 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6531 // test the msb of the lsb
6532 emitcode ("anl", "a,#0xfe");
6533 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6537 emitcode ("rrc", "a");
6539 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6540 emitcode ("cpl", "c");
6541 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6548 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6549 genIfxJump (ifx, "c");
6553 if (sameRegs (AOP (result), AOP (left)))
6555 /* if left is same as result */
6556 for (; size--; offset++)
6558 if (AOP_TYPE (right) == AOP_LIT)
6560 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6562 else if (IS_AOP_PREG (left))
6564 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6565 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6566 aopPut (AOP (result), "a", offset);
6569 emitcode ("xrl", "%s,%s",
6570 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6571 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6575 if (AOP_TYPE (left) == AOP_ACC)
6576 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6579 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6580 if (IS_AOP_PREG (left))
6582 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6583 aopPut (AOP (result), "a", offset);
6586 emitcode ("xrl", "%s,a",
6587 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6594 // left & result in different registers
6595 if (AOP_TYPE (result) == AOP_CRY)
6598 // if(size), result in bit
6599 // if(!size && ifx), conditional oper: if(left ^ right)
6600 symbol *tlbl = newiTempLabel (NULL);
6601 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6604 emitcode ("setb", "c");
6607 if ((AOP_TYPE (right) == AOP_LIT) &&
6608 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6610 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6614 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6615 emitcode ("xrl", "a,%s",
6616 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6618 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6619 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6621 emitcode("mov", "b,a");
6625 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6626 emitcode ("xrl", "a,%s", rOp);
6629 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6635 emitcode ("", "!tlabeldef", tlbl->key + 100);
6639 jmpTrueOrFalse (ifx, tlbl);
6643 for (; (size--); offset++)
6646 // result = left & right
6647 if (AOP_TYPE (right) == AOP_LIT)
6649 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6651 aopPut (AOP (result),
6652 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6656 D (emitcode (";", "better literal XOR."););
6657 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6658 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6659 FALSE, FALSE, FALSE));
6663 // faster than result <- left, anl result,right
6664 // and better if result is SFR
6665 if (AOP_TYPE (left) == AOP_ACC)
6667 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6668 FALSE, FALSE, FALSE));
6672 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6673 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6675 emitcode("mov", "b,a");
6679 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6680 emitcode ("xrl", "a,%s", rOp);
6683 aopPut (AOP (result), "a", offset);
6690 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6691 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6692 freeAsmop (result, NULL, ic, TRUE);
6695 /*-----------------------------------------------------------------*/
6696 /* genInline - write the inline code out */
6697 /*-----------------------------------------------------------------*/
6699 genInline (iCode * ic)
6701 char *buffer, *bp, *bp1;
6703 D (emitcode (";", "genInline ");
6706 _G.inLine += (!options.asmpeep);
6708 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6709 strcpy (buffer, IC_INLINE (ic));
6711 /* emit each line as a code */
6736 /* emitcode("",buffer); */
6737 _G.inLine -= (!options.asmpeep);
6740 /*-----------------------------------------------------------------*/
6741 /* genRRC - rotate right with carry */
6742 /*-----------------------------------------------------------------*/
6746 operand *left, *result;
6747 int size, offset = 0;
6750 D (emitcode (";", "genRRC ");
6753 /* rotate right with carry */
6754 left = IC_LEFT (ic);
6755 result = IC_RESULT (ic);
6756 aopOp (left, ic, FALSE, FALSE);
6757 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6759 /* move it to the result */
6760 size = AOP_SIZE (result);
6764 _startLazyDPSEvaluation ();
6767 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6769 emitcode ("rrc", "a");
6770 if (AOP_SIZE (result) > 1)
6771 aopPut (AOP (result), "a", offset--);
6773 _endLazyDPSEvaluation ();
6775 /* now we need to put the carry into the
6776 highest order byte of the result */
6777 if (AOP_SIZE (result) > 1)
6779 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6782 emitcode ("mov", "acc.7,c");
6783 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6784 freeAsmop (left, NULL, ic, TRUE);
6785 freeAsmop (result, NULL, ic, TRUE);
6788 /*-----------------------------------------------------------------*/
6789 /* genRLC - generate code for rotate left with carry */
6790 /*-----------------------------------------------------------------*/
6794 operand *left, *result;
6795 int size, offset = 0;
6798 D (emitcode (";", "genRLC ");
6801 /* rotate right with carry */
6802 left = IC_LEFT (ic);
6803 result = IC_RESULT (ic);
6804 aopOp (left, ic, FALSE, FALSE);
6805 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6807 /* move it to the result */
6808 size = AOP_SIZE (result);
6812 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6814 emitcode ("add", "a,acc");
6815 if (AOP_SIZE (result) > 1)
6817 aopPut (AOP (result), "a", offset++);
6820 _startLazyDPSEvaluation ();
6823 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6825 emitcode ("rlc", "a");
6826 if (AOP_SIZE (result) > 1)
6827 aopPut (AOP (result), "a", offset++);
6829 _endLazyDPSEvaluation ();
6831 /* now we need to put the carry into the
6832 highest order byte of the result */
6833 if (AOP_SIZE (result) > 1)
6835 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6838 emitcode ("mov", "acc.0,c");
6839 aopPut (AOP (result), "a", 0);
6840 freeAsmop (left, NULL, ic, TRUE);
6841 freeAsmop (result, NULL, ic, TRUE);
6844 /*-----------------------------------------------------------------*/
6845 /* genGetHbit - generates code get highest order bit */
6846 /*-----------------------------------------------------------------*/
6848 genGetHbit (iCode * ic)
6850 operand *left, *result;
6851 left = IC_LEFT (ic);
6852 result = IC_RESULT (ic);
6853 aopOp (left, ic, FALSE, FALSE);
6854 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6856 D (emitcode (";", "genGetHbit ");
6859 /* get the highest order byte into a */
6860 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6861 if (AOP_TYPE (result) == AOP_CRY)
6863 emitcode ("rlc", "a");
6868 emitcode ("rl", "a");
6869 emitcode ("anl", "a,#0x01");
6874 freeAsmop (left, NULL, ic, TRUE);
6875 freeAsmop (result, NULL, ic, TRUE);
6878 /*-----------------------------------------------------------------*/
6879 /* AccRol - rotate left accumulator by known count */
6880 /*-----------------------------------------------------------------*/
6882 AccRol (int shCount)
6884 shCount &= 0x0007; // shCount : 0..7
6891 emitcode ("rl", "a");
6894 emitcode ("rl", "a");
6895 emitcode ("rl", "a");
6898 emitcode ("swap", "a");
6899 emitcode ("rr", "a");
6902 emitcode ("swap", "a");
6905 emitcode ("swap", "a");
6906 emitcode ("rl", "a");
6909 emitcode ("rr", "a");
6910 emitcode ("rr", "a");
6913 emitcode ("rr", "a");
6918 /*-----------------------------------------------------------------*/
6919 /* AccLsh - left shift accumulator by known count */
6920 /*-----------------------------------------------------------------*/
6922 AccLsh (int shCount)
6927 emitcode ("add", "a,acc");
6928 else if (shCount == 2)
6930 emitcode ("add", "a,acc");
6931 emitcode ("add", "a,acc");
6935 /* rotate left accumulator */
6937 /* and kill the lower order bits */
6938 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
6943 /*-----------------------------------------------------------------*/
6944 /* AccRsh - right shift accumulator by known count */
6945 /*-----------------------------------------------------------------*/
6947 AccRsh (int shCount)
6954 emitcode ("rrc", "a");
6958 /* rotate right accumulator */
6959 AccRol (8 - shCount);
6960 /* and kill the higher order bits */
6961 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6966 #ifdef BETTER_LITERAL_SHIFT
6967 /*-----------------------------------------------------------------*/
6968 /* AccSRsh - signed right shift accumulator by known count */
6969 /*-----------------------------------------------------------------*/
6971 AccSRsh (int shCount)
6978 emitcode ("mov", "c,acc.7");
6979 emitcode ("rrc", "a");
6981 else if (shCount == 2)
6983 emitcode ("mov", "c,acc.7");
6984 emitcode ("rrc", "a");
6985 emitcode ("mov", "c,acc.7");
6986 emitcode ("rrc", "a");
6990 tlbl = newiTempLabel (NULL);
6991 /* rotate right accumulator */
6992 AccRol (8 - shCount);
6993 /* and kill the higher order bits */
6994 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6995 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
6996 emitcode ("orl", "a,#!constbyte",
6997 (unsigned char) ~SRMask[shCount]);
6998 emitcode ("", "!tlabeldef", tlbl->key + 100);
7004 #ifdef BETTER_LITERAL_SHIFT
7005 /*-----------------------------------------------------------------*/
7006 /* shiftR1Left2Result - shift right one byte from left to result */
7007 /*-----------------------------------------------------------------*/
7009 shiftR1Left2Result (operand * left, int offl,
7010 operand * result, int offr,
7011 int shCount, int sign)
7013 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7014 /* shift right accumulator */
7019 aopPut (AOP (result), "a", offr);
7023 #ifdef BETTER_LITERAL_SHIFT
7024 /*-----------------------------------------------------------------*/
7025 /* shiftL1Left2Result - shift left one byte from left to result */
7026 /*-----------------------------------------------------------------*/
7028 shiftL1Left2Result (operand * left, int offl,
7029 operand * result, int offr, int shCount)
7031 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7032 /* shift left accumulator */
7034 aopPut (AOP (result), "a", offr);
7038 #ifdef BETTER_LITERAL_SHIFT
7039 /*-----------------------------------------------------------------*/
7040 /* movLeft2Result - move byte from left to result */
7041 /*-----------------------------------------------------------------*/
7043 movLeft2Result (operand * left, int offl,
7044 operand * result, int offr, int sign)
7047 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7049 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7051 if (*l == '@' && (IS_AOP_PREG (result)))
7053 emitcode ("mov", "a,%s", l);
7054 aopPut (AOP (result), "a", offr);
7060 aopPut (AOP (result), l, offr);
7064 /* MSB sign in acc.7 ! */
7065 if (getDataSize (left) == offl + 1)
7067 emitcode ("mov", "a,%s", l);
7068 aopPut (AOP (result), "a", offr);
7076 #ifdef BETTER_LITERAL_SHIFT
7077 /*-----------------------------------------------------------------*/
7078 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7079 /*-----------------------------------------------------------------*/
7083 emitcode ("rrc", "a");
7084 emitcode ("xch", "a,%s", x);
7085 emitcode ("rrc", "a");
7086 emitcode ("xch", "a,%s", x);
7090 #ifdef BETTER_LITERAL_SHIFT
7092 /*-----------------------------------------------------------------*/
7093 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7094 /*-----------------------------------------------------------------*/
7098 emitcode ("xch", "a,%s", x);
7099 emitcode ("rlc", "a");
7100 emitcode ("xch", "a,%s", x);
7101 emitcode ("rlc", "a");
7105 #ifdef BETTER_LITERAL_SHIFT
7106 /*-----------------------------------------------------------------*/
7107 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7108 /*-----------------------------------------------------------------*/
7112 emitcode ("xch", "a,%s", x);
7113 emitcode ("add", "a,acc");
7114 emitcode ("xch", "a,%s", x);
7115 emitcode ("rlc", "a");
7119 #ifdef BETTER_LITERAL_SHIFT
7120 /*-----------------------------------------------------------------*/
7121 /* AccAXLsh - left shift a:x by known count (0..7) */
7122 /*-----------------------------------------------------------------*/
7124 AccAXLsh (char *x, int shCount)
7139 case 5: // AAAAABBB:CCCCCDDD
7141 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7143 emitcode ("anl", "a,#!constbyte",
7144 SLMask[shCount]); // BBB00000:CCCCCDDD
7146 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7148 AccRol (shCount); // DDDCCCCC:BBB00000
7150 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7152 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7154 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7156 emitcode ("anl", "a,#!constbyte",
7157 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7159 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7161 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7164 case 6: // AAAAAABB:CCCCCCDD
7165 emitcode ("anl", "a,#!constbyte",
7166 SRMask[shCount]); // 000000BB:CCCCCCDD
7167 emitcode ("mov", "c,acc.0"); // c = B
7168 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7170 AccAXRrl1 (x); // BCCCCCCD:D000000B
7171 AccAXRrl1 (x); // BBCCCCCC:DD000000
7173 emitcode("rrc","a");
7174 emitcode("xch","a,%s", x);
7175 emitcode("rrc","a");
7176 emitcode("mov","c,acc.0"); //<< get correct bit
7177 emitcode("xch","a,%s", x);
7179 emitcode("rrc","a");
7180 emitcode("xch","a,%s", x);
7181 emitcode("rrc","a");
7182 emitcode("xch","a,%s", x);
7185 case 7: // a:x <<= 7
7187 emitcode ("anl", "a,#!constbyte",
7188 SRMask[shCount]); // 0000000B:CCCCCCCD
7190 emitcode ("mov", "c,acc.0"); // c = B
7192 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7194 AccAXRrl1 (x); // BCCCCCCC:D0000000
7203 #ifdef BETTER_LITERAL_SHIFT
7205 /*-----------------------------------------------------------------*/
7206 /* AccAXRsh - right shift a:x known count (0..7) */
7207 /*-----------------------------------------------------------------*/
7209 AccAXRsh (char *x, int shCount)
7217 AccAXRrl1 (x); // 0->a:x
7222 AccAXRrl1 (x); // 0->a:x
7225 AccAXRrl1 (x); // 0->a:x
7230 case 5: // AAAAABBB:CCCCCDDD = a:x
7232 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7234 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7236 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7238 emitcode ("anl", "a,#!constbyte",
7239 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7241 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7243 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7245 emitcode ("anl", "a,#!constbyte",
7246 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7248 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7250 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7252 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7255 case 6: // AABBBBBB:CCDDDDDD
7257 emitcode ("mov", "c,acc.7");
7258 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7260 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7262 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7264 emitcode ("anl", "a,#!constbyte",
7265 SRMask[shCount]); // 000000AA:BBBBBBCC
7268 case 7: // ABBBBBBB:CDDDDDDD
7270 emitcode ("mov", "c,acc.7"); // c = A
7272 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7274 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7276 emitcode ("anl", "a,#!constbyte",
7277 SRMask[shCount]); // 0000000A:BBBBBBBC
7286 #ifdef BETTER_LITERAL_SHIFT
7287 /*-----------------------------------------------------------------*/
7288 /* AccAXRshS - right shift signed a:x known count (0..7) */
7289 /*-----------------------------------------------------------------*/
7291 AccAXRshS (char *x, int shCount)
7299 emitcode ("mov", "c,acc.7");
7300 AccAXRrl1 (x); // s->a:x
7304 emitcode ("mov", "c,acc.7");
7305 AccAXRrl1 (x); // s->a:x
7307 emitcode ("mov", "c,acc.7");
7308 AccAXRrl1 (x); // s->a:x
7313 case 5: // AAAAABBB:CCCCCDDD = a:x
7315 tlbl = newiTempLabel (NULL);
7316 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7318 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7320 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7322 emitcode ("anl", "a,#!constbyte",
7323 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7325 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7327 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7329 emitcode ("anl", "a,#!constbyte",
7330 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7332 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7334 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7336 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7338 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7339 emitcode ("orl", "a,#!constbyte",
7340 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7342 emitcode ("", "!tlabeldef", tlbl->key + 100);
7343 break; // SSSSAAAA:BBBCCCCC
7345 case 6: // AABBBBBB:CCDDDDDD
7347 tlbl = newiTempLabel (NULL);
7348 emitcode ("mov", "c,acc.7");
7349 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7351 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7353 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7355 emitcode ("anl", "a,#!constbyte",
7356 SRMask[shCount]); // 000000AA:BBBBBBCC
7358 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7359 emitcode ("orl", "a,#!constbyte",
7360 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7362 emitcode ("", "!tlabeldef", tlbl->key + 100);
7364 case 7: // ABBBBBBB:CDDDDDDD
7366 tlbl = newiTempLabel (NULL);
7367 emitcode ("mov", "c,acc.7"); // c = A
7369 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7371 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7373 emitcode ("anl", "a,#!constbyte",
7374 SRMask[shCount]); // 0000000A:BBBBBBBC
7376 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7377 emitcode ("orl", "a,#!constbyte",
7378 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7380 emitcode ("", "!tlabeldef", tlbl->key + 100);
7388 #ifdef BETTER_LITERAL_SHIFT
7390 _loadLeftIntoAx(char **lsb,
7396 // Get the initial value from left into a pair of registers.
7397 // MSB must be in A, LSB can be any register.
7399 // If the result is held in registers, it is an optimization
7400 // if the LSB can be held in the register which will hold the,
7401 // result LSB since this saves us from having to copy it into
7402 // the result following AccAXLsh.
7404 // If the result is addressed indirectly, this is not a gain.
7405 if (AOP_NEEDSACC(result))
7409 _startLazyDPSEvaluation();
7410 if (AOP_TYPE(left) == AOP_DPTR2)
7413 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7414 // get LSB in DP2_RESULT_REG.
7415 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7416 assert(!strcmp(leftByte, DP2_RESULT_REG));
7420 // get LSB into DP2_RESULT_REG
7421 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7422 if (strcmp(leftByte, DP2_RESULT_REG))
7425 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7428 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7429 assert(strcmp(leftByte, DP2_RESULT_REG));
7432 _endLazyDPSEvaluation();
7433 *lsb = DP2_RESULT_REG;
7437 if (sameRegs (AOP (result), AOP (left)) &&
7438 ((offl + MSB16) == offr))
7440 /* don't crash result[offr] */
7441 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7442 emitcode ("xch", "a,%s",
7443 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7447 movLeft2Result (left, offl, result, offr, 0);
7448 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7450 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7451 assert(strcmp(*lsb,"a"));
7456 _storeAxResults(char *lsb,
7460 _startLazyDPSEvaluation();
7461 if (AOP_NEEDSACC(result))
7463 /* We have to explicitly update the result LSB.
7465 emitcode("xch","a,%s", lsb);
7466 aopPut(AOP(result), "a", offr);
7467 emitcode("mov","a,%s", lsb);
7469 if (getDataSize (result) > 1)
7471 aopPut (AOP (result), "a", offr + MSB16);
7473 _endLazyDPSEvaluation();
7476 /*-----------------------------------------------------------------*/
7477 /* shiftL2Left2Result - shift left two bytes from left to result */
7478 /*-----------------------------------------------------------------*/
7480 shiftL2Left2Result (operand * left, int offl,
7481 operand * result, int offr, int shCount)
7485 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7487 AccAXLsh (lsb, shCount);
7489 _storeAxResults(lsb, result, offr);
7493 #ifdef BETTER_LITERAL_SHIFT
7494 /*-----------------------------------------------------------------*/
7495 /* shiftR2Left2Result - shift right two bytes from left to result */
7496 /*-----------------------------------------------------------------*/
7498 shiftR2Left2Result (operand * left, int offl,
7499 operand * result, int offr,
7500 int shCount, int sign)
7504 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7506 /* a:x >> shCount (x = lsb(result)) */
7509 AccAXRshS(lsb, shCount);
7513 AccAXRsh(lsb, shCount);
7516 _storeAxResults(lsb, result, offr);
7522 /*-----------------------------------------------------------------*/
7523 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7524 /*-----------------------------------------------------------------*/
7526 shiftLLeftOrResult (operand * left, int offl,
7527 operand * result, int offr, int shCount)
7529 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7530 /* shift left accumulator */
7532 /* or with result */
7533 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7534 /* back to result */
7535 aopPut (AOP (result), "a", offr);
7541 /*-----------------------------------------------------------------*/
7542 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7543 /*-----------------------------------------------------------------*/
7545 shiftRLeftOrResult (operand * left, int offl,
7546 operand * result, int offr, int shCount)
7548 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7549 /* shift right accumulator */
7551 /* or with result */
7552 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7553 /* back to result */
7554 aopPut (AOP (result), "a", offr);
7558 #ifdef BETTER_LITERAL_SHIFT
7559 /*-----------------------------------------------------------------*/
7560 /* genlshOne - left shift a one byte quantity by known count */
7561 /*-----------------------------------------------------------------*/
7563 genlshOne (operand * result, operand * left, int shCount)
7565 D (emitcode (";", "genlshOne "););
7566 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7570 #ifdef BETTER_LITERAL_SHIFT
7571 /*-----------------------------------------------------------------*/
7572 /* genlshTwo - left shift two bytes by known amount != 0 */
7573 /*-----------------------------------------------------------------*/
7575 genlshTwo (operand * result, operand * left, int shCount)
7579 D (emitcode (";", "genlshTwo "););
7581 size = getDataSize (result);
7583 /* if shCount >= 8 */
7588 _startLazyDPSEvaluation();
7594 _endLazyDPSEvaluation();
7595 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7596 aopPut (AOP (result), zero, LSB);
7600 movLeft2Result (left, LSB, result, MSB16, 0);
7601 aopPut (AOP (result), zero, LSB);
7602 _endLazyDPSEvaluation();
7607 aopPut (AOP (result), zero, LSB);
7608 _endLazyDPSEvaluation();
7612 /* 1 <= shCount <= 7 */
7617 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7621 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7629 /*-----------------------------------------------------------------*/
7630 /* shiftLLong - shift left one long from left to result */
7631 /* offl = LSB or MSB16 */
7632 /*-----------------------------------------------------------------*/
7634 shiftLLong (operand * left, operand * result, int offr)
7637 int size = AOP_SIZE (result);
7639 if (size >= LSB + offr)
7641 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7643 emitcode ("add", "a,acc");
7644 if (sameRegs (AOP (left), AOP (result)) &&
7645 size >= MSB16 + offr && offr != LSB)
7646 emitcode ("xch", "a,%s",
7647 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7649 aopPut (AOP (result), "a", LSB + offr);
7652 if (size >= MSB16 + offr)
7654 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7656 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7659 emitcode ("rlc", "a");
7660 if (sameRegs (AOP (left), AOP (result)) &&
7661 size >= MSB24 + offr && offr != LSB)
7662 emitcode ("xch", "a,%s",
7663 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7665 aopPut (AOP (result), "a", MSB16 + offr);
7668 if (size >= MSB24 + offr)
7670 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7672 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7675 emitcode ("rlc", "a");
7676 if (sameRegs (AOP (left), AOP (result)) &&
7677 size >= MSB32 + offr && offr != LSB)
7678 emitcode ("xch", "a,%s",
7679 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7681 aopPut (AOP (result), "a", MSB24 + offr);
7684 if (size > MSB32 + offr)
7686 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7688 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7691 emitcode ("rlc", "a");
7692 aopPut (AOP (result), "a", MSB32 + offr);
7695 aopPut (AOP (result), zero, LSB);
7701 /*-----------------------------------------------------------------*/
7702 /* genlshFour - shift four byte by a known amount != 0 */
7703 /*-----------------------------------------------------------------*/
7705 genlshFour (operand * result, operand * left, int shCount)
7709 D (emitcode (";", "genlshFour ");
7712 size = AOP_SIZE (result);
7714 /* if shifting more that 3 bytes */
7719 /* lowest order of left goes to the highest
7720 order of the destination */
7721 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7723 movLeft2Result (left, LSB, result, MSB32, 0);
7724 aopPut (AOP (result), zero, LSB);
7725 aopPut (AOP (result), zero, MSB16);
7726 aopPut (AOP (result), zero, MSB24);
7730 /* more than two bytes */
7731 else if (shCount >= 16)
7733 /* lower order two bytes goes to higher order two bytes */
7735 /* if some more remaining */
7737 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7740 movLeft2Result (left, MSB16, result, MSB32, 0);
7741 movLeft2Result (left, LSB, result, MSB24, 0);
7743 aopPut (AOP (result), zero, MSB16);
7744 aopPut (AOP (result), zero, LSB);
7748 /* if more than 1 byte */
7749 else if (shCount >= 8)
7751 /* lower order three bytes goes to higher order three bytes */
7756 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7758 movLeft2Result (left, LSB, result, MSB16, 0);
7764 movLeft2Result (left, MSB24, result, MSB32, 0);
7765 movLeft2Result (left, MSB16, result, MSB24, 0);
7766 movLeft2Result (left, LSB, result, MSB16, 0);
7767 aopPut (AOP (result), zero, LSB);
7769 else if (shCount == 1)
7770 shiftLLong (left, result, MSB16);
7773 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7774 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7775 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7776 aopPut (AOP (result), zero, LSB);
7781 /* 1 <= shCount <= 7 */
7782 else if (shCount <= 2)
7784 shiftLLong (left, result, LSB);
7786 shiftLLong (result, result, LSB);
7788 /* 3 <= shCount <= 7, optimize */
7791 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7792 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7793 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7798 #ifdef BETTER_LITERAL_SHIFT
7799 /*-----------------------------------------------------------------*/
7800 /* genLeftShiftLiteral - left shifting by known count */
7801 /*-----------------------------------------------------------------*/
7803 genLeftShiftLiteral (operand * left,
7808 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7811 size = getSize (operandType (result));
7813 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7815 /* We only handle certain easy cases so far. */
7817 && (shCount < (size * 8))
7821 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7825 freeAsmop (right, NULL, ic, TRUE);
7827 aopOp(left, ic, FALSE, FALSE);
7828 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7831 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7833 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7834 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7836 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7839 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7841 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7842 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7844 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7850 emitcode ("; shift left ", "result %d, left %d", size,
7854 /* I suppose that the left size >= result size */
7857 _startLazyDPSEvaluation();
7860 movLeft2Result (left, size, result, size, 0);
7862 _endLazyDPSEvaluation();
7864 else if (shCount >= (size * 8))
7866 _startLazyDPSEvaluation();
7869 aopPut (AOP (result), zero, size);
7871 _endLazyDPSEvaluation();
7878 genlshOne (result, left, shCount);
7882 genlshTwo (result, left, shCount);
7886 genlshFour (result, left, shCount);
7890 fprintf(stderr, "*** ack! mystery literal shift!\n");
7894 freeAsmop (left, NULL, ic, TRUE);
7895 freeAsmop (result, NULL, ic, TRUE);
7900 /*-----------------------------------------------------------------*/
7901 /* genLeftShift - generates code for left shifting */
7902 /*-----------------------------------------------------------------*/
7904 genLeftShift (iCode * ic)
7906 operand *left, *right, *result;
7909 symbol *tlbl, *tlbl1;
7911 D (emitcode (";", "genLeftShift "););
7913 right = IC_RIGHT (ic);
7914 left = IC_LEFT (ic);
7915 result = IC_RESULT (ic);
7917 aopOp (right, ic, FALSE, FALSE);
7920 #ifdef BETTER_LITERAL_SHIFT
7921 /* if the shift count is known then do it
7922 as efficiently as possible */
7923 if (AOP_TYPE (right) == AOP_LIT)
7925 if (genLeftShiftLiteral (left, right, result, ic))
7932 /* shift count is unknown then we have to form
7933 a loop get the loop count in B : Note: we take
7934 only the lower order byte since shifting
7935 more that 32 bits make no sense anyway, ( the
7936 largest size of an object can be only 32 bits ) */
7938 if (AOP_TYPE (right) == AOP_LIT)
7940 /* Really should be handled by genLeftShiftLiteral,
7941 * but since I'm too lazy to fix that today, at least we can make
7942 * some small improvement.
7944 emitcode("mov", "b,#!constbyte",
7945 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7949 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7950 emitcode ("inc", "b");
7952 freeAsmop (right, NULL, ic, TRUE);
7953 aopOp (left, ic, FALSE, FALSE);
7954 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7956 /* now move the left to the result if they are not the
7958 if (!sameRegs (AOP (left), AOP (result)) &&
7959 AOP_SIZE (result) > 1)
7962 size = AOP_SIZE (result);
7964 _startLazyDPSEvaluation ();
7967 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7968 if (*l == '@' && (IS_AOP_PREG (result)))
7971 emitcode ("mov", "a,%s", l);
7972 aopPut (AOP (result), "a", offset);
7975 aopPut (AOP (result), l, offset);
7978 _endLazyDPSEvaluation ();
7981 tlbl = newiTempLabel (NULL);
7982 size = AOP_SIZE (result);
7984 tlbl1 = newiTempLabel (NULL);
7986 /* if it is only one byte then */
7989 symbol *tlbl1 = newiTempLabel (NULL);
7991 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7993 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
7994 emitcode ("", "!tlabeldef", tlbl->key + 100);
7995 emitcode ("add", "a,acc");
7996 emitcode ("", "!tlabeldef", tlbl1->key + 100);
7997 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
7998 aopPut (AOP (result), "a", 0);
8002 reAdjustPreg (AOP (result));
8004 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8005 emitcode ("", "!tlabeldef", tlbl->key + 100);
8006 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8008 emitcode ("add", "a,acc");
8009 aopPut (AOP (result), "a", offset++);
8010 _startLazyDPSEvaluation ();
8013 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8015 emitcode ("rlc", "a");
8016 aopPut (AOP (result), "a", offset++);
8018 _endLazyDPSEvaluation ();
8019 reAdjustPreg (AOP (result));
8021 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8022 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8024 freeAsmop (left, NULL, ic, TRUE);
8025 freeAsmop (result, NULL, ic, TRUE);
8028 #ifdef BETTER_LITERAL_SHIFT
8029 /*-----------------------------------------------------------------*/
8030 /* genrshOne - right shift a one byte quantity by known count */
8031 /*-----------------------------------------------------------------*/
8033 genrshOne (operand * result, operand * left,
8034 int shCount, int sign)
8036 D (emitcode (";", "genrshOne"););
8037 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8041 #ifdef BETTER_LITERAL_SHIFT
8042 /*-----------------------------------------------------------------*/
8043 /* genrshTwo - right shift two bytes by known amount != 0 */
8044 /*-----------------------------------------------------------------*/
8046 genrshTwo (operand * result, operand * left,
8047 int shCount, int sign)
8049 D (emitcode (";", "genrshTwo"););
8051 /* if shCount >= 8 */
8055 _startLazyDPSEvaluation();
8058 shiftR1Left2Result (left, MSB16, result, LSB,
8063 movLeft2Result (left, MSB16, result, LSB, sign);
8065 addSign (result, MSB16, sign);
8066 _endLazyDPSEvaluation();
8069 /* 1 <= shCount <= 7 */
8072 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8079 /*-----------------------------------------------------------------*/
8080 /* shiftRLong - shift right one long from left to result */
8081 /* offl = LSB or MSB16 */
8082 /*-----------------------------------------------------------------*/
8084 shiftRLong (operand * left, int offl,
8085 operand * result, int sign)
8087 int isSameRegs=sameRegs(AOP(left),AOP(result));
8089 if (isSameRegs && offl>1) {
8090 // we are in big trouble, but this shouldn't happen
8091 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8094 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8099 emitcode ("rlc", "a");
8100 emitcode ("subb", "a,acc");
8101 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8103 aopPut (AOP(result), zero, MSB32);
8108 emitcode ("clr", "c");
8110 emitcode ("mov", "c,acc.7");
8113 emitcode ("rrc", "a");
8115 if (isSameRegs && offl==MSB16) {
8116 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8118 aopPut (AOP (result), "a", MSB32);
8119 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8122 emitcode ("rrc", "a");
8123 if (isSameRegs && offl==1) {
8124 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8126 aopPut (AOP (result), "a", MSB24);
8127 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8129 emitcode ("rrc", "a");
8130 aopPut (AOP (result), "a", MSB16 - offl);
8134 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8135 emitcode ("rrc", "a");
8136 aopPut (AOP (result), "a", LSB);
8143 /*-----------------------------------------------------------------*/
8144 /* genrshFour - shift four byte by a known amount != 0 */
8145 /*-----------------------------------------------------------------*/
8147 genrshFour (operand * result, operand * left,
8148 int shCount, int sign)
8150 D (emitcode (";", "genrshFour");
8153 /* if shifting more that 3 bytes */
8158 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8160 movLeft2Result (left, MSB32, result, LSB, sign);
8161 addSign (result, MSB16, sign);
8163 else if (shCount >= 16)
8167 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8170 movLeft2Result (left, MSB24, result, LSB, 0);
8171 movLeft2Result (left, MSB32, result, MSB16, sign);
8173 addSign (result, MSB24, sign);
8175 else if (shCount >= 8)
8179 shiftRLong (left, MSB16, result, sign);
8180 else if (shCount == 0)
8182 movLeft2Result (left, MSB16, result, LSB, 0);
8183 movLeft2Result (left, MSB24, result, MSB16, 0);
8184 movLeft2Result (left, MSB32, result, MSB24, sign);
8185 addSign (result, MSB32, sign);
8189 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8190 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8191 /* the last shift is signed */
8192 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8193 addSign (result, MSB32, sign);
8197 { /* 1 <= shCount <= 7 */
8200 shiftRLong (left, LSB, result, sign);
8202 shiftRLong (result, LSB, result, sign);
8206 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8207 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8208 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8214 #ifdef BETTER_LITERAL_SHIFT
8215 /*-----------------------------------------------------------------*/
8216 /* genRightShiftLiteral - right shifting by known count */
8217 /*-----------------------------------------------------------------*/
8219 genRightShiftLiteral (operand * left,
8225 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8228 size = getSize (operandType (result));
8230 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8232 /* We only handle certain easy cases so far. */
8234 && (shCount < (size * 8))
8238 D(emitcode (";", "genRightShiftLiteral wimping out"););
8242 freeAsmop (right, NULL, ic, TRUE);
8244 aopOp (left, ic, FALSE, FALSE);
8245 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8248 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8252 /* test the LEFT size !!! */
8254 /* I suppose that the left size >= result size */
8257 size = getDataSize (result);
8258 _startLazyDPSEvaluation();
8261 movLeft2Result (left, size, result, size, 0);
8263 _endLazyDPSEvaluation();
8265 else if (shCount >= (size * 8))
8269 /* get sign in acc.7 */
8270 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8272 addSign (result, LSB, sign);
8279 genrshOne (result, left, shCount, sign);
8283 genrshTwo (result, left, shCount, sign);
8287 genrshFour (result, left, shCount, sign);
8294 freeAsmop (left, NULL, ic, TRUE);
8295 freeAsmop (result, NULL, ic, TRUE);
8301 /*-----------------------------------------------------------------*/
8302 /* genSignedRightShift - right shift of signed number */
8303 /*-----------------------------------------------------------------*/
8305 genSignedRightShift (iCode * ic)
8307 operand *right, *left, *result;
8310 symbol *tlbl, *tlbl1;
8312 D (emitcode (";", "genSignedRightShift "););
8314 /* we do it the hard way put the shift count in b
8315 and loop thru preserving the sign */
8317 right = IC_RIGHT (ic);
8318 left = IC_LEFT (ic);
8319 result = IC_RESULT (ic);
8321 aopOp (right, ic, FALSE, FALSE);
8323 #ifdef BETTER_LITERAL_SHIFT
8324 if (AOP_TYPE (right) == AOP_LIT)
8326 if (genRightShiftLiteral (left, right, result, ic, 1))
8332 /* shift count is unknown then we have to form
8333 a loop get the loop count in B : Note: we take
8334 only the lower order byte since shifting
8335 more that 32 bits make no sense anyway, ( the
8336 largest size of an object can be only 32 bits ) */
8338 if (AOP_TYPE (right) == AOP_LIT)
8340 /* Really should be handled by genRightShiftLiteral,
8341 * but since I'm too lazy to fix that today, at least we can make
8342 * some small improvement.
8344 emitcode("mov", "b,#!constbyte",
8345 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8349 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8350 emitcode ("inc", "b");
8352 freeAsmop (right, NULL, ic, TRUE);
8353 aopOp (left, ic, FALSE, FALSE);
8354 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8356 /* now move the left to the result if they are not the
8358 if (!sameRegs (AOP (left), AOP (result)) &&
8359 AOP_SIZE (result) > 1)
8362 size = AOP_SIZE (result);
8364 _startLazyDPSEvaluation ();
8367 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8368 if (*l == '@' && IS_AOP_PREG (result))
8371 emitcode ("mov", "a,%s", l);
8372 aopPut (AOP (result), "a", offset);
8375 aopPut (AOP (result), l, offset);
8378 _endLazyDPSEvaluation ();
8381 /* mov the highest order bit to OVR */
8382 tlbl = newiTempLabel (NULL);
8383 tlbl1 = newiTempLabel (NULL);
8385 size = AOP_SIZE (result);
8387 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8388 emitcode ("rlc", "a");
8389 emitcode ("mov", "ov,c");
8390 /* if it is only one byte then */
8393 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8395 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8396 emitcode ("", "!tlabeldef", tlbl->key + 100);
8397 emitcode ("mov", "c,ov");
8398 emitcode ("rrc", "a");
8399 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8400 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8401 aopPut (AOP (result), "a", 0);
8405 reAdjustPreg (AOP (result));
8406 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8407 emitcode ("", "!tlabeldef", tlbl->key + 100);
8408 emitcode ("mov", "c,ov");
8409 _startLazyDPSEvaluation ();
8412 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8414 emitcode ("rrc", "a");
8415 aopPut (AOP (result), "a", offset--);
8417 _endLazyDPSEvaluation ();
8418 reAdjustPreg (AOP (result));
8419 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8420 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8423 freeAsmop (left, NULL, ic, TRUE);
8424 freeAsmop (result, NULL, ic, TRUE);
8427 /*-----------------------------------------------------------------*/
8428 /* genRightShift - generate code for right shifting */
8429 /*-----------------------------------------------------------------*/
8431 genRightShift (iCode * ic)
8433 operand *right, *left, *result;
8437 symbol *tlbl, *tlbl1;
8439 D (emitcode (";", "genRightShift "););
8441 /* if signed then we do it the hard way preserve the
8442 sign bit moving it inwards */
8443 retype = getSpec (operandType (IC_RESULT (ic)));
8445 if (!SPEC_USIGN (retype))
8447 genSignedRightShift (ic);
8451 /* signed & unsigned types are treated the same : i.e. the
8452 signed is NOT propagated inwards : quoting from the
8453 ANSI - standard : "for E1 >> E2, is equivalent to division
8454 by 2**E2 if unsigned or if it has a non-negative value,
8455 otherwise the result is implementation defined ", MY definition
8456 is that the sign does not get propagated */
8458 right = IC_RIGHT (ic);
8459 left = IC_LEFT (ic);
8460 result = IC_RESULT (ic);
8462 aopOp (right, ic, FALSE, FALSE);
8464 #ifdef BETTER_LITERAL_SHIFT
8465 /* if the shift count is known then do it
8466 as efficiently as possible */
8467 if (AOP_TYPE (right) == AOP_LIT)
8469 if (genRightShiftLiteral (left, right, result, ic, 0))
8476 /* shift count is unknown then we have to form
8477 a loop get the loop count in B : Note: we take
8478 only the lower order byte since shifting
8479 more that 32 bits make no sense anyway, ( the
8480 largest size of an object can be only 32 bits ) */
8482 if (AOP_TYPE (right) == AOP_LIT)
8484 /* Really should be handled by genRightShiftLiteral,
8485 * but since I'm too lazy to fix that today, at least we can make
8486 * some small improvement.
8488 emitcode("mov", "b,#!constbyte",
8489 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8493 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8494 emitcode ("inc", "b");
8496 freeAsmop (right, NULL, ic, TRUE);
8497 aopOp (left, ic, FALSE, FALSE);
8498 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8500 /* now move the left to the result if they are not the
8502 if (!sameRegs (AOP (left), AOP (result)) &&
8503 AOP_SIZE (result) > 1)
8506 size = AOP_SIZE (result);
8508 _startLazyDPSEvaluation ();
8511 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8512 if (*l == '@' && IS_AOP_PREG (result))
8515 emitcode ("mov", "a,%s", l);
8516 aopPut (AOP (result), "a", offset);
8519 aopPut (AOP (result), l, offset);
8522 _endLazyDPSEvaluation ();
8525 tlbl = newiTempLabel (NULL);
8526 tlbl1 = newiTempLabel (NULL);
8527 size = AOP_SIZE (result);
8530 /* if it is only one byte then */
8533 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8535 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8536 emitcode ("", "!tlabeldef", tlbl->key + 100);
8538 emitcode ("rrc", "a");
8539 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8540 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8541 aopPut (AOP (result), "a", 0);
8545 reAdjustPreg (AOP (result));
8546 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8547 emitcode ("", "!tlabeldef", tlbl->key + 100);
8549 _startLazyDPSEvaluation ();
8552 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8554 emitcode ("rrc", "a");
8555 aopPut (AOP (result), "a", offset--);
8557 _endLazyDPSEvaluation ();
8558 reAdjustPreg (AOP (result));
8560 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8561 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8564 freeAsmop (left, NULL, ic, TRUE);
8565 freeAsmop (result, NULL, ic, TRUE);
8568 /*-----------------------------------------------------------------*/
8569 /* genUnpackBits - generates code for unpacking bits */
8570 /*-----------------------------------------------------------------*/
8572 genUnpackBits (operand * result, char *rname, int ptype)
8579 D (emitcode (";", "genUnpackBits ");
8582 etype = getSpec (operandType (result));
8584 /* read the first byte */
8590 emitcode ("mov", "a,@%s", rname);
8594 emitcode ("movx", "a,@%s", rname);
8598 emitcode ("movx", "a,@dptr");
8602 emitcode ("clr", "a");
8603 emitcode ("movc", "a,@a+dptr");
8607 emitcode ("lcall", "__gptrget");
8611 /* if we have bitdisplacement then it fits */
8612 /* into this byte completely or if length is */
8613 /* less than a byte */
8614 if ((shCnt = SPEC_BSTR (etype)) ||
8615 (SPEC_BLEN (etype) <= 8))
8618 /* shift right acc */
8621 emitcode ("anl", "a,#!constbyte",
8622 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8623 aopPut (AOP (result), "a", offset);
8627 /* bit field did not fit in a byte */
8628 rlen = SPEC_BLEN (etype) - 8;
8629 aopPut (AOP (result), "a", offset++);
8638 emitcode ("inc", "%s", rname);
8639 emitcode ("mov", "a,@%s", rname);
8643 emitcode ("inc", "%s", rname);
8644 emitcode ("movx", "a,@%s", rname);
8648 emitcode ("inc", "dptr");
8649 emitcode ("movx", "a,@dptr");
8653 emitcode ("clr", "a");
8654 emitcode ("inc", "dptr");
8655 emitcode ("movc", "a,@a+dptr");
8659 emitcode ("inc", "dptr");
8660 emitcode ("lcall", "__gptrget");
8665 /* if we are done */
8669 aopPut (AOP (result), "a", offset++);
8675 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8676 aopPut (AOP (result), "a", offset);
8683 /*-----------------------------------------------------------------*/
8684 /* genDataPointerGet - generates code when ptr offset is known */
8685 /*-----------------------------------------------------------------*/
8687 genDataPointerGet (operand * left,
8693 int size, offset = 0;
8694 aopOp (result, ic, TRUE, FALSE);
8696 /* get the string representation of the name */
8697 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8698 size = AOP_SIZE (result);
8699 _startLazyDPSEvaluation ();
8703 sprintf (buffer, "(%s + %d)", l + 1, offset);
8705 sprintf (buffer, "%s", l + 1);
8706 aopPut (AOP (result), buffer, offset++);
8708 _endLazyDPSEvaluation ();
8710 freeAsmop (left, NULL, ic, TRUE);
8711 freeAsmop (result, NULL, ic, TRUE);
8714 /*-----------------------------------------------------------------*/
8715 /* genNearPointerGet - emitcode for near pointer fetch */
8716 /*-----------------------------------------------------------------*/
8718 genNearPointerGet (operand * left,
8726 sym_link *rtype, *retype, *letype;
8727 sym_link *ltype = operandType (left);
8730 rtype = operandType (result);
8731 retype = getSpec (rtype);
8732 letype = getSpec (ltype);
8734 aopOp (left, ic, FALSE, FALSE);
8736 /* if left is rematerialisable and
8737 result is not bit variable type and
8738 the left is pointer to data space i.e
8739 lower 128 bytes of space */
8740 if (AOP_TYPE (left) == AOP_IMMD &&
8741 !IS_BITVAR (retype) &&
8742 !IS_BITVAR (letype) &&
8743 DCL_TYPE (ltype) == POINTER)
8745 genDataPointerGet (left, result, ic);
8749 /* if the value is already in a pointer register
8750 then don't need anything more */
8751 if (!AOP_INPREG (AOP (left)))
8753 /* otherwise get a free pointer register */
8755 preg = getFreePtr (ic, &aop, FALSE);
8756 emitcode ("mov", "%s,%s",
8758 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8762 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8764 freeAsmop (left, NULL, ic, TRUE);
8765 aopOp (result, ic, FALSE, FALSE);
8767 /* if bitfield then unpack the bits */
8768 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8769 genUnpackBits (result, rname, POINTER);
8772 /* we have can just get the values */
8773 int size = AOP_SIZE (result);
8778 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8781 emitcode ("mov", "a,@%s", rname);
8782 aopPut (AOP (result), "a", offset);
8786 sprintf (buffer, "@%s", rname);
8787 aopPut (AOP (result), buffer, offset);
8791 emitcode ("inc", "%s", rname);
8795 /* now some housekeeping stuff */
8798 /* we had to allocate for this iCode */
8799 if (pi) { /* post increment present */
8800 aopPut(AOP ( left ),rname,0);
8802 freeAsmop (NULL, aop, ic, TRUE);
8806 /* we did not allocate which means left
8807 already in a pointer register, then
8808 if size > 0 && this could be used again
8809 we have to point it back to where it
8811 if (AOP_SIZE (result) > 1 &&
8812 !OP_SYMBOL (left)->remat &&
8813 (OP_SYMBOL (left)->liveTo > ic->seq ||
8817 int size = AOP_SIZE (result) - 1;
8819 emitcode ("dec", "%s", rname);
8824 freeAsmop (result, NULL, ic, TRUE);
8825 if (pi) pi->generated = 1;
8828 /*-----------------------------------------------------------------*/
8829 /* genPagedPointerGet - emitcode for paged pointer fetch */
8830 /*-----------------------------------------------------------------*/
8832 genPagedPointerGet (operand * left,
8840 sym_link *rtype, *retype, *letype;
8842 rtype = operandType (result);
8843 retype = getSpec (rtype);
8844 letype = getSpec (operandType (left));
8845 aopOp (left, ic, FALSE, FALSE);
8847 /* if the value is already in a pointer register
8848 then don't need anything more */
8849 if (!AOP_INPREG (AOP (left)))
8851 /* otherwise get a free pointer register */
8853 preg = getFreePtr (ic, &aop, FALSE);
8854 emitcode ("mov", "%s,%s",
8856 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8860 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8862 freeAsmop (left, NULL, ic, TRUE);
8863 aopOp (result, ic, FALSE, FALSE);
8865 /* if bitfield then unpack the bits */
8866 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8867 genUnpackBits (result, rname, PPOINTER);
8870 /* we have can just get the values */
8871 int size = AOP_SIZE (result);
8877 emitcode ("movx", "a,@%s", rname);
8878 aopPut (AOP (result), "a", offset);
8883 emitcode ("inc", "%s", rname);
8887 /* now some housekeeping stuff */
8890 /* we had to allocate for this iCode */
8891 if (pi) aopPut ( AOP (left), rname, 0);
8892 freeAsmop (NULL, aop, ic, TRUE);
8896 /* we did not allocate which means left
8897 already in a pointer register, then
8898 if size > 0 && this could be used again
8899 we have to point it back to where it
8901 if (AOP_SIZE (result) > 1 &&
8902 !OP_SYMBOL (left)->remat &&
8903 (OP_SYMBOL (left)->liveTo > ic->seq ||
8907 int size = AOP_SIZE (result) - 1;
8909 emitcode ("dec", "%s", rname);
8914 freeAsmop (result, NULL, ic, TRUE);
8915 if (pi) pi->generated = 1;
8918 /*-----------------------------------------------------------------*/
8919 /* genFarPointerGet - gget value from far space */
8920 /*-----------------------------------------------------------------*/
8922 genFarPointerGet (operand * left,
8923 operand * result, iCode * ic, iCode *pi)
8925 int size, offset, dopi=1;
8926 sym_link *retype = getSpec (operandType (result));
8927 sym_link *letype = getSpec (operandType (left));
8928 D (emitcode (";", "genFarPointerGet");
8931 aopOp (left, ic, FALSE, FALSE);
8933 /* if the operand is already in dptr
8934 then we do nothing else we move the value to dptr */
8935 if (AOP_TYPE (left) != AOP_STR)
8937 /* if this is remateriazable */
8938 if (AOP_TYPE (left) == AOP_IMMD)
8940 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8944 /* we need to get it byte by byte */
8945 _startLazyDPSEvaluation ();
8946 if (AOP_TYPE (left) != AOP_DPTR)
8948 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8949 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8950 if (options.model == MODEL_FLAT24)
8951 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8955 /* We need to generate a load to DPTR indirect through DPTR. */
8956 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8958 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8959 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8960 if (options.model == MODEL_FLAT24)
8961 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8962 emitcode ("pop", "dph");
8963 emitcode ("pop", "dpl");
8966 _endLazyDPSEvaluation ();
8969 /* so dptr know contains the address */
8970 aopOp (result, ic, FALSE, TRUE);
8972 /* if bit then unpack */
8973 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8974 genUnpackBits (result, "dptr", FPOINTER);
8977 size = AOP_SIZE (result);
8980 _startLazyDPSEvaluation ();
8987 emitcode ("movx", "a,@dptr");
8988 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
8989 emitcode ("inc", "dptr");
8991 aopPut (AOP (result), "a", offset++);
8993 _endLazyDPSEvaluation ();
8995 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
8996 aopPut ( AOP (left), "dpl", 0);
8997 aopPut ( AOP (left), "dph", 1);
8998 if (options.model == MODEL_FLAT24)
8999 aopPut ( AOP (left), "dpx", 2);
9001 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9002 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9004 size = AOP_SIZE (result) - 1;
9005 while (size--) emitcode ("lcall","__decdptr");
9008 freeAsmop (left, NULL, ic, TRUE);
9009 freeAsmop (result, NULL, ic, TRUE);
9012 /*-----------------------------------------------------------------*/
9013 /* emitcodePointerGet - gget value from code space */
9014 /*-----------------------------------------------------------------*/
9016 emitcodePointerGet (operand * left,
9017 operand * result, iCode * ic, iCode *pi)
9019 int size, offset, dopi=1;
9020 sym_link *retype = getSpec (operandType (result));
9022 aopOp (left, ic, FALSE, FALSE);
9024 /* if the operand is already in dptr
9025 then we do nothing else we move the value to dptr */
9026 if (AOP_TYPE (left) != AOP_STR)
9028 /* if this is remateriazable */
9029 if (AOP_TYPE (left) == AOP_IMMD)
9031 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9034 { /* we need to get it byte by byte */
9035 _startLazyDPSEvaluation ();
9036 if (AOP_TYPE (left) != AOP_DPTR)
9038 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9039 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9040 if (options.model == MODEL_FLAT24)
9041 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9045 /* We need to generate a load to DPTR indirect through DPTR. */
9046 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9048 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9049 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9050 if (options.model == MODEL_FLAT24)
9051 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9052 emitcode ("pop", "dph");
9053 emitcode ("pop", "dpl");
9056 _endLazyDPSEvaluation ();
9059 /* so dptr know contains the address */
9060 aopOp (result, ic, FALSE, TRUE);
9062 /* if bit then unpack */
9063 if (IS_BITVAR (retype))
9064 genUnpackBits (result, "dptr", CPOINTER);
9067 size = AOP_SIZE (result);
9070 _startLazyDPSEvaluation ();
9076 emitcode ("clr", "a");
9077 emitcode ("movc", "a,@a+dptr");
9078 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9079 emitcode ("inc", "dptr");
9080 aopPut (AOP (result), "a", offset++);
9082 _endLazyDPSEvaluation ();
9084 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9085 aopPut ( AOP (left), "dpl", 0);
9086 aopPut ( AOP (left), "dph", 1);
9087 if (options.model == MODEL_FLAT24)
9088 aopPut ( AOP (left), "dpx", 2);
9090 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9091 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9093 size = AOP_SIZE (result) - 1;
9094 while (size--) emitcode ("lcall","__decdptr");
9097 freeAsmop (left, NULL, ic, TRUE);
9098 freeAsmop (result, NULL, ic, TRUE);
9101 /*-----------------------------------------------------------------*/
9102 /* genGenPointerGet - gget value from generic pointer space */
9103 /*-----------------------------------------------------------------*/
9105 genGenPointerGet (operand * left,
9106 operand * result, iCode * ic, iCode * pi)
9109 sym_link *retype = getSpec (operandType (result));
9110 sym_link *letype = getSpec (operandType (left));
9112 D (emitcode (";", "genGenPointerGet "); );
9114 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9116 /* if the operand is already in dptr
9117 then we do nothing else we move the value to dptr */
9118 if (AOP_TYPE (left) != AOP_STR)
9120 /* if this is remateriazable */
9121 if (AOP_TYPE (left) == AOP_IMMD)
9123 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9124 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9125 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9127 emitcode ("mov", "b,#%d", pointerCode (retype));
9130 { /* we need to get it byte by byte */
9131 _startLazyDPSEvaluation ();
9132 if (AOP(left)->type==AOP_DPTR2) {
9134 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9137 emitcode ("mov", "dpl,%s", l);
9138 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9141 emitcode ("mov", "dph,%s", l);
9142 if (options.model == MODEL_FLAT24) {
9143 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9146 emitcode ("mov", "dpx,%s", l);
9147 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9149 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9152 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9153 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9154 if (options.model == MODEL_FLAT24) {
9155 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9156 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9158 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9161 _endLazyDPSEvaluation ();
9164 /* so dptr know contains the address */
9165 aopOp (result, ic, FALSE, TRUE);
9167 /* if bit then unpack */
9168 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9169 genUnpackBits (result, "dptr", GPOINTER);
9172 size = AOP_SIZE (result);
9177 emitcode ("lcall", "__gptrget");
9178 aopPut (AOP (result), "a", offset++);
9179 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9180 emitcode ("inc", "dptr");
9184 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9185 aopPut ( AOP (left), "dpl", 0);
9186 aopPut ( AOP (left), "dph", 1);
9187 if (options.model == MODEL_FLAT24) {
9188 aopPut ( AOP (left), "dpx", 2);
9189 aopPut ( AOP (left), "b", 3);
9190 } else aopPut ( AOP (left), "b", 2);
9192 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9193 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9195 size = AOP_SIZE (result) - 1;
9196 while (size--) emitcode ("lcall","__decdptr");
9199 freeAsmop (left, NULL, ic, TRUE);
9200 freeAsmop (result, NULL, ic, TRUE);
9203 /*-----------------------------------------------------------------*/
9204 /* genPointerGet - generate code for pointer get */
9205 /*-----------------------------------------------------------------*/
9207 genPointerGet (iCode * ic, iCode *pi)
9209 operand *left, *result;
9210 sym_link *type, *etype;
9213 D (emitcode (";", "genPointerGet ");
9216 left = IC_LEFT (ic);
9217 result = IC_RESULT (ic);
9219 /* depending on the type of pointer we need to
9220 move it to the correct pointer register */
9221 type = operandType (left);
9222 etype = getSpec (type);
9223 /* if left is of type of pointer then it is simple */
9224 if (IS_PTR (type) && !IS_FUNC (type->next))
9225 p_type = DCL_TYPE (type);
9228 /* we have to go by the storage class */
9229 p_type = PTR_TYPE (SPEC_OCLS (etype));
9231 /* special case when cast remat */
9232 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9233 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9234 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9235 type = type = operandType (left);
9236 p_type = DCL_TYPE (type);
9238 /* now that we have the pointer type we assign
9239 the pointer values */
9245 genNearPointerGet (left, result, ic, pi);
9249 genPagedPointerGet (left, result, ic, pi);
9253 genFarPointerGet (left, result, ic, pi);
9257 emitcodePointerGet (left, result, ic, pi);
9261 genGenPointerGet (left, result, ic, pi);
9267 /*-----------------------------------------------------------------*/
9268 /* genPackBits - generates code for packed bit storage */
9269 /*-----------------------------------------------------------------*/
9271 genPackBits (sym_link * etype,
9273 char *rname, int p_type)
9281 blen = SPEC_BLEN (etype);
9282 bstr = SPEC_BSTR (etype);
9284 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9287 /* if the bit lenth is less than or */
9288 /* it exactly fits a byte then */
9289 if (SPEC_BLEN (etype) <= 8)
9291 shCount = SPEC_BSTR (etype);
9293 /* shift left acc */
9296 if (SPEC_BLEN (etype) < 8)
9297 { /* if smaller than a byte */
9303 emitcode ("mov", "b,a");
9304 emitcode ("mov", "a,@%s", rname);
9308 emitcode ("mov", "b,a");
9309 emitcode ("movx", "a,@dptr");
9313 emitcode ("push", "b");
9314 emitcode ("push", "acc");
9315 emitcode ("lcall", "__gptrget");
9316 emitcode ("pop", "b");
9320 emitcode ("anl", "a,#!constbyte", (unsigned char)
9321 ((unsigned char) (0xFF << (blen + bstr)) |
9322 (unsigned char) (0xFF >> (8 - bstr))));
9323 emitcode ("orl", "a,b");
9324 if (p_type == GPOINTER)
9325 emitcode ("pop", "b");
9332 emitcode ("mov", "@%s,a", rname);
9336 emitcode ("movx", "@dptr,a");
9340 emitcode ("lcall", "__gptrput");
9345 if (SPEC_BLEN (etype) <= 8)
9348 emitcode ("inc", "%s", rname);
9349 rLen = SPEC_BLEN (etype);
9351 /* now generate for lengths greater than one byte */
9355 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9367 emitcode ("mov", "@%s,a", rname);
9370 emitcode ("mov", "@%s,%s", rname, l);
9375 emitcode ("movx", "@dptr,a");
9380 emitcode ("lcall", "__gptrput");
9383 emitcode ("inc", "%s", rname);
9388 /* last last was not complete */
9391 /* save the byte & read byte */
9395 emitcode ("mov", "b,a");
9396 emitcode ("mov", "a,@%s", rname);
9400 emitcode ("mov", "b,a");
9401 emitcode ("movx", "a,@dptr");
9405 emitcode ("push", "b");
9406 emitcode ("push", "acc");
9407 emitcode ("lcall", "__gptrget");
9408 emitcode ("pop", "b");
9412 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9413 emitcode ("orl", "a,b");
9416 if (p_type == GPOINTER)
9417 emitcode ("pop", "b");
9423 emitcode ("mov", "@%s,a", rname);
9427 emitcode ("movx", "@dptr,a");
9431 emitcode ("lcall", "__gptrput");
9435 /*-----------------------------------------------------------------*/
9436 /* genDataPointerSet - remat pointer to data space */
9437 /*-----------------------------------------------------------------*/
9439 genDataPointerSet (operand * right,
9443 int size, offset = 0;
9444 char *l, buffer[256];
9446 aopOp (right, ic, FALSE, FALSE);
9448 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9449 size = AOP_SIZE (right);
9453 sprintf (buffer, "(%s + %d)", l + 1, offset);
9455 sprintf (buffer, "%s", l + 1);
9456 emitcode ("mov", "%s,%s", buffer,
9457 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9460 freeAsmop (right, NULL, ic, TRUE);
9461 freeAsmop (result, NULL, ic, TRUE);
9464 /*-----------------------------------------------------------------*/
9465 /* genNearPointerSet - emitcode for near pointer put */
9466 /*-----------------------------------------------------------------*/
9468 genNearPointerSet (operand * right,
9476 sym_link *retype, *letype;
9477 sym_link *ptype = operandType (result);
9479 retype = getSpec (operandType (right));
9480 letype = getSpec (ptype);
9482 aopOp (result, ic, FALSE, FALSE);
9484 /* if the result is rematerializable &
9485 in data space & not a bit variable */
9486 if (AOP_TYPE (result) == AOP_IMMD &&
9487 DCL_TYPE (ptype) == POINTER &&
9488 !IS_BITVAR (retype) &&
9489 !IS_BITVAR (letype))
9491 genDataPointerSet (right, result, ic);
9495 /* if the value is already in a pointer register
9496 then don't need anything more */
9497 if (!AOP_INPREG (AOP (result)))
9499 /* otherwise get a free pointer register */
9501 preg = getFreePtr (ic, &aop, FALSE);
9502 emitcode ("mov", "%s,%s",
9504 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9508 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9510 aopOp (right, ic, FALSE, FALSE);
9512 /* if bitfield then unpack the bits */
9513 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9514 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9517 /* we have can just get the values */
9518 int size = AOP_SIZE (right);
9523 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9527 emitcode ("mov", "@%s,a", rname);
9530 emitcode ("mov", "@%s,%s", rname, l);
9532 emitcode ("inc", "%s", rname);
9537 /* now some housekeeping stuff */
9540 /* we had to allocate for this iCode */
9541 if (pi) aopPut (AOP (result),rname,0);
9542 freeAsmop (NULL, aop, ic, TRUE);
9546 /* we did not allocate which means left
9547 already in a pointer register, then
9548 if size > 0 && this could be used again
9549 we have to point it back to where it
9551 if (AOP_SIZE (right) > 1 &&
9552 !OP_SYMBOL (result)->remat &&
9553 (OP_SYMBOL (result)->liveTo > ic->seq ||
9557 int size = AOP_SIZE (right) - 1;
9559 emitcode ("dec", "%s", rname);
9564 if (pi) pi->generated = 1;
9565 freeAsmop (result, NULL, ic, TRUE);
9566 freeAsmop (right, NULL, ic, TRUE);
9571 /*-----------------------------------------------------------------*/
9572 /* genPagedPointerSet - emitcode for Paged pointer put */
9573 /*-----------------------------------------------------------------*/
9575 genPagedPointerSet (operand * right,
9583 sym_link *retype, *letype;
9585 retype = getSpec (operandType (right));
9586 letype = getSpec (operandType (result));
9588 aopOp (result, ic, FALSE, FALSE);
9590 /* if the value is already in a pointer register
9591 then don't need anything more */
9592 if (!AOP_INPREG (AOP (result)))
9594 /* otherwise get a free pointer register */
9596 preg = getFreePtr (ic, &aop, FALSE);
9597 emitcode ("mov", "%s,%s",
9599 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9603 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9605 aopOp (right, ic, FALSE, FALSE);
9607 /* if bitfield then unpack the bits */
9608 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9609 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9612 /* we have can just get the values */
9613 int size = AOP_SIZE (right);
9618 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9621 emitcode ("movx", "@%s,a", rname);
9624 emitcode ("inc", "%s", rname);
9630 /* now some housekeeping stuff */
9633 if (pi) aopPut (AOP (result),rname,0);
9634 /* we had to allocate for this iCode */
9635 freeAsmop (NULL, aop, ic, TRUE);
9639 /* we did not allocate which means left
9640 already in a pointer register, then
9641 if size > 0 && this could be used again
9642 we have to point it back to where it
9644 if (AOP_SIZE (right) > 1 &&
9645 !OP_SYMBOL (result)->remat &&
9646 (OP_SYMBOL (result)->liveTo > ic->seq ||
9650 int size = AOP_SIZE (right) - 1;
9652 emitcode ("dec", "%s", rname);
9657 if (pi) pi->generated = 1;
9658 freeAsmop (result, NULL, ic, TRUE);
9659 freeAsmop (right, NULL, ic, TRUE);
9664 /*-----------------------------------------------------------------*/
9665 /* genFarPointerSet - set value from far space */
9666 /*-----------------------------------------------------------------*/
9668 genFarPointerSet (operand * right,
9669 operand * result, iCode * ic, iCode *pi)
9671 int size, offset, dopi=1;
9672 sym_link *retype = getSpec (operandType (right));
9673 sym_link *letype = getSpec (operandType (result));
9675 aopOp (result, ic, FALSE, FALSE);
9677 /* if the operand is already in dptr
9678 then we do nothing else we move the value to dptr */
9679 if (AOP_TYPE (result) != AOP_STR)
9681 /* if this is remateriazable */
9682 if (AOP_TYPE (result) == AOP_IMMD)
9683 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9686 /* we need to get it byte by byte */
9687 _startLazyDPSEvaluation ();
9688 if (AOP_TYPE (result) != AOP_DPTR)
9690 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9691 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9692 if (options.model == MODEL_FLAT24)
9693 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9697 /* We need to generate a load to DPTR indirect through DPTR. */
9698 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9700 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9701 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9702 if (options.model == MODEL_FLAT24)
9703 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9704 emitcode ("pop", "dph");
9705 emitcode ("pop", "dpl");
9708 _endLazyDPSEvaluation ();
9711 /* so dptr know contains the address */
9712 aopOp (right, ic, FALSE, TRUE);
9714 /* if bit then unpack */
9715 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9716 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9719 size = AOP_SIZE (right);
9722 _startLazyDPSEvaluation ();
9725 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9731 emitcode ("movx", "@dptr,a");
9732 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9733 emitcode ("inc", "dptr");
9735 _endLazyDPSEvaluation ();
9738 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9739 aopPut (AOP(result),"dpl",0);
9740 aopPut (AOP(result),"dph",1);
9741 if (options.model == MODEL_FLAT24)
9742 aopPut (AOP(result),"dpx",2);
9744 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9745 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9747 size = AOP_SIZE (right) - 1;
9748 while (size--) emitcode ("lcall","__decdptr");
9750 freeAsmop (result, NULL, ic, TRUE);
9751 freeAsmop (right, NULL, ic, TRUE);
9754 /*-----------------------------------------------------------------*/
9755 /* genGenPointerSet - set value from generic pointer space */
9756 /*-----------------------------------------------------------------*/
9758 genGenPointerSet (operand * right,
9759 operand * result, iCode * ic, iCode *pi)
9762 sym_link *retype = getSpec (operandType (right));
9763 sym_link *letype = getSpec (operandType (result));
9765 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9767 /* if the operand is already in dptr
9768 then we do nothing else we move the value to dptr */
9769 if (AOP_TYPE (result) != AOP_STR)
9771 _startLazyDPSEvaluation ();
9772 /* if this is remateriazable */
9773 if (AOP_TYPE (result) == AOP_IMMD)
9775 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9776 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9777 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9779 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9782 { /* we need to get it byte by byte */
9783 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9784 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9785 if (options.model == MODEL_FLAT24) {
9786 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9787 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9789 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9792 _endLazyDPSEvaluation ();
9794 /* so dptr know contains the address */
9795 aopOp (right, ic, FALSE, TRUE);
9797 /* if bit then unpack */
9798 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9799 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9802 size = AOP_SIZE (right);
9805 _startLazyDPSEvaluation ();
9808 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9814 emitcode ("lcall", "__gptrput");
9815 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9816 emitcode ("inc", "dptr");
9818 _endLazyDPSEvaluation ();
9821 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9822 aopPut (AOP(result),"dpl",0);
9823 aopPut (AOP(result),"dph",1);
9824 if (options.model == MODEL_FLAT24) {
9825 aopPut (AOP(result),"dpx",2);
9826 aopPut (AOP(result),"b",3);
9828 aopPut (AOP(result),"b",2);
9831 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9832 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9834 size = AOP_SIZE (right) - 1;
9835 while (size--) emitcode ("lcall","__decdptr");
9837 freeAsmop (result, NULL, ic, TRUE);
9838 freeAsmop (right, NULL, ic, TRUE);
9841 /*-----------------------------------------------------------------*/
9842 /* genPointerSet - stores the value into a pointer location */
9843 /*-----------------------------------------------------------------*/
9845 genPointerSet (iCode * ic, iCode *pi)
9847 operand *right, *result;
9848 sym_link *type, *etype;
9851 D (emitcode (";", "genPointerSet ");
9854 right = IC_RIGHT (ic);
9855 result = IC_RESULT (ic);
9857 /* depending on the type of pointer we need to
9858 move it to the correct pointer register */
9859 type = operandType (result);
9860 etype = getSpec (type);
9861 /* if left is of type of pointer then it is simple */
9862 if (IS_PTR (type) && !IS_FUNC (type->next))
9864 p_type = DCL_TYPE (type);
9868 /* we have to go by the storage class */
9869 p_type = PTR_TYPE (SPEC_OCLS (etype));
9871 /* special case when cast remat */
9872 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9873 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9874 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9875 type = type = operandType (result);
9876 p_type = DCL_TYPE (type);
9879 /* now that we have the pointer type we assign
9880 the pointer values */
9886 genNearPointerSet (right, result, ic, pi);
9890 genPagedPointerSet (right, result, ic, pi);
9894 genFarPointerSet (right, result, ic, pi);
9898 genGenPointerSet (right, result, ic, pi);
9904 /*-----------------------------------------------------------------*/
9905 /* genIfx - generate code for Ifx statement */
9906 /*-----------------------------------------------------------------*/
9908 genIfx (iCode * ic, iCode * popIc)
9910 operand *cond = IC_COND (ic);
9913 D (emitcode (";", "genIfx "););
9915 aopOp (cond, ic, FALSE, FALSE);
9917 /* get the value into acc */
9918 if (AOP_TYPE (cond) != AOP_CRY)
9922 /* the result is now in the accumulator */
9923 freeAsmop (cond, NULL, ic, TRUE);
9925 /* if there was something to be popped then do it */
9929 /* if the condition is a bit variable */
9930 if (isbit && IS_ITEMP (cond) &&
9932 genIfxJump (ic, SPIL_LOC (cond)->rname);
9933 else if (isbit && !IS_ITEMP (cond))
9934 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9936 genIfxJump (ic, "a");
9941 /*-----------------------------------------------------------------*/
9942 /* genAddrOf - generates code for address of */
9943 /*-----------------------------------------------------------------*/
9945 genAddrOf (iCode * ic)
9947 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9950 D (emitcode (";", "genAddrOf ");
9953 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9955 /* if the operand is on the stack then we
9956 need to get the stack offset of this
9960 /* if 10 bit stack */
9961 if (options.stack10bit) {
9963 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
9964 /* if it has an offset then we need to compute it */
9965 emitcode ("subb", "a,#!constbyte",
9966 -((sym->stack < 0) ?
9967 ((short) (sym->stack - _G.nRegsSaved)) :
9968 ((short) sym->stack)) & 0xff);
9969 emitcode ("mov","b,a");
9970 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
9971 ((short) (sym->stack - _G.nRegsSaved)) :
9972 ((short) sym->stack)) >> 8) & 0xff);
9974 emitcode ("mov", "a,_bpx");
9975 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
9976 ((char) (sym->stack - _G.nRegsSaved)) :
9977 ((char) sym->stack )) & 0xff);
9978 emitcode ("mov", "b,a");
9979 emitcode ("mov", "a,_bpx+1");
9980 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
9981 ((short) (sym->stack - _G.nRegsSaved)) :
9982 ((short) sym->stack )) >> 8) & 0xff);
9983 aopPut (AOP (IC_RESULT (ic)), "b", 0);
9984 aopPut (AOP (IC_RESULT (ic)), "a", 1);
9985 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9987 /* we can just move _bp */
9988 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9989 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9990 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9993 /* if it has an offset then we need to compute it */
9995 emitcode ("mov", "a,_bp");
9996 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
9997 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9999 /* we can just move _bp */
10000 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10002 /* fill the result with zero */
10003 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10006 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10008 "*** warning: pointer to stack var truncated.\n");
10013 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10019 /* object not on stack then we need the name */
10020 size = AOP_SIZE (IC_RESULT (ic));
10025 char s[SDCC_NAME_MAX];
10029 tsprintf(s,"!his",sym->rname);
10032 tsprintf(s,"!hihis",sym->rname);
10035 tsprintf(s,"!hihihis",sym->rname);
10037 default: /* should not need this (just in case) */
10038 sprintf (s, "#(%s >> %d)",
10043 sprintf (s, "#%s", sym->rname);
10044 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10048 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10052 /*-----------------------------------------------------------------*/
10053 /* genArrayInit - generates code for address of */
10054 /*-----------------------------------------------------------------*/
10056 genArrayInit (iCode * ic)
10058 literalList *iLoop;
10060 int elementSize = 0, eIndex;
10061 unsigned val, lastVal;
10063 operand *left=IC_LEFT(ic);
10065 D (emitcode (";", "genArrayInit "););
10067 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10069 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10071 // Load immediate value into DPTR.
10072 emitcode("mov", "dptr, %s",
10073 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10075 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10078 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10079 "Unexpected operand to genArrayInit.\n");
10082 // a regression because of SDCCcse.c:1.52
10083 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10084 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10085 if (options.model == MODEL_FLAT24)
10086 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10090 type = operandType(IC_LEFT(ic));
10092 if (type && type->next)
10094 elementSize = getSize(type->next);
10098 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10099 "can't determine element size in genArrayInit.\n");
10103 iLoop = IC_ARRAYILIST(ic);
10108 bool firstpass = TRUE;
10110 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10111 iLoop->count, (int)iLoop->literalValue, elementSize);
10117 symbol *tlbl = NULL;
10119 count = ix > 256 ? 256 : ix;
10123 tlbl = newiTempLabel (NULL);
10124 if (firstpass || (count & 0xff))
10126 emitcode("mov", "b, #!constbyte", count & 0xff);
10129 emitcode ("", "!tlabeldef", tlbl->key + 100);
10134 for (eIndex = 0; eIndex < elementSize; eIndex++)
10136 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10137 if (val != lastVal)
10139 emitcode("mov", "a, #!constbyte", val);
10143 emitcode("movx", "@dptr, a");
10144 emitcode("inc", "dptr");
10149 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10155 iLoop = iLoop->next;
10158 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10161 /*-----------------------------------------------------------------*/
10162 /* genFarFarAssign - assignment when both are in far space */
10163 /*-----------------------------------------------------------------*/
10165 genFarFarAssign (operand * result, operand * right, iCode * ic)
10167 int size = AOP_SIZE (right);
10169 symbol *rSym = NULL;
10173 /* quick & easy case. */
10174 D(emitcode(";","genFarFarAssign (1 byte case)"););
10175 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10176 freeAsmop (right, NULL, ic, FALSE);
10177 /* now assign DPTR to result */
10179 aopOp(result, ic, FALSE, FALSE);
10181 aopPut(AOP(result), "a", 0);
10182 freeAsmop(result, NULL, ic, FALSE);
10186 /* See if we've got an underlying symbol to abuse. */
10187 if (IS_SYMOP(result) && OP_SYMBOL(result))
10189 if (IS_TRUE_SYMOP(result))
10191 rSym = OP_SYMBOL(result);
10193 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10195 rSym = OP_SYMBOL(result)->usl.spillLoc;
10199 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10201 /* We can use the '390 auto-toggle feature to good effect here. */
10203 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10204 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10205 emitcode ("mov", "dptr,#%s", rSym->rname);
10206 /* DP2 = result, DP1 = right, DP1 is current. */
10209 emitcode("movx", "a,@dptr");
10210 emitcode("movx", "@dptr,a");
10213 emitcode("inc", "dptr");
10214 emitcode("inc", "dptr");
10217 emitcode("mov", "dps, #0");
10218 freeAsmop (right, NULL, ic, FALSE);
10220 some alternative code for processors without auto-toggle
10221 no time to test now, so later well put in...kpb
10222 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10223 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10224 emitcode ("mov", "dptr,#%s", rSym->rname);
10225 /* DP2 = result, DP1 = right, DP1 is current. */
10229 emitcode("movx", "a,@dptr");
10231 emitcode("inc", "dptr");
10232 emitcode("inc", "dps");
10233 emitcode("movx", "@dptr,a");
10235 emitcode("inc", "dptr");
10236 emitcode("inc", "dps");
10238 emitcode("mov", "dps, #0");
10239 freeAsmop (right, NULL, ic, FALSE);
10244 D (emitcode (";", "genFarFarAssign"););
10245 aopOp (result, ic, TRUE, TRUE);
10247 _startLazyDPSEvaluation ();
10251 aopPut (AOP (result),
10252 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10255 _endLazyDPSEvaluation ();
10256 freeAsmop (result, NULL, ic, FALSE);
10257 freeAsmop (right, NULL, ic, FALSE);
10261 /*-----------------------------------------------------------------*/
10262 /* genAssign - generate code for assignment */
10263 /*-----------------------------------------------------------------*/
10265 genAssign (iCode * ic)
10267 operand *result, *right;
10269 unsigned long lit = 0L;
10271 D (emitcode (";", "genAssign ");
10274 result = IC_RESULT (ic);
10275 right = IC_RIGHT (ic);
10277 /* if they are the same */
10278 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10281 aopOp (right, ic, FALSE, FALSE);
10283 emitcode (";", "genAssign: resultIsFar = %s",
10284 isOperandInFarSpace (result) ?
10287 /* special case both in far space */
10288 if ((AOP_TYPE (right) == AOP_DPTR ||
10289 AOP_TYPE (right) == AOP_DPTR2) &&
10290 /* IS_TRUE_SYMOP(result) && */
10291 isOperandInFarSpace (result))
10293 genFarFarAssign (result, right, ic);
10297 aopOp (result, ic, TRUE, FALSE);
10299 /* if they are the same registers */
10300 if (sameRegs (AOP (right), AOP (result)))
10303 /* if the result is a bit */
10304 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10306 /* if the right size is a literal then
10307 we know what the value is */
10308 if (AOP_TYPE (right) == AOP_LIT)
10310 if (((int) operandLitValue (right)))
10311 aopPut (AOP (result), one, 0);
10313 aopPut (AOP (result), zero, 0);
10317 /* the right is also a bit variable */
10318 if (AOP_TYPE (right) == AOP_CRY)
10320 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10321 aopPut (AOP (result), "c", 0);
10325 /* we need to or */
10327 aopPut (AOP (result), "a", 0);
10331 /* bit variables done */
10333 size = AOP_SIZE (result);
10335 if (AOP_TYPE (right) == AOP_LIT)
10336 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10339 (AOP_TYPE (result) != AOP_REG) &&
10340 (AOP_TYPE (right) == AOP_LIT) &&
10341 !IS_FLOAT (operandType (right)))
10343 _startLazyDPSEvaluation ();
10344 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10346 aopPut (AOP (result),
10347 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10352 /* And now fill the rest with zeros. */
10355 emitcode ("clr", "a");
10359 aopPut (AOP (result), "a", offset++);
10361 _endLazyDPSEvaluation ();
10365 _startLazyDPSEvaluation ();
10368 aopPut (AOP (result),
10369 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10373 _endLazyDPSEvaluation ();
10377 freeAsmop (right, NULL, ic, FALSE);
10378 freeAsmop (result, NULL, ic, TRUE);
10381 /*-----------------------------------------------------------------*/
10382 /* genJumpTab - generates code for jump table */
10383 /*-----------------------------------------------------------------*/
10385 genJumpTab (iCode * ic)
10390 D (emitcode (";", "genJumpTab ");
10393 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10394 /* get the condition into accumulator */
10395 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10397 /* multiply by four! */
10398 emitcode ("add", "a,acc");
10399 emitcode ("add", "a,acc");
10400 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10402 jtab = newiTempLabel (NULL);
10403 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10404 emitcode ("jmp", "@a+dptr");
10405 emitcode ("", "!tlabeldef", jtab->key + 100);
10406 /* now generate the jump labels */
10407 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10408 jtab = setNextItem (IC_JTLABELS (ic)))
10409 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10413 /*-----------------------------------------------------------------*/
10414 /* genCast - gen code for casting */
10415 /*-----------------------------------------------------------------*/
10417 genCast (iCode * ic)
10419 operand *result = IC_RESULT (ic);
10420 sym_link *ctype = operandType (IC_LEFT (ic));
10421 sym_link *rtype = operandType (IC_RIGHT (ic));
10422 operand *right = IC_RIGHT (ic);
10425 D (emitcode (";", "genCast ");
10428 /* if they are equivalent then do nothing */
10429 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10432 aopOp (right, ic, FALSE, FALSE);
10433 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10435 /* if the result is a bit */
10436 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10437 if (IS_BITVAR(OP_SYMBOL(result)->type))
10439 /* if the right size is a literal then
10440 we know what the value is */
10441 if (AOP_TYPE (right) == AOP_LIT)
10443 if (((int) operandLitValue (right)))
10444 aopPut (AOP (result), one, 0);
10446 aopPut (AOP (result), zero, 0);
10451 /* the right is also a bit variable */
10452 if (AOP_TYPE (right) == AOP_CRY)
10454 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10455 aopPut (AOP (result), "c", 0);
10459 /* we need to or */
10461 aopPut (AOP (result), "a", 0);
10465 /* if they are the same size : or less */
10466 if (AOP_SIZE (result) <= AOP_SIZE (right))
10469 /* if they are in the same place */
10470 if (sameRegs (AOP (right), AOP (result)))
10473 /* if they in different places then copy */
10474 size = AOP_SIZE (result);
10476 _startLazyDPSEvaluation ();
10479 aopPut (AOP (result),
10480 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10484 _endLazyDPSEvaluation ();
10489 /* if the result is of type pointer */
10490 if (IS_PTR (ctype))
10494 sym_link *type = operandType (right);
10496 /* pointer to generic pointer */
10497 if (IS_GENPTR (ctype))
10503 p_type = DCL_TYPE (type);
10507 #if OLD_CAST_BEHAVIOR
10508 /* KV: we are converting a non-pointer type to
10509 * a generic pointer. This (ifdef'd out) code
10510 * says that the resulting generic pointer
10511 * should have the same class as the storage
10512 * location of the non-pointer variable.
10514 * For example, converting an int (which happens
10515 * to be stored in DATA space) to a pointer results
10516 * in a DATA generic pointer; if the original int
10517 * in XDATA space, so will be the resulting pointer.
10519 * I don't like that behavior, and thus this change:
10520 * all such conversions will be forced to XDATA and
10521 * throw a warning. If you want some non-XDATA
10522 * type, or you want to suppress the warning, you
10523 * must go through an intermediate cast, like so:
10525 * char _generic *gp = (char _xdata *)(intVar);
10527 sym_link *etype = getSpec (type);
10529 /* we have to go by the storage class */
10530 if (SPEC_OCLS (etype) != generic)
10532 p_type = PTR_TYPE (SPEC_OCLS (etype));
10537 /* Converting unknown class (i.e. register variable)
10538 * to generic pointer. This is not good, but
10539 * we'll make a guess (and throw a warning).
10542 werror (W_INT_TO_GEN_PTR_CAST);
10546 /* the first two bytes are known */
10547 size = GPTRSIZE - 1;
10549 _startLazyDPSEvaluation ();
10552 aopPut (AOP (result),
10553 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10557 _endLazyDPSEvaluation ();
10559 /* the last byte depending on type */
10577 /* this should never happen */
10578 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10579 "got unknown pointer type");
10582 aopPut (AOP (result), l, GPTRSIZE - 1);
10586 /* just copy the pointers */
10587 size = AOP_SIZE (result);
10589 _startLazyDPSEvaluation ();
10592 aopPut (AOP (result),
10593 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10597 _endLazyDPSEvaluation ();
10601 /* so we now know that the size of destination is greater
10602 than the size of the source */
10603 /* we move to result for the size of source */
10604 size = AOP_SIZE (right);
10606 _startLazyDPSEvaluation ();
10609 aopPut (AOP (result),
10610 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10614 _endLazyDPSEvaluation ();
10616 /* now depending on the sign of the source && destination */
10617 size = AOP_SIZE (result) - AOP_SIZE (right);
10618 /* if unsigned or not an integral type */
10619 /* also, if the source is a bit, we don't need to sign extend, because
10620 * it can't possibly have set the sign bit.
10622 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10626 aopPut (AOP (result), zero, offset++);
10631 /* we need to extend the sign :{ */
10632 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10633 FALSE, FALSE, TRUE);
10635 emitcode ("rlc", "a");
10636 emitcode ("subb", "a,acc");
10638 aopPut (AOP (result), "a", offset++);
10641 /* we are done hurray !!!! */
10644 freeAsmop (right, NULL, ic, TRUE);
10645 freeAsmop (result, NULL, ic, TRUE);
10649 /*-----------------------------------------------------------------*/
10650 /* genDjnz - generate decrement & jump if not zero instrucion */
10651 /*-----------------------------------------------------------------*/
10653 genDjnz (iCode * ic, iCode * ifx)
10655 symbol *lbl, *lbl1;
10659 /* if the if condition has a false label
10660 then we cannot save */
10661 if (IC_FALSE (ifx))
10664 /* if the minus is not of the form
10666 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10667 !IS_OP_LITERAL (IC_RIGHT (ic)))
10670 if (operandLitValue (IC_RIGHT (ic)) != 1)
10673 /* if the size of this greater than one then no
10675 if (getSize (operandType (IC_RESULT (ic))) > 1)
10678 /* otherwise we can save BIG */
10679 D(emitcode(";", "genDjnz"););
10681 lbl = newiTempLabel (NULL);
10682 lbl1 = newiTempLabel (NULL);
10684 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10686 if (AOP_NEEDSACC(IC_RESULT(ic)))
10688 /* If the result is accessed indirectly via
10689 * the accumulator, we must explicitly write
10690 * it back after the decrement.
10692 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10694 if (strcmp(rByte, "a"))
10696 /* Something is hopelessly wrong */
10697 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10698 __FILE__, __LINE__);
10699 /* We can just give up; the generated code will be inefficient,
10700 * but what the hey.
10702 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10705 emitcode ("dec", "%s", rByte);
10706 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10707 emitcode ("jnz", "!tlabel", lbl->key + 100);
10709 else if (IS_AOP_PREG (IC_RESULT (ic)))
10711 emitcode ("dec", "%s",
10712 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10713 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10714 emitcode ("jnz", "!tlabel", lbl->key + 100);
10718 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10721 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10722 emitcode ("", "!tlabeldef", lbl->key + 100);
10723 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10724 emitcode ("", "!tlabeldef", lbl1->key + 100);
10726 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10727 ifx->generated = 1;
10731 /*-----------------------------------------------------------------*/
10732 /* genReceive - generate code for a receive iCode */
10733 /*-----------------------------------------------------------------*/
10735 genReceive (iCode * ic)
10738 D (emitcode (";", "genReceive ");
10741 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10742 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10743 IS_TRUE_SYMOP (IC_RESULT (ic))))
10745 int size = getSize (operandType (IC_RESULT (ic)));
10746 int offset = fReturnSizeDS390 - size;
10749 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10750 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10753 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10754 size = AOP_SIZE (IC_RESULT (ic));
10758 emitcode ("pop", "acc");
10759 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10766 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10768 assignResultValue (IC_RESULT (ic));
10771 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10774 /*-----------------------------------------------------------------*/
10775 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10776 /*-----------------------------------------------------------------*/
10777 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10779 operand *from , *to , *count;
10782 /* we know it has to be 3 parameters */
10783 assert (nparms == 3);
10789 aopOp (from, ic->next, FALSE, FALSE);
10791 /* get from into DPTR1 */
10792 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10793 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10794 if (options.model == MODEL_FLAT24) {
10795 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10798 freeAsmop (from, NULL, ic, FALSE);
10799 aopOp (to, ic, FALSE, FALSE);
10800 /* get "to" into DPTR */
10801 /* if the operand is already in dptr
10802 then we do nothing else we move the value to dptr */
10803 if (AOP_TYPE (to) != AOP_STR) {
10804 /* if already in DPTR then we need to push */
10805 if (AOP_TYPE(to) == AOP_DPTR) {
10806 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10807 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10808 if (options.model == MODEL_FLAT24)
10809 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10810 emitcode ("pop", "dph");
10811 emitcode ("pop", "dpl");
10813 _startLazyDPSEvaluation ();
10814 /* if this is remateriazable */
10815 if (AOP_TYPE (to) == AOP_IMMD) {
10816 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10817 } else { /* we need to get it byte by byte */
10818 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10819 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10820 if (options.model == MODEL_FLAT24) {
10821 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10824 _endLazyDPSEvaluation ();
10827 freeAsmop (to, NULL, ic, FALSE);
10829 aopOp (count, ic->next->next, FALSE,FALSE);
10830 lbl =newiTempLabel(NULL);
10832 /* now for the actual copy */
10833 if (AOP_TYPE(count) == AOP_LIT &&
10834 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10835 emitcode (";","OH! JOY auto increment with djnz (very fast)");
10836 emitcode ("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10837 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10838 emitcode ("","!tlabeldef",lbl->key+100);
10840 emitcode ("clr","a");
10841 emitcode ("movc", "a,@a+dptr");
10843 emitcode ("movx", "a,@dptr");
10844 emitcode ("movx", "@dptr,a");
10845 emitcode ("inc", "dptr");
10846 emitcode ("inc", "dptr");
10847 emitcode ("djnz","b,!tlabel",lbl->key+100);
10849 symbol *lbl1 = newiTempLabel(NULL);
10851 emitcode (";"," Auto increment but no djnz");
10852 emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10853 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10854 emitcode ("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10855 emitcode ("","!tlabeldef",lbl->key+100);
10857 emitcode ("clr","a");
10858 emitcode ("movc", "a,@a+dptr");
10860 emitcode ("movx", "a,@dptr");
10861 emitcode ("movx", "@dptr,a");
10862 emitcode ("inc", "dptr");
10863 emitcode ("inc", "dptr");
10864 emitcode ("mov","a,b");
10865 emitcode ("orl","a,ap");
10866 emitcode ("jz","!tlabel",lbl1->key+100);
10867 emitcode ("mov","a,ap");
10868 emitcode ("add","a,#0xFF");
10869 emitcode ("mov","ap,a");
10870 emitcode ("mov","a,b");
10871 emitcode ("addc","a,#0xFF");
10872 emitcode ("mov","b,a");
10873 emitcode ("sjmp","!tlabel",lbl->key+100);
10874 emitcode ("","!tlabeldef",lbl1->key+100);
10876 emitcode ("mov", "dps, #0");
10877 freeAsmop (count, NULL, ic, FALSE);
10881 /*-----------------------------------------------------------------*/
10882 /* genMemsetX - gencode for memSetX data */
10883 /*-----------------------------------------------------------------*/
10884 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10886 operand *to , *val , *count;
10889 /* we know it has to be 3 parameters */
10890 assert (nparms == 3);
10896 aopOp (to, ic, FALSE, FALSE);
10897 /* get "to" into DPTR */
10898 /* if the operand is already in dptr
10899 then we do nothing else we move the value to dptr */
10900 if (AOP_TYPE (to) != AOP_STR) {
10901 /* if already in DPTR then we need to push */
10902 if (AOP_TYPE(to) == AOP_DPTR) {
10903 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10904 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10905 if (options.model == MODEL_FLAT24)
10906 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10907 emitcode ("pop", "dph");
10908 emitcode ("pop", "dpl");
10910 _startLazyDPSEvaluation ();
10911 /* if this is remateriazable */
10912 if (AOP_TYPE (to) == AOP_IMMD) {
10913 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10914 } else { /* we need to get it byte by byte */
10915 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10916 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10917 if (options.model == MODEL_FLAT24) {
10918 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10921 _endLazyDPSEvaluation ();
10924 freeAsmop (to, NULL, ic, FALSE);
10926 aopOp (val, ic->next->next, FALSE,FALSE);
10927 aopOp (count, ic->next->next, FALSE,FALSE);
10928 lbl =newiTempLabel(NULL);
10929 /* now for the actual copy */
10930 if (AOP_TYPE(count) == AOP_LIT &&
10931 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10932 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10933 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10935 emitcode ("","!tlabeldef",lbl->key+100);
10936 emitcode ("movx", "@dptr,a");
10937 emitcode ("inc", "dptr");
10938 emitcode ("djnz","b,!tlabel",lbl->key+100);
10940 symbol *lbl1 = newiTempLabel(NULL);
10942 emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10943 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10944 emitcode ("","!tlabeldef",lbl->key+100);
10945 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10947 emitcode ("movx", "a,@dptr");
10948 emitcode ("inc", "dptr");
10949 emitcode ("mov","a,b");
10950 emitcode ("orl","a,ap");
10951 emitcode ("jz","!tlabel",lbl1->key+100);
10952 emitcode ("mov","a,ap");
10953 emitcode ("add","a,#0xFF");
10954 emitcode ("mov","ap,a");
10955 emitcode ("mov","a,b");
10956 emitcode ("addc","a,#0xFF");
10957 emitcode ("mov","b,a");
10958 emitcode ("sjmp","!tlabel",lbl->key+100);
10959 emitcode ("","!tlabeldef",lbl1->key+100);
10961 freeAsmop (count, NULL, ic, FALSE);
10964 /*-----------------------------------------------------------------*/
10965 /* genBuiltIn - calls the appropriate function to generating code */
10966 /* for a built in function */
10967 /*-----------------------------------------------------------------*/
10968 static void genBuiltIn (iCode *ic)
10970 operand *bi_parms[MAX_BUILTIN_ARGS];
10975 /* get all the arguments for a built in function */
10976 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
10978 /* which function is it */
10979 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
10980 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
10981 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
10982 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
10983 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
10984 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
10985 genMemsetX(bi_iCode,nbi_parms,bi_parms);
10987 werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n");
10993 /*-----------------------------------------------------------------*/
10994 /* gen390Code - generate code for Dallas 390 based controllers */
10995 /*-----------------------------------------------------------------*/
10997 gen390Code (iCode * lic)
11002 lineHead = lineCurr = NULL;
11004 if (options.model == MODEL_FLAT24) {
11005 fReturnSizeDS390 = 5;
11006 fReturn = fReturn24;
11008 fReturnSizeDS390 = 4;
11009 fReturn = fReturn16;
11010 options.stack10bit=0;
11014 /* print the allocation information */
11016 printAllocInfo (currFunc, codeOutFile);
11018 /* if debug information required */
11019 if (options.debug && currFunc)
11021 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11023 if (IS_STATIC (currFunc->etype))
11024 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11026 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11029 /* stack pointer name */
11030 if (options.useXstack)
11036 for (ic = lic; ic; ic = ic->next)
11039 if (cln != ic->lineno)
11044 emitcode ("", "C$%s$%d$%d$%d ==.",
11045 FileBaseName (ic->filename), ic->lineno,
11046 ic->level, ic->block);
11049 emitcode (";", "%s %d", ic->filename, ic->lineno);
11052 /* if the result is marked as
11053 spilt and rematerializable or code for
11054 this has already been generated then
11056 if (resultRemat (ic) || ic->generated)
11059 /* depending on the operation */
11079 /* IPOP happens only when trying to restore a
11080 spilt live range, if there is an ifx statement
11081 following this pop then the if statement might
11082 be using some of the registers being popped which
11083 would destory the contents of the register so
11084 we need to check for this condition and handle it */
11086 ic->next->op == IFX &&
11087 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11088 genIfx (ic->next, ic);
11106 genEndFunction (ic);
11126 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11143 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11147 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11154 /* note these two are xlated by algebraic equivalence
11155 during parsing SDCC.y */
11156 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11157 "got '>=' or '<=' shouldn't have come here");
11161 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11173 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11177 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11181 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11205 genRightShift (ic);
11208 case GET_VALUE_AT_ADDRESS:
11209 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11213 if (POINTER_SET (ic))
11214 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11240 if (ic->builtinSEND) genBuiltIn(ic);
11241 else addSet (&_G.sendSet, ic);
11254 /* now we are ready to call the
11255 peep hole optimizer */
11256 if (!options.nopeep)
11257 peepHole (&lineHead);
11259 /* now do the actual printing */
11260 printLine (lineHead, codeOutFile);