1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
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)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
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"
55 char *aopLiteral (value * val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0x00";
67 static char *one = "#0x01";
72 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
73 static char *fReturn[] =
74 {"dpl", "dph", "dpx", "b", "a"};
75 static char *accUse[] =
78 static short rbank = -1;
92 static void saverbank (int, iCode *, bool);
94 #define RESULTONSTACK(x) \
95 (IC_RESULT(x) && IC_RESULT(x)->aop && \
96 IC_RESULT(x)->aop->type == AOP_STK )
98 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
99 #define MOVA(x) { char *_mova_tmp = strdup(x); \
100 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
102 emitcode("mov","a,%s",_mova_tmp); \
106 #define CLRC emitcode("clr","c")
107 #define SETC emitcode("setb","c")
109 static lineNode *lineHead = NULL;
110 static lineNode *lineCurr = NULL;
112 static unsigned char SLMask[] =
113 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
114 0xE0, 0xC0, 0x80, 0x00};
115 static unsigned char SRMask[] =
116 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
117 0x07, 0x03, 0x01, 0x00};
124 /*-----------------------------------------------------------------*/
125 /* emitcode - writes the code into a file : for now it is simple */
126 /*-----------------------------------------------------------------*/
128 emitcode (char *inst, char *fmt,...)
131 char lb[MAX_INLINEASM];
139 sprintf (lb, "%s\t", inst);
141 sprintf (lb, "%s", inst);
142 vsprintf (lb + (strlen (lb)), fmt, ap);
145 vsprintf (lb, fmt, ap);
147 while (isspace (*lbp))
151 lineCurr = (lineCurr ?
152 connectLine (lineCurr, newLineNode (lb)) :
153 (lineHead = newLineNode (lb)));
154 lineCurr->isInline = _G.inLine;
155 lineCurr->isDebug = _G.debugLine;
159 /*-----------------------------------------------------------------*/
160 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
161 /*-----------------------------------------------------------------*/
163 getFreePtr (iCode * ic, asmop ** aopp, bool result)
165 bool r0iu = FALSE, r1iu = FALSE;
166 bool r0ou = FALSE, r1ou = FALSE;
168 /* the logic: if r0 & r1 used in the instruction
169 then we are in trouble otherwise */
171 /* first check if r0 & r1 are used by this
172 instruction, in which case we are in trouble */
173 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
174 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
179 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
180 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
182 /* if no usage of r0 then return it */
185 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
186 (*aopp)->type = AOP_R0;
188 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
191 /* if no usage of r1 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
195 (*aopp)->type = AOP_R1;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
200 /* now we know they both have usage */
201 /* if r0 not used in this instruction */
204 /* push it if not already pushed */
207 emitcode ("push", "%s",
208 ds390_regWithIdx (R0_IDX)->dname);
212 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
213 (*aopp)->type = AOP_R0;
215 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
218 /* if r1 not used then */
222 /* push it if not already pushed */
225 emitcode ("push", "%s",
226 ds390_regWithIdx (R1_IDX)->dname);
230 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
231 (*aopp)->type = AOP_R1;
232 return ds390_regWithIdx (R1_IDX);
236 /* I said end of world but not quite end of world yet */
237 /* if this is a result then we can push it on the stack */
240 (*aopp)->type = AOP_STK;
245 /* other wise this is true end of the world */
246 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
247 "getFreePtr should never reach here");
251 /*-----------------------------------------------------------------*/
252 /* newAsmop - creates a new asmOp */
253 /*-----------------------------------------------------------------*/
255 newAsmop (short type)
259 aop = Safe_calloc (1, sizeof (asmop));
264 static int _currentDPS; /* Current processor DPS. */
265 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
266 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
268 /*-----------------------------------------------------------------*/
269 /* genSetDPTR: generate code to select which DPTR is in use (zero */
270 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
271 /* alternate DPTR (DPL1/DPH1/DPX1). */
272 /*-----------------------------------------------------------------*/
277 /* If we are doing lazy evaluation, simply note the desired
278 * change, but don't emit any code yet.
288 emitcode ("mov", "dps, #0x00");
292 emitcode ("mov", "dps, #0x01");
296 /*-----------------------------------------------------------------*/
297 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
299 /* Any code that operates on DPTR (NB: not on the individual */
300 /* components, like DPH) *must* call _flushLazyDPS() before using */
301 /* DPTR within a lazy DPS evaluation block. */
303 /* Note that aopPut and aopGet already contain the proper calls to */
304 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
305 /* DPS evaluation block. */
307 /* Also, _flushLazyDPS must be called before any flow control */
308 /* operations that could potentially branch out of the block. */
310 /* Lazy DPS evaluation is simply an optimization (though an */
311 /* important one), so if in doubt, leave it out. */
312 /*-----------------------------------------------------------------*/
314 _startLazyDPSEvaluation (void)
321 /*-----------------------------------------------------------------*/
322 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
323 /* desired one. Call before using DPTR within a lazy DPS evaluation */
325 /*-----------------------------------------------------------------*/
335 if (_desiredDPS != _currentDPS)
339 emitcode ("inc", "dps");
343 emitcode ("dec", "dps");
345 _currentDPS = _desiredDPS;
349 /*-----------------------------------------------------------------*/
350 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
352 /* Forces us back to the safe state (standard DPTR selected). */
353 /*-----------------------------------------------------------------*/
355 _endLazyDPSEvaluation (void)
369 /*-----------------------------------------------------------------*/
370 /* pointerCode - returns the code for a pointer type */
371 /*-----------------------------------------------------------------*/
373 pointerCode (sym_link * etype)
376 return PTR_TYPE (SPEC_OCLS (etype));
380 /*-----------------------------------------------------------------*/
381 /* aopForSym - for a true symbol */
382 /*-----------------------------------------------------------------*/
384 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
387 memmap *space = SPEC_OCLS (sym->etype);
389 /* if already has one */
393 /* assign depending on the storage class */
394 /* if it is on the stack or indirectly addressable */
395 /* space we need to assign either r0 or r1 to it */
396 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
398 sym->aop = aop = newAsmop (0);
399 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
400 aop->size = getSize (sym->type);
402 /* now assign the address of the variable to
403 the pointer register */
404 if (aop->type != AOP_STK)
410 emitcode ("push", "acc");
412 emitcode ("mov", "a,_bp");
413 emitcode ("add", "a,#0x%02x",
415 ((char) (sym->stack - _G.nRegsSaved)) :
416 ((char) sym->stack)) & 0xff);
417 emitcode ("mov", "%s,a",
418 aop->aopu.aop_ptr->name);
421 emitcode ("pop", "acc");
424 emitcode ("mov", "%s,#%s",
425 aop->aopu.aop_ptr->name,
427 aop->paged = space->paged;
430 aop->aopu.aop_stk = sym->stack;
434 if (sym->onStack && options.stack10bit)
436 /* It's on the 10 bit stack, which is located in
441 emitcode ("push", "acc");
443 emitcode ("mov", "a,_bp");
444 emitcode ("add", "a,#0x%02x",
446 ((char) (sym->stack - _G.nRegsSaved)) :
447 ((char) sym->stack)) & 0xff);
452 emitcode ("mov", "dpx1,#0x40");
453 emitcode ("mov", "dph1,#0x00");
454 emitcode ("mov", "dpl1, a");
459 emitcode ("mov", "dpx,#0x40");
460 emitcode ("mov", "dph,#0x00");
461 emitcode ("mov", "dpl, a");
465 emitcode ("pop", "acc");
467 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
468 aop->size = getSize (sym->type);
472 /* if in bit space */
473 if (IN_BITSPACE (space))
475 sym->aop = aop = newAsmop (AOP_CRY);
476 aop->aopu.aop_dir = sym->rname;
477 aop->size = getSize (sym->type);
480 /* if it is in direct space */
481 if (IN_DIRSPACE (space))
483 sym->aop = aop = newAsmop (AOP_DIR);
484 aop->aopu.aop_dir = sym->rname;
485 aop->size = getSize (sym->type);
489 /* special case for a function */
490 if (IS_FUNC (sym->type))
492 sym->aop = aop = newAsmop (AOP_IMMD);
493 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
494 strcpy (aop->aopu.aop_immd, sym->rname);
495 aop->size = FPTRSIZE;
499 /* only remaining is far space */
500 /* in which case DPTR gets the address */
501 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
506 emitcode ("mov", "dptr,#%s", sym->rname);
511 emitcode ("mov", "dptr,#%s", sym->rname);
513 aop->size = getSize (sym->type);
515 /* if it is in code space */
516 if (IN_CODESPACE (space))
522 /*-----------------------------------------------------------------*/
523 /* aopForRemat - rematerialzes an object */
524 /*-----------------------------------------------------------------*/
526 aopForRemat (symbol * sym)
528 iCode *ic = sym->rematiCode;
529 asmop *aop = newAsmop (AOP_IMMD);
536 val += (int) operandLitValue (IC_RIGHT (ic));
537 else if (ic->op == '-')
538 val -= (int) operandLitValue (IC_RIGHT (ic));
542 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
546 sprintf (buffer, "(%s %c 0x%04x)",
547 OP_SYMBOL (IC_LEFT (ic))->rname,
548 val >= 0 ? '+' : '-',
551 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
553 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
554 strcpy (aop->aopu.aop_immd, buffer);
558 /*-----------------------------------------------------------------*/
559 /* regsInCommon - two operands have some registers in common */
560 /*-----------------------------------------------------------------*/
562 regsInCommon (operand * op1, operand * op2)
567 /* if they have registers in common */
568 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
571 sym1 = OP_SYMBOL (op1);
572 sym2 = OP_SYMBOL (op2);
574 if (sym1->nRegs == 0 || sym2->nRegs == 0)
577 for (i = 0; i < sym1->nRegs; i++)
583 for (j = 0; j < sym2->nRegs; j++)
588 if (sym2->regs[j] == sym1->regs[i])
596 /*-----------------------------------------------------------------*/
597 /* operandsEqu - equivalent */
598 /*-----------------------------------------------------------------*/
600 operandsEqu (operand * op1, operand * op2)
604 /* if they not symbols */
605 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
608 sym1 = OP_SYMBOL (op1);
609 sym2 = OP_SYMBOL (op2);
611 /* if both are itemps & one is spilt
612 and the other is not then false */
613 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
614 sym1->isspilt != sym2->isspilt)
617 /* if they are the same */
621 if (strcmp (sym1->rname, sym2->rname) == 0)
625 /* if left is a tmp & right is not */
626 if (IS_ITEMP (op1) &&
629 (sym1->usl.spillLoc == sym2))
632 if (IS_ITEMP (op2) &&
636 (sym2->usl.spillLoc == sym1))
642 /*-----------------------------------------------------------------*/
643 /* sameRegs - two asmops have the same registers */
644 /*-----------------------------------------------------------------*/
646 sameRegs (asmop * aop1, asmop * aop2)
652 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
659 if (aop1->type != AOP_REG ||
660 aop2->type != AOP_REG)
663 if (aop1->size != aop2->size)
666 for (i = 0; i < aop1->size; i++)
667 if (aop1->aopu.aop_reg[i] !=
668 aop2->aopu.aop_reg[i])
674 /*-----------------------------------------------------------------*/
675 /* aopOp - allocates an asmop for an operand : */
676 /*-----------------------------------------------------------------*/
678 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
687 /* if this a literal */
688 if (IS_OP_LITERAL (op))
690 op->aop = aop = newAsmop (AOP_LIT);
691 aop->aopu.aop_lit = op->operand.valOperand;
692 aop->size = getSize (operandType (op));
696 /* if already has a asmop then continue */
700 /* if the underlying symbol has a aop */
701 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
703 op->aop = OP_SYMBOL (op)->aop;
707 /* if this is a true symbol */
708 if (IS_TRUE_SYMOP (op))
710 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
714 /* this is a temporary : this has
720 e) can be a return use only */
722 sym = OP_SYMBOL (op);
725 /* if the type is a conditional */
726 if (sym->regType == REG_CND)
728 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
733 /* if it is spilt then two situations
735 b) has a spill location */
736 if (sym->isspilt || sym->nRegs == 0)
739 /* rematerialize it NOW */
742 sym->aop = op->aop = aop =
744 aop->size = getSize (sym->type);
751 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
752 aop->size = getSize (sym->type);
753 for (i = 0; i < 2; i++)
754 aop->aopu.aop_str[i] = accUse[i];
764 /* a AOP_STR uses DPTR, but DPTR is already in use;
767 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
770 aop = op->aop = sym->aop = newAsmop (AOP_STR);
771 aop->size = getSize (sym->type);
772 for (i = 0; i < (int) fReturnSizeDS390; i++)
773 aop->aopu.aop_str[i] = fReturn[i];
777 /* else spill location */
778 sym->aop = op->aop = aop =
779 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
780 aop->size = getSize (sym->type);
784 /* must be in a register */
785 sym->aop = op->aop = aop = newAsmop (AOP_REG);
786 aop->size = sym->nRegs;
787 for (i = 0; i < sym->nRegs; i++)
788 aop->aopu.aop_reg[i] = sym->regs[i];
791 /*-----------------------------------------------------------------*/
792 /* freeAsmop - free up the asmop given to an operand */
793 /*----------------------------------------------------------------*/
795 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
812 /* depending on the asmop type only three cases need work AOP_RO
813 , AOP_R1 && AOP_STK */
821 emitcode ("pop", "ar0");
825 bitVectUnSetBit (ic->rUsed, R0_IDX);
833 emitcode ("pop", "ar1");
837 bitVectUnSetBit (ic->rUsed, R1_IDX);
843 int stk = aop->aopu.aop_stk + aop->size;
844 bitVectUnSetBit (ic->rUsed, R0_IDX);
845 bitVectUnSetBit (ic->rUsed, R1_IDX);
847 getFreePtr (ic, &aop, FALSE);
849 if (options.stack10bit)
851 /* I'm not sure what to do here yet... */
854 "*** Warning: probably generating bad code for "
855 "10 bit stack mode.\n");
860 emitcode ("mov", "a,_bp");
861 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
862 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
866 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
871 emitcode ("pop", "acc");
872 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
875 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
878 freeAsmop (op, NULL, ic, TRUE);
881 emitcode ("pop", "ar0");
887 emitcode ("pop", "ar1");
894 /* all other cases just dealloc */
900 OP_SYMBOL (op)->aop = NULL;
901 /* if the symbol has a spill */
903 SPIL_LOC (op)->aop = NULL;
908 /*------------------------------------------------------------------*/
909 /* aopGet - for fetching value of the aop */
911 /* Set canClobberACC if you are aure it is OK to clobber the value */
912 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
913 /* just less efficient. */
914 /*------------------------------------------------------------------*/
926 /* offset is greater than
928 if (offset > (aop->size - 1) &&
929 aop->type != AOP_LIT)
932 /* depending on type */
938 /* if we need to increment it */
939 while (offset > aop->coff)
941 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
945 while (offset < aop->coff)
947 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
954 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
955 return (dname ? "acc" : "a");
957 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
958 rs = Safe_calloc (1, strlen (s) + 1);
965 if (aop->type == AOP_DPTR2)
970 emitcode ("xch", "a, ap");
976 while (offset > aop->coff)
978 emitcode ("inc", "dptr");
982 while (offset < aop->coff)
984 emitcode ("lcall", "__decdptr");
991 emitcode ("clr", "a");
992 emitcode ("movc", "a,@a+dptr");
996 emitcode ("movx", "a,@dptr");
999 if (aop->type == AOP_DPTR2)
1004 emitcode ("xch", "a, ap");
1008 return (dname ? "acc" : "a");
1012 sprintf (s, "#%s", aop->aopu.aop_immd);
1014 sprintf (s, "#(%s >> %d)",
1019 aop->aopu.aop_immd);
1020 rs = Safe_calloc (1, strlen (s) + 1);
1026 sprintf (s, "(%s + %d)",
1030 sprintf (s, "%s", aop->aopu.aop_dir);
1031 rs = Safe_calloc (1, strlen (s) + 1);
1037 return aop->aopu.aop_reg[offset]->dname;
1039 return aop->aopu.aop_reg[offset]->name;
1042 emitcode ("clr", "a");
1043 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1044 emitcode ("rlc", "a");
1045 return (dname ? "acc" : "a");
1048 if (!offset && dname)
1050 return aop->aopu.aop_str[offset];
1053 return aopLiteral (aop->aopu.aop_lit, offset);
1057 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1061 return aop->aopu.aop_str[offset];
1065 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1066 "aopget got unsupported aop->type");
1069 /*-----------------------------------------------------------------*/
1070 /* aopPut - puts a string for a aop */
1071 /*-----------------------------------------------------------------*/
1073 aopPut (asmop * aop, char *s, int offset)
1078 if (aop->size && offset > (aop->size - 1))
1080 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1081 "aopPut got offset > aop->size");
1085 /* will assign value to value */
1086 /* depending on where it is ofcourse */
1091 sprintf (d, "(%s + %d)",
1092 aop->aopu.aop_dir, offset);
1094 sprintf (d, "%s", aop->aopu.aop_dir);
1097 emitcode ("mov", "%s,%s", d, s);
1102 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1103 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1106 strcmp (s, "r0") == 0 ||
1107 strcmp (s, "r1") == 0 ||
1108 strcmp (s, "r2") == 0 ||
1109 strcmp (s, "r3") == 0 ||
1110 strcmp (s, "r4") == 0 ||
1111 strcmp (s, "r5") == 0 ||
1112 strcmp (s, "r6") == 0 ||
1113 strcmp (s, "r7") == 0)
1114 emitcode ("mov", "%s,%s",
1115 aop->aopu.aop_reg[offset]->dname, s);
1117 emitcode ("mov", "%s,%s",
1118 aop->aopu.aop_reg[offset]->name, s);
1125 if (aop->type == AOP_DPTR2)
1133 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1134 "aopPut writting to code space");
1138 while (offset > aop->coff)
1141 emitcode ("inc", "dptr");
1144 while (offset < aop->coff)
1147 emitcode ("lcall", "__decdptr");
1152 /* if not in accumulater */
1155 emitcode ("movx", "@dptr,a");
1157 if (aop->type == AOP_DPTR2)
1165 while (offset > aop->coff)
1168 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1170 while (offset < aop->coff)
1173 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1180 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1186 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1188 else if (strcmp (s, "r0") == 0 ||
1189 strcmp (s, "r1") == 0 ||
1190 strcmp (s, "r2") == 0 ||
1191 strcmp (s, "r3") == 0 ||
1192 strcmp (s, "r4") == 0 ||
1193 strcmp (s, "r5") == 0 ||
1194 strcmp (s, "r6") == 0 ||
1195 strcmp (s, "r7") == 0)
1198 sprintf (buffer, "a%s", s);
1199 emitcode ("mov", "@%s,%s",
1200 aop->aopu.aop_ptr->name, buffer);
1203 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1208 if (strcmp (s, "a") == 0)
1209 emitcode ("push", "acc");
1211 emitcode ("push", "%s", s);
1216 /* if bit variable */
1217 if (!aop->aopu.aop_dir)
1219 emitcode ("clr", "a");
1220 emitcode ("rlc", "a");
1225 emitcode ("clr", "%s", aop->aopu.aop_dir);
1227 emitcode ("setb", "%s", aop->aopu.aop_dir);
1228 else if (!strcmp (s, "c"))
1229 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1232 lbl = newiTempLabel (NULL);
1234 if (strcmp (s, "a"))
1238 emitcode ("clr", "c");
1239 emitcode ("jz", "%05d$", lbl->key + 100);
1240 emitcode ("cpl", "c");
1241 emitcode ("", "%05d$:", lbl->key + 100);
1242 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1249 if (strcmp (aop->aopu.aop_str[offset], s))
1250 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1255 if (!offset && (strcmp (s, "acc") == 0))
1258 if (strcmp (aop->aopu.aop_str[offset], s))
1259 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1263 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1264 "aopPut got unsupported aop->type");
1271 /*--------------------------------------------------------------------*/
1272 /* reAdjustPreg - points a register back to where it should (coff==0) */
1273 /*--------------------------------------------------------------------*/
1275 reAdjustPreg (asmop * aop)
1277 emitcode (";jwk","reAdjustPreg: %d", aop->coff);
1278 if ((aop->coff==0) || (aop->size <= 1)) {
1287 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1291 if (aop->type == AOP_DPTR2)
1298 emitcode ("lcall", "__decdptr");
1301 if (aop->type == AOP_DPTR2)
1311 #define AOP(op) op->aop
1312 #define AOP_TYPE(op) AOP(op)->type
1313 #define AOP_SIZE(op) AOP(op)->size
1314 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1315 AOP_TYPE(x) == AOP_R0))
1317 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1318 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1321 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1322 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1323 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1325 /* Workaround for DS80C390 bug: div ab may return bogus results
1326 * if A is accessed in instruction immediately before the div.
1328 * Will be fixed in B4 rev of processor, Dallas claims.
1331 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1332 if (!AOP_NEEDSACC(RIGHT)) \
1334 /* We can load A first, then B, since \
1335 * B (the RIGHT operand) won't clobber A, \
1336 * thus avoiding touching A right before the div. \
1338 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1339 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1341 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1345 /* Just stuff in a nop after loading A. */ \
1346 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1347 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1349 emitcode("nop", "; workaround for DS80C390 div bug."); \
1352 /*-----------------------------------------------------------------*/
1353 /* genNotFloat - generates not for float operations */
1354 /*-----------------------------------------------------------------*/
1356 genNotFloat (operand * op, operand * res)
1362 D (emitcode (";", "genNotFloat ");
1365 /* we will put 127 in the first byte of
1367 aopPut (AOP (res), "#127", 0);
1368 size = AOP_SIZE (op) - 1;
1371 _startLazyDPSEvaluation ();
1372 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1377 emitcode ("orl", "a,%s",
1379 offset++, FALSE, FALSE, FALSE));
1381 _endLazyDPSEvaluation ();
1382 tlbl = newiTempLabel (NULL);
1384 tlbl = newiTempLabel (NULL);
1385 aopPut (res->aop, one, 1);
1386 emitcode ("jz", "%05d$", (tlbl->key + 100));
1387 aopPut (res->aop, zero, 1);
1388 emitcode ("", "%05d$:", (tlbl->key + 100));
1390 size = res->aop->size - 2;
1392 /* put zeros in the rest */
1394 aopPut (res->aop, zero, offset++);
1397 /*-----------------------------------------------------------------*/
1398 /* opIsGptr: returns non-zero if the passed operand is */
1399 /* a generic pointer type. */
1400 /*-----------------------------------------------------------------*/
1402 opIsGptr (operand * op)
1404 sym_link *type = operandType (op);
1406 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1413 /*-----------------------------------------------------------------*/
1414 /* getDataSize - get the operand data size */
1415 /*-----------------------------------------------------------------*/
1417 getDataSize (operand * op)
1420 size = AOP_SIZE (op);
1421 if (size == GPTRSIZE)
1423 sym_link *type = operandType (op);
1424 if (IS_GENPTR (type))
1426 /* generic pointer; arithmetic operations
1427 * should ignore the high byte (pointer type).
1435 /*-----------------------------------------------------------------*/
1436 /* outAcc - output Acc */
1437 /*-----------------------------------------------------------------*/
1439 outAcc (operand * result)
1442 size = getDataSize (result);
1445 aopPut (AOP (result), "a", 0);
1448 /* unsigned or positive */
1451 aopPut (AOP (result), zero, offset++);
1456 /*-----------------------------------------------------------------*/
1457 /* outBitC - output a bit C */
1458 /*-----------------------------------------------------------------*/
1460 outBitC (operand * result)
1462 /* if the result is bit */
1463 if (AOP_TYPE (result) == AOP_CRY)
1465 aopPut (AOP (result), "c", 0);
1469 emitcode ("clr", "a");
1470 emitcode ("rlc", "a");
1475 /*-----------------------------------------------------------------*/
1476 /* toBoolean - emit code for orl a,operator(sizeop) */
1477 /*-----------------------------------------------------------------*/
1479 toBoolean (operand * oper)
1481 int size = AOP_SIZE (oper) - 1;
1484 /* The generic part of a generic pointer should
1485 * not participate in it's truth value.
1487 * i.e. 0x10000000 is zero.
1489 if (opIsGptr (oper))
1491 D (emitcode (";", "toBoolean: generic ptr special case.");
1496 _startLazyDPSEvaluation ();
1497 if (AOP_NEEDSACC (oper))
1499 emitcode ("push", "b");
1500 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1504 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1508 if (AOP_NEEDSACC (oper))
1510 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1514 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1517 _endLazyDPSEvaluation ();
1519 if (AOP_NEEDSACC (oper))
1521 emitcode ("mov", "a,b");
1522 emitcode ("pop", "b");
1527 /*-----------------------------------------------------------------*/
1528 /* genNot - generate code for ! operation */
1529 /*-----------------------------------------------------------------*/
1534 sym_link *optype = operandType (IC_LEFT (ic));
1536 D (emitcode (";", "genNot ");
1539 /* assign asmOps to operand & result */
1540 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1541 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1543 /* if in bit space then a special case */
1544 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1546 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1547 emitcode ("cpl", "c");
1548 outBitC (IC_RESULT (ic));
1552 /* if type float then do float */
1553 if (IS_FLOAT (optype))
1555 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1559 toBoolean (IC_LEFT (ic));
1561 tlbl = newiTempLabel (NULL);
1562 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1563 emitcode ("", "%05d$:", tlbl->key + 100);
1564 outBitC (IC_RESULT (ic));
1567 /* release the aops */
1568 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1569 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1573 /*-----------------------------------------------------------------*/
1574 /* genCpl - generate code for complement */
1575 /*-----------------------------------------------------------------*/
1582 D (emitcode (";", "genCpl ");
1586 /* assign asmOps to operand & result */
1587 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1588 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1590 /* if both are in bit space then
1592 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1593 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1596 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1597 emitcode ("cpl", "c");
1598 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1602 size = AOP_SIZE (IC_RESULT (ic));
1603 _startLazyDPSEvaluation ();
1606 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1608 emitcode ("cpl", "a");
1609 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1611 _endLazyDPSEvaluation ();
1615 /* release the aops */
1616 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1617 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1620 /*-----------------------------------------------------------------*/
1621 /* genUminusFloat - unary minus for floating points */
1622 /*-----------------------------------------------------------------*/
1624 genUminusFloat (operand * op, operand * result)
1626 int size, offset = 0;
1628 /* for this we just need to flip the
1629 first it then copy the rest in place */
1630 D (emitcode (";", "genUminusFloat");
1633 _startLazyDPSEvaluation ();
1634 size = AOP_SIZE (op) - 1;
1635 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1638 emitcode ("cpl", "acc.7");
1639 aopPut (AOP (result), "a", 3);
1643 aopPut (AOP (result),
1644 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1648 _endLazyDPSEvaluation ();
1651 /*-----------------------------------------------------------------*/
1652 /* genUminus - unary minus code generation */
1653 /*-----------------------------------------------------------------*/
1655 genUminus (iCode * ic)
1658 sym_link *optype, *rtype;
1660 D (emitcode (";", "genUminus ");
1665 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1666 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1668 /* if both in bit space then special
1670 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1671 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1674 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1675 emitcode ("cpl", "c");
1676 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1680 optype = operandType (IC_LEFT (ic));
1681 rtype = operandType (IC_RESULT (ic));
1683 /* if float then do float stuff */
1684 if (IS_FLOAT (optype))
1686 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1690 /* otherwise subtract from zero */
1691 size = AOP_SIZE (IC_LEFT (ic));
1693 _startLazyDPSEvaluation ();
1696 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1697 if (!strcmp (l, "a"))
1701 emitcode ("cpl", "a");
1702 emitcode ("addc", "a,#0");
1708 emitcode ("clr", "a");
1709 emitcode ("subb", "a,%s", l);
1711 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1713 _endLazyDPSEvaluation ();
1715 /* if any remaining bytes in the result */
1716 /* we just need to propagate the sign */
1717 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1719 emitcode ("rlc", "a");
1720 emitcode ("subb", "a,acc");
1722 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1726 /* release the aops */
1727 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1728 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1731 /*-----------------------------------------------------------------*/
1732 /* saveRegisters - will look for a call and save the registers */
1733 /*-----------------------------------------------------------------*/
1735 saveRegisters (iCode * lic)
1743 for (ic = lic; ic; ic = ic->next)
1744 if (ic->op == CALL || ic->op == PCALL)
1749 fprintf (stderr, "found parameter push with no function call\n");
1753 /* if the registers have been saved already then
1755 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1758 /* find the registers in use at this time
1759 and push them away to safety */
1760 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1764 if (options.useXstack)
1766 if (bitVectBitValue (rsave, R0_IDX))
1767 emitcode ("mov", "b,r0");
1768 emitcode ("mov", "r0,%s", spname);
1769 for (i = 0; i < ds390_nRegs; i++)
1771 if (bitVectBitValue (rsave, i))
1774 emitcode ("mov", "a,b");
1776 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1777 emitcode ("movx", "@r0,a");
1778 emitcode ("inc", "r0");
1781 emitcode ("mov", "%s,r0", spname);
1782 if (bitVectBitValue (rsave, R0_IDX))
1783 emitcode ("mov", "r0,b");
1786 for (i = 0; i < ds390_nRegs; i++)
1788 if (bitVectBitValue (rsave, i))
1789 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1792 detype = getSpec (operandType (IC_LEFT (ic)));
1794 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1795 IS_ISR (currFunc->etype) &&
1798 saverbank (SPEC_BANK (detype), ic, TRUE);
1801 /*-----------------------------------------------------------------*/
1802 /* unsaveRegisters - pop the pushed registers */
1803 /*-----------------------------------------------------------------*/
1805 unsaveRegisters (iCode * ic)
1809 /* find the registers in use at this time
1810 and push them away to safety */
1811 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1814 if (options.useXstack)
1816 emitcode ("mov", "r0,%s", spname);
1817 for (i = ds390_nRegs; i >= 0; i--)
1819 if (bitVectBitValue (rsave, i))
1821 emitcode ("dec", "r0");
1822 emitcode ("movx", "a,@r0");
1824 emitcode ("mov", "b,a");
1826 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1830 emitcode ("mov", "%s,r0", spname);
1831 if (bitVectBitValue (rsave, R0_IDX))
1832 emitcode ("mov", "r0,b");
1835 for (i = ds390_nRegs; i >= 0; i--)
1837 if (bitVectBitValue (rsave, i))
1838 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1844 /*-----------------------------------------------------------------*/
1846 /*-----------------------------------------------------------------*/
1848 pushSide (operand * oper, int size)
1851 _startLazyDPSEvaluation ();
1854 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1855 if (AOP_TYPE (oper) != AOP_REG &&
1856 AOP_TYPE (oper) != AOP_DIR &&
1859 emitcode ("mov", "a,%s", l);
1860 emitcode ("push", "acc");
1863 emitcode ("push", "%s", l);
1865 _endLazyDPSEvaluation ();
1868 /*-----------------------------------------------------------------*/
1869 /* assignResultValue - */
1870 /*-----------------------------------------------------------------*/
1872 assignResultValue (operand * oper)
1875 int size = AOP_SIZE (oper);
1877 _startLazyDPSEvaluation ();
1880 aopPut (AOP (oper), fReturn[offset], offset);
1883 _endLazyDPSEvaluation ();
1887 /*-----------------------------------------------------------------*/
1888 /* genXpush - pushes onto the external stack */
1889 /*-----------------------------------------------------------------*/
1891 genXpush (iCode * ic)
1893 asmop *aop = newAsmop (0);
1895 int size, offset = 0;
1897 D (emitcode (";", "genXpush ");
1900 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1901 r = getFreePtr (ic, &aop, FALSE);
1904 emitcode ("mov", "%s,_spx", r->name);
1906 size = AOP_SIZE (IC_LEFT (ic));
1907 _startLazyDPSEvaluation ();
1911 char *l = aopGet (AOP (IC_LEFT (ic)),
1912 offset++, FALSE, FALSE, TRUE);
1914 emitcode ("movx", "@%s,a", r->name);
1915 emitcode ("inc", "%s", r->name);
1918 _endLazyDPSEvaluation ();
1921 emitcode ("mov", "_spx,%s", r->name);
1923 freeAsmop (NULL, aop, ic, TRUE);
1924 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1927 /*-----------------------------------------------------------------*/
1928 /* genIpush - genrate code for pushing this gets a little complex */
1929 /*-----------------------------------------------------------------*/
1931 genIpush (iCode * ic)
1933 int size, offset = 0;
1936 D (emitcode (";", "genIpush ");
1939 /* if this is not a parm push : ie. it is spill push
1940 and spill push is always done on the local stack */
1944 /* and the item is spilt then do nothing */
1945 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1948 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1949 size = AOP_SIZE (IC_LEFT (ic));
1950 /* push it on the stack */
1951 _startLazyDPSEvaluation ();
1954 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1960 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1962 _endLazyDPSEvaluation ();
1966 /* this is a paramter push: in this case we call
1967 the routine to find the call and save those
1968 registers that need to be saved */
1971 /* if use external stack then call the external
1972 stack pushing routine */
1973 if (options.useXstack)
1979 /* then do the push */
1980 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1982 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1983 size = AOP_SIZE (IC_LEFT (ic));
1985 _startLazyDPSEvaluation ();
1988 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1989 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1990 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1993 emitcode ("mov", "a,%s", l);
1994 emitcode ("push", "acc");
1997 emitcode ("push", "%s ;jwk genIpush", l);
1999 _endLazyDPSEvaluation ();
2001 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2004 /*-----------------------------------------------------------------*/
2005 /* genIpop - recover the registers: can happen only for spilling */
2006 /*-----------------------------------------------------------------*/
2008 genIpop (iCode * ic)
2012 D (emitcode (";", "genIpop ");
2016 /* if the temp was not pushed then */
2017 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2020 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2021 size = AOP_SIZE (IC_LEFT (ic));
2022 offset = (size - 1);
2023 _startLazyDPSEvaluation ();
2026 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2027 FALSE, TRUE, TRUE));
2029 _endLazyDPSEvaluation ();
2031 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2034 /*-----------------------------------------------------------------*/
2035 /* unsaverbank - restores the resgister bank from stack */
2036 /*-----------------------------------------------------------------*/
2038 unsaverbank (int bank, iCode * ic, bool popPsw)
2046 if (options.useXstack)
2049 r = getFreePtr (ic, &aop, FALSE);
2052 emitcode ("mov", "%s,_spx", r->name);
2053 emitcode ("movx", "a,@%s", r->name);
2054 emitcode ("mov", "psw,a");
2055 emitcode ("dec", "%s", r->name);
2059 emitcode ("pop", "psw");
2062 for (i = (ds390_nRegs - 1); i >= 0; i--)
2064 if (options.useXstack)
2066 emitcode ("movx", "a,@%s", r->name);
2067 emitcode ("mov", "(%s+%d),a",
2068 regs390[i].base, 8 * bank + regs390[i].offset);
2069 emitcode ("dec", "%s", r->name);
2073 emitcode ("pop", "(%s+%d)",
2074 regs390[i].base, 8 * bank + regs390[i].offset);
2077 if (options.useXstack)
2080 emitcode ("mov", "_spx,%s", r->name);
2081 freeAsmop (NULL, aop, ic, TRUE);
2086 /*-----------------------------------------------------------------*/
2087 /* saverbank - saves an entire register bank on the stack */
2088 /*-----------------------------------------------------------------*/
2090 saverbank (int bank, iCode * ic, bool pushPsw)
2096 if (options.useXstack)
2100 r = getFreePtr (ic, &aop, FALSE);
2101 emitcode ("mov", "%s,_spx", r->name);
2105 for (i = 0; i < ds390_nRegs; i++)
2107 if (options.useXstack)
2109 emitcode ("inc", "%s", r->name);
2110 emitcode ("mov", "a,(%s+%d)",
2111 regs390[i].base, 8 * bank + regs390[i].offset);
2112 emitcode ("movx", "@%s,a", r->name);
2115 emitcode ("push", "(%s+%d)",
2116 regs390[i].base, 8 * bank + regs390[i].offset);
2121 if (options.useXstack)
2123 emitcode ("mov", "a,psw");
2124 emitcode ("movx", "@%s,a", r->name);
2125 emitcode ("inc", "%s", r->name);
2126 emitcode ("mov", "_spx,%s", r->name);
2127 freeAsmop (NULL, aop, ic, TRUE);
2131 emitcode ("push", "psw");
2133 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2139 /*-----------------------------------------------------------------*/
2140 /* genCall - generates a call statement */
2141 /*-----------------------------------------------------------------*/
2143 genCall (iCode * ic)
2147 D (emitcode (";", "genCall ");
2150 /* if caller saves & we have not saved then */
2154 /* if we are calling a function that is not using
2155 the same register bank then we need to save the
2156 destination registers on the stack */
2157 detype = getSpec (operandType (IC_LEFT (ic)));
2159 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2160 IS_ISR (currFunc->etype) &&
2163 saverbank (SPEC_BANK (detype), ic, TRUE);
2165 /* if send set is not empty the assign */
2170 for (sic = setFirstItem (_G.sendSet); sic;
2171 sic = setNextItem (_G.sendSet))
2173 int size, offset = 0;
2175 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2176 size = AOP_SIZE (IC_LEFT (sic));
2178 _startLazyDPSEvaluation ();
2181 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2182 FALSE, FALSE, TRUE);
2183 if (strcmp (l, fReturn[offset])) {
2186 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2192 _endLazyDPSEvaluation ();
2193 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2198 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2199 OP_SYMBOL (IC_LEFT (ic))->rname :
2200 OP_SYMBOL (IC_LEFT (ic))->name));
2202 /* if we need assign a result value */
2203 if ((IS_ITEMP (IC_RESULT (ic)) &&
2204 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2205 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2206 IS_TRUE_SYMOP (IC_RESULT (ic)))
2208 if (isOperandInFarSpace (IC_RESULT (ic))
2209 && getSize (operandType (IC_RESULT (ic))) <= 2)
2211 int size = getSize (operandType (IC_RESULT (ic)));
2213 /* Special case for 1 or 2 byte return in far space. */
2214 emitcode (";", "Kevin function call abuse #1");
2219 emitcode ("mov", "b,%s", fReturn[1]);
2222 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2223 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2227 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2229 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2234 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2237 assignResultValue (IC_RESULT (ic));
2239 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2243 /* adjust the stack for parameters if
2248 if (ic->parmBytes > 3)
2250 emitcode ("mov", "a,%s", spname);
2251 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2252 emitcode ("mov", "%s,a", spname);
2255 for (i = 0; i < ic->parmBytes; i++)
2256 emitcode ("dec", "%s", spname);
2260 /* if register bank was saved then pop them */
2262 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2264 /* if we hade saved some registers then unsave them */
2265 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2266 unsaveRegisters (ic);
2271 /*-----------------------------------------------------------------*/
2272 /* genPcall - generates a call by pointer statement */
2273 /*-----------------------------------------------------------------*/
2275 genPcall (iCode * ic)
2278 symbol *rlbl = newiTempLabel (NULL);
2280 D (emitcode (";", "genPcall ");
2284 /* if caller saves & we have not saved then */
2288 /* if we are calling a function that is not using
2289 the same register bank then we need to save the
2290 destination registers on the stack */
2291 detype = getSpec (operandType (IC_LEFT (ic)));
2293 IS_ISR (currFunc->etype) &&
2294 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2295 saverbank (SPEC_BANK (detype), ic, TRUE);
2298 /* push the return address on to the stack */
2299 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2300 emitcode ("push", "acc");
2301 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2302 emitcode ("push", "acc");
2304 if (options.model == MODEL_FLAT24)
2306 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2307 emitcode ("push", "acc");
2310 /* now push the calling address */
2311 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2313 pushSide (IC_LEFT (ic), FPTRSIZE);
2315 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2317 /* if send set is not empty the assign */
2322 for (sic = setFirstItem (_G.sendSet); sic;
2323 sic = setNextItem (_G.sendSet))
2325 int size, offset = 0;
2327 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2328 size = AOP_SIZE (IC_LEFT (sic));
2329 _startLazyDPSEvaluation ();
2332 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2333 FALSE, FALSE, TRUE);
2334 if (strcmp (l, fReturn[offset]))
2336 emitcode ("mov", "%s,%s",
2342 _endLazyDPSEvaluation ();
2343 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2348 emitcode ("ret", "");
2349 emitcode ("", "%05d$:", (rlbl->key + 100));
2352 /* if we need assign a result value */
2353 if ((IS_ITEMP (IC_RESULT (ic)) &&
2354 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2355 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2356 IS_TRUE_SYMOP (IC_RESULT (ic)))
2360 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2363 assignResultValue (IC_RESULT (ic));
2365 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2368 /* adjust the stack for parameters if
2373 if (ic->parmBytes > 3)
2375 emitcode ("mov", "a,%s", spname);
2376 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2377 emitcode ("mov", "%s,a", spname);
2380 for (i = 0; i < ic->parmBytes; i++)
2381 emitcode ("dec", "%s", spname);
2385 /* if register bank was saved then unsave them */
2387 (SPEC_BANK (currFunc->etype) !=
2388 SPEC_BANK (detype)))
2389 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2391 /* if we hade saved some registers then
2394 unsaveRegisters (ic);
2398 /*-----------------------------------------------------------------*/
2399 /* resultRemat - result is rematerializable */
2400 /*-----------------------------------------------------------------*/
2402 resultRemat (iCode * ic)
2404 if (SKIP_IC (ic) || ic->op == IFX)
2407 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2409 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2410 if (sym->remat && !POINTER_SET (ic))
2417 #if defined(__BORLANDC__) || defined(_MSC_VER)
2418 #define STRCASECMP stricmp
2420 #define STRCASECMP strcasecmp
2423 /*-----------------------------------------------------------------*/
2424 /* inExcludeList - return 1 if the string is in exclude Reg list */
2425 /*-----------------------------------------------------------------*/
2427 inExcludeList (char *s)
2431 if (options.excludeRegs[i] &&
2432 STRCASECMP (options.excludeRegs[i], "none") == 0)
2435 for (i = 0; options.excludeRegs[i]; i++)
2437 if (options.excludeRegs[i] &&
2438 STRCASECMP (s, options.excludeRegs[i]) == 0)
2444 /*-----------------------------------------------------------------*/
2445 /* genFunction - generated code for function entry */
2446 /*-----------------------------------------------------------------*/
2448 genFunction (iCode * ic)
2453 D (emitcode (";", "genFunction ");
2457 /* create the function header */
2458 emitcode (";", "-----------------------------------------");
2459 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2460 emitcode (";", "-----------------------------------------");
2462 emitcode ("", "%s:", sym->rname);
2463 fetype = getSpec (operandType (IC_LEFT (ic)));
2465 /* if critical function then turn interrupts off */
2466 if (SPEC_CRTCL (fetype))
2467 emitcode ("clr", "ea");
2469 /* here we need to generate the equates for the
2470 register bank if required */
2471 if (SPEC_BANK (fetype) != rbank)
2475 rbank = SPEC_BANK (fetype);
2476 for (i = 0; i < ds390_nRegs; i++)
2478 if (strcmp (regs390[i].base, "0") == 0)
2479 emitcode ("", "%s = 0x%02x",
2481 8 * rbank + regs390[i].offset);
2483 emitcode ("", "%s = %s + 0x%02x",
2486 8 * rbank + regs390[i].offset);
2490 /* if this is an interrupt service routine then
2491 save acc, b, dpl, dph */
2492 if (IS_ISR (sym->etype))
2495 if (!inExcludeList ("acc"))
2496 emitcode ("push", "acc");
2497 if (!inExcludeList ("b"))
2498 emitcode ("push", "b");
2499 if (!inExcludeList ("dpl"))
2500 emitcode ("push", "dpl");
2501 if (!inExcludeList ("dph"))
2502 emitcode ("push", "dph");
2503 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2505 emitcode ("push", "dpx");
2506 /* Make sure we're using standard DPTR */
2507 emitcode ("push", "dps");
2508 emitcode ("mov", "dps, #0x00");
2509 if (options.stack10bit)
2511 /* This ISR could conceivably use DPTR2. Better save it. */
2512 emitcode ("push", "dpl1");
2513 emitcode ("push", "dph1");
2514 emitcode ("push", "dpx1");
2515 emitcode ("push", "ap");
2518 /* if this isr has no bank i.e. is going to
2519 run with bank 0 , then we need to save more
2521 if (!SPEC_BANK (sym->etype))
2524 /* if this function does not call any other
2525 function then we can be economical and
2526 save only those registers that are used */
2531 /* if any registers used */
2534 /* save the registers used */
2535 for (i = 0; i < sym->regsUsed->size; i++)
2537 if (bitVectBitValue (sym->regsUsed, i) ||
2538 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2539 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2546 /* this function has a function call cannot
2547 determines register usage so we will have the
2549 saverbank (0, ic, FALSE);
2555 /* if callee-save to be used for this function
2556 then save the registers being used in this function */
2557 if (sym->calleeSave)
2561 /* if any registers used */
2564 /* save the registers used */
2565 for (i = 0; i < sym->regsUsed->size; i++)
2567 if (bitVectBitValue (sym->regsUsed, i) ||
2568 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2570 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2578 /* set the register bank to the desired value */
2579 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2581 emitcode ("push", "psw");
2582 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2585 if (IS_RENT (sym->etype) || options.stackAuto)
2588 if (options.useXstack)
2590 emitcode ("mov", "r0,%s", spname);
2591 emitcode ("mov", "a,_bp");
2592 emitcode ("movx", "@r0,a");
2593 emitcode ("inc", "%s", spname);
2597 /* set up the stack */
2598 emitcode ("push", "_bp"); /* save the callers stack */
2600 emitcode ("mov", "_bp,%s", spname);
2603 /* adjust the stack for the function */
2609 werror (W_STACK_OVERFLOW, sym->name);
2611 if (i > 3 && sym->recvSize < 4)
2614 emitcode ("mov", "a,sp");
2615 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2616 emitcode ("mov", "sp,a");
2621 emitcode ("inc", "sp");
2627 emitcode ("mov", "a,_spx");
2628 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2629 emitcode ("mov", "_spx,a");
2634 /*-----------------------------------------------------------------*/
2635 /* genEndFunction - generates epilogue for functions */
2636 /*-----------------------------------------------------------------*/
2638 genEndFunction (iCode * ic)
2640 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2642 D (emitcode (";", "genEndFunction ");
2645 if (IS_RENT (sym->etype) || options.stackAuto)
2647 emitcode ("mov", "%s,_bp", spname);
2650 /* if use external stack but some variables were
2651 added to the local stack then decrement the
2653 if (options.useXstack && sym->stack)
2655 emitcode ("mov", "a,sp");
2656 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2657 emitcode ("mov", "sp,a");
2661 if ((IS_RENT (sym->etype) || options.stackAuto))
2663 if (options.useXstack)
2665 emitcode ("mov", "r0,%s", spname);
2666 emitcode ("movx", "a,@r0");
2667 emitcode ("mov", "_bp,a");
2668 emitcode ("dec", "%s", spname);
2672 emitcode ("pop", "_bp");
2676 /* restore the register bank */
2677 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2678 emitcode ("pop", "psw");
2680 if (IS_ISR (sym->etype))
2683 /* now we need to restore the registers */
2684 /* if this isr has no bank i.e. is going to
2685 run with bank 0 , then we need to save more
2687 if (!SPEC_BANK (sym->etype))
2690 /* if this function does not call any other
2691 function then we can be economical and
2692 save only those registers that are used */
2697 /* if any registers used */
2700 /* save the registers used */
2701 for (i = sym->regsUsed->size; i >= 0; i--)
2703 if (bitVectBitValue (sym->regsUsed, i) ||
2704 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2705 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2712 /* this function has a function call cannot
2713 determines register usage so we will have the
2715 unsaverbank (0, ic, FALSE);
2719 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2721 if (options.stack10bit)
2723 emitcode ("pop", "ap");
2724 emitcode ("pop", "dpx1");
2725 emitcode ("pop", "dph1");
2726 emitcode ("pop", "dpl1");
2728 emitcode ("pop", "dps");
2729 emitcode ("pop", "dpx");
2731 if (!inExcludeList ("dph"))
2732 emitcode ("pop", "dph");
2733 if (!inExcludeList ("dpl"))
2734 emitcode ("pop", "dpl");
2735 if (!inExcludeList ("b"))
2736 emitcode ("pop", "b");
2737 if (!inExcludeList ("acc"))
2738 emitcode ("pop", "acc");
2740 if (SPEC_CRTCL (sym->etype))
2741 emitcode ("setb", "ea");
2743 /* if debug then send end of function */
2744 /* if (options.debug && currFunc) { */
2748 emitcode ("", "C$%s$%d$%d$%d ==.",
2749 FileBaseName (ic->filename), currFunc->lastLine,
2750 ic->level, ic->block);
2751 if (IS_STATIC (currFunc->etype))
2752 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2754 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2758 emitcode ("reti", "");
2762 if (SPEC_CRTCL (sym->etype))
2763 emitcode ("setb", "ea");
2765 if (sym->calleeSave)
2769 /* if any registers used */
2772 /* save the registers used */
2773 for (i = sym->regsUsed->size; i >= 0; i--)
2775 if (bitVectBitValue (sym->regsUsed, i) ||
2776 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2777 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2783 /* if debug then send end of function */
2787 emitcode ("", "C$%s$%d$%d$%d ==.",
2788 FileBaseName (ic->filename), currFunc->lastLine,
2789 ic->level, ic->block);
2790 if (IS_STATIC (currFunc->etype))
2791 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2793 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2797 emitcode ("ret", "");
2802 /*-----------------------------------------------------------------*/
2803 /* genRet - generate code for return statement */
2804 /*-----------------------------------------------------------------*/
2808 int size, offset = 0, pushed = 0;
2810 D (emitcode (";", "genRet ");
2813 /* if we have no return value then
2814 just generate the "ret" */
2818 /* we have something to return then
2819 move the return value into place */
2820 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2821 size = AOP_SIZE (IC_LEFT (ic));
2823 _startLazyDPSEvaluation ();
2827 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2829 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2830 FALSE, TRUE, FALSE);
2831 emitcode ("push", "%s", l);
2836 l = aopGet (AOP (IC_LEFT (ic)), offset,
2837 FALSE, FALSE, FALSE);
2838 if (strcmp (fReturn[offset], l))
2839 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2842 _endLazyDPSEvaluation ();
2849 if (strcmp (fReturn[pushed], "a"))
2850 emitcode ("pop", fReturn[pushed]);
2852 emitcode ("pop", "acc");
2855 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2858 /* generate a jump to the return label
2859 if the next is not the return statement */
2860 if (!(ic->next && ic->next->op == LABEL &&
2861 IC_LABEL (ic->next) == returnLabel))
2863 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2867 /*-----------------------------------------------------------------*/
2868 /* genLabel - generates a label */
2869 /*-----------------------------------------------------------------*/
2871 genLabel (iCode * ic)
2873 /* special case never generate */
2874 if (IC_LABEL (ic) == entryLabel)
2877 D (emitcode (";", "genLabel ");
2880 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2883 /*-----------------------------------------------------------------*/
2884 /* genGoto - generates a ljmp */
2885 /*-----------------------------------------------------------------*/
2887 genGoto (iCode * ic)
2889 D (emitcode (";", "genGoto ");
2891 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2894 /*-----------------------------------------------------------------*/
2895 /* findLabelBackwards: walks back through the iCode chain looking */
2896 /* for the given label. Returns number of iCode instructions */
2897 /* between that label and given ic. */
2898 /* Returns zero if label not found. */
2899 /*-----------------------------------------------------------------*/
2901 findLabelBackwards (iCode * ic, int key)
2910 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2912 /* printf("findLabelBackwards = %d\n", count); */
2920 /*-----------------------------------------------------------------*/
2921 /* genPlusIncr :- does addition with increment if possible */
2922 /*-----------------------------------------------------------------*/
2924 genPlusIncr (iCode * ic)
2926 unsigned int icount;
2927 unsigned int size = getDataSize (IC_RESULT (ic));
2929 /* will try to generate an increment */
2930 /* if the right side is not a literal
2932 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2935 /* if the literal value of the right hand side
2936 is greater than 4 then it is not worth it */
2937 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2940 /* if increment 16 bits in register */
2942 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2943 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2944 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2952 /* If the next instruction is a goto and the goto target
2953 * is <= 5 instructions previous to this, we can generate
2954 * jumps straight to that target.
2956 if (ic->next && ic->next->op == GOTO
2957 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2960 emitcode (";", "tail increment optimized (range %d)", labelRange);
2961 tlbl = IC_LABEL (ic->next);
2966 tlbl = newiTempLabel (NULL);
2969 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2970 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2971 IS_AOP_PREG (IC_RESULT (ic)))
2972 emitcode ("cjne", "%s,#0x00,%05d$"
2973 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2977 emitcode ("clr", "a");
2978 emitcode ("cjne", "a,%s,%05d$"
2979 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2983 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2986 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2987 IS_AOP_PREG (IC_RESULT (ic)))
2988 emitcode ("cjne", "%s,#0x00,%05d$"
2989 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2992 emitcode ("cjne", "a,%s,%05d$"
2993 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2996 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3000 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3001 IS_AOP_PREG (IC_RESULT (ic)))
3002 emitcode ("cjne", "%s,#0x00,%05d$"
3003 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3007 emitcode ("cjne", "a,%s,%05d$"
3008 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3011 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3016 emitcode ("", "%05d$:", tlbl->key + 100);
3021 /* if the sizes are greater than 1 then we cannot */
3022 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3023 AOP_SIZE (IC_LEFT (ic)) > 1)
3026 /* we can if the aops of the left & result match or
3027 if they are in registers and the registers are the
3030 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3031 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3032 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3037 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3038 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3039 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3044 _startLazyDPSEvaluation ();
3047 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3049 _endLazyDPSEvaluation ();
3058 /*-----------------------------------------------------------------*/
3059 /* outBitAcc - output a bit in acc */
3060 /*-----------------------------------------------------------------*/
3062 outBitAcc (operand * result)
3064 symbol *tlbl = newiTempLabel (NULL);
3065 /* if the result is a bit */
3066 if (AOP_TYPE (result) == AOP_CRY)
3068 aopPut (AOP (result), "a", 0);
3072 emitcode ("jz", "%05d$", tlbl->key + 100);
3073 emitcode ("mov", "a,%s", one);
3074 emitcode ("", "%05d$:", tlbl->key + 100);
3079 /*-----------------------------------------------------------------*/
3080 /* genPlusBits - generates code for addition of two bits */
3081 /*-----------------------------------------------------------------*/
3083 genPlusBits (iCode * ic)
3085 D (emitcode (";", "genPlusBits ");
3087 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3089 symbol *lbl = newiTempLabel (NULL);
3090 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3091 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3092 emitcode ("cpl", "c");
3093 emitcode ("", "%05d$:", (lbl->key + 100));
3094 outBitC (IC_RESULT (ic));
3098 emitcode ("clr", "a");
3099 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3100 emitcode ("rlc", "a");
3101 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3102 emitcode ("addc", "a,#0x00");
3103 outAcc (IC_RESULT (ic));
3108 adjustArithmeticResult (iCode * ic)
3110 if (opIsGptr (IC_RESULT (ic)) &&
3111 opIsGptr (IC_LEFT (ic)) &&
3112 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3114 aopPut (AOP (IC_RESULT (ic)),
3115 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3119 if (opIsGptr (IC_RESULT (ic)) &&
3120 opIsGptr (IC_RIGHT (ic)) &&
3121 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3123 aopPut (AOP (IC_RESULT (ic)),
3124 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3128 if (opIsGptr (IC_RESULT (ic)) &&
3129 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3130 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3131 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3132 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3135 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3136 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3140 #define AOP_OP_3(ic) \
3141 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3142 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3143 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3144 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3145 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3146 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3148 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3150 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3153 #define AOP_OP_3_NOFATAL(ic, rc) \
3154 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3155 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3156 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3157 isOperandInFarSpace(IC_RESULT(ic))) \
3159 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3164 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3165 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3167 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3168 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3170 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3172 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3176 #define AOP_OP_2(ic) \
3177 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3178 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3180 #define AOP_SET_LOCALS(ic) \
3181 left = IC_LEFT(ic); \
3182 right = IC_RIGHT(ic); \
3183 result = IC_RESULT(ic);
3185 /*-----------------------------------------------------------------*/
3186 /* genPlus - generates code for addition */
3187 /*-----------------------------------------------------------------*/
3189 genPlus (iCode * ic)
3191 int size, offset = 0;
3192 bool pushResult = FALSE;
3195 D (emitcode (";", "genPlus ");
3198 /* special cases :- */
3200 AOP_OP_3_NOFATAL (ic, pushResult);
3203 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3209 /* if literal, literal on the right or
3210 if left requires ACC or right is already
3212 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3213 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3214 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3216 operand *t = IC_RIGHT (ic);
3217 IC_RIGHT (ic) = IC_LEFT (ic);
3219 emitcode (";", "Swapped plus args.");
3222 /* if both left & right are in bit
3224 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3225 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3231 /* if left in bit space & right literal */
3232 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3233 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3235 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3236 /* if result in bit space */
3237 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3239 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3240 emitcode ("cpl", "c");
3241 outBitC (IC_RESULT (ic));
3245 size = getDataSize (IC_RESULT (ic));
3246 _startLazyDPSEvaluation ();
3249 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3250 emitcode ("addc", "a,#00");
3251 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3253 _endLazyDPSEvaluation ();
3258 /* if I can do an increment instead
3259 of add then GOOD for ME */
3260 if (genPlusIncr (ic) == TRUE)
3262 emitcode (";", "did genPlusIncr");
3267 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3269 _startLazyDPSEvaluation ();
3272 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3274 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3276 emitcode ("add", "a,%s",
3277 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3279 emitcode ("addc", "a,%s",
3280 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3284 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3286 emitcode ("add", "a,%s",
3287 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3289 emitcode ("addc", "a,%s",
3290 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3294 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3298 emitcode ("push", "acc");
3302 _endLazyDPSEvaluation ();
3306 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3308 size = getDataSize (IC_LEFT (ic));
3309 rSize = getDataSize (IC_RESULT (ic));
3311 /* If the pushed data is bigger than the result,
3312 * simply discard unused bytes. Icky, but works.
3314 * Should we throw a warning here? We're losing data...
3316 while (size > rSize)
3318 D (emitcode (";", "discarding unused result byte.");
3320 emitcode ("pop", "acc");
3326 emitcode ("clr", "a");
3327 /* Conversly, we haven't pushed enough here.
3328 * just zero-pad, and all is well.
3330 while (size < rSize)
3332 emitcode ("push", "acc");
3338 _startLazyDPSEvaluation ();
3341 emitcode ("pop", "acc");
3342 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3344 _endLazyDPSEvaluation ();
3347 adjustArithmeticResult (ic);
3350 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3351 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3352 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3355 /*-----------------------------------------------------------------*/
3356 /* genMinusDec :- does subtraction with deccrement if possible */
3357 /*-----------------------------------------------------------------*/
3359 genMinusDec (iCode * ic)
3361 unsigned int icount;
3362 unsigned int size = getDataSize (IC_RESULT (ic));
3364 /* will try to generate an increment */
3365 /* if the right side is not a literal
3367 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3370 /* if the literal value of the right hand side
3371 is greater than 4 then it is not worth it */
3372 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3375 /* if decrement 16 bits in register */
3376 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3377 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3378 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3386 /* If the next instruction is a goto and the goto target
3387 * is <= 5 instructions previous to this, we can generate
3388 * jumps straight to that target.
3390 if (ic->next && ic->next->op == GOTO
3391 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3394 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3395 tlbl = IC_LABEL (ic->next);
3400 tlbl = newiTempLabel (NULL);
3404 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3405 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3406 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3407 IS_AOP_PREG (IC_RESULT (ic)))
3408 emitcode ("cjne", "%s,#0xff,%05d$"
3409 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3413 emitcode ("mov", "a,#0xff");
3414 emitcode ("cjne", "a,%s,%05d$"
3415 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3418 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3421 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3422 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3423 IS_AOP_PREG (IC_RESULT (ic)))
3424 emitcode ("cjne", "%s,#0xff,%05d$"
3425 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3429 emitcode ("cjne", "a,%s,%05d$"
3430 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3433 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3437 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3438 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3439 IS_AOP_PREG (IC_RESULT (ic)))
3440 emitcode ("cjne", "%s,#0xff,%05d$"
3441 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3445 emitcode ("cjne", "a,%s,%05d$"
3446 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3449 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3453 emitcode ("", "%05d$:", tlbl->key + 100);
3458 /* if the sizes are greater than 1 then we cannot */
3459 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3460 AOP_SIZE (IC_LEFT (ic)) > 1)
3463 /* we can if the aops of the left & result match or
3464 if they are in registers and the registers are the
3467 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3468 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3469 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3472 _startLazyDPSEvaluation ();
3475 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3477 _endLazyDPSEvaluation ();
3485 /*-----------------------------------------------------------------*/
3486 /* addSign - complete with sign */
3487 /*-----------------------------------------------------------------*/
3489 addSign (operand * result, int offset, int sign)
3491 int size = (getDataSize (result) - offset);
3496 emitcode ("rlc", "a");
3497 emitcode ("subb", "a,acc");
3499 aopPut (AOP (result), "a", offset++);
3503 aopPut (AOP (result), zero, offset++);
3507 /*-----------------------------------------------------------------*/
3508 /* genMinusBits - generates code for subtraction of two bits */
3509 /*-----------------------------------------------------------------*/
3511 genMinusBits (iCode * ic)
3513 symbol *lbl = newiTempLabel (NULL);
3515 D (emitcode (";", "genMinusBits ");
3518 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3520 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3521 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3522 emitcode ("cpl", "c");
3523 emitcode ("", "%05d$:", (lbl->key + 100));
3524 outBitC (IC_RESULT (ic));
3528 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3529 emitcode ("subb", "a,acc");
3530 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3531 emitcode ("inc", "a");
3532 emitcode ("", "%05d$:", (lbl->key + 100));
3533 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3534 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3538 /*-----------------------------------------------------------------*/
3539 /* genMinus - generates code for subtraction */
3540 /*-----------------------------------------------------------------*/
3542 genMinus (iCode * ic)
3544 int size, offset = 0;
3546 unsigned long lit = 0L;
3547 bool pushResult = FALSE;
3549 D (emitcode (";", "genMinus ");
3552 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3553 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3554 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3555 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3561 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3563 /* special cases :- */
3564 /* if both left & right are in bit space */
3565 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3566 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3572 /* if I can do an decrement instead
3573 of subtract then GOOD for ME */
3574 if (genMinusDec (ic) == TRUE)
3579 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3581 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3587 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3592 /* if literal, add a,#-lit, else normal subb */
3593 _startLazyDPSEvaluation ();
3596 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3597 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3598 emitcode ("subb", "a,%s",
3599 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3602 /* first add without previous c */
3604 emitcode ("add", "a,#0x%02x",
3605 (unsigned int) (lit & 0x0FFL));
3607 emitcode ("addc", "a,#0x%02x",
3608 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3613 emitcode ("push", "acc");
3617 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3621 _endLazyDPSEvaluation ();
3625 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3627 size = getDataSize (IC_LEFT (ic));
3628 rSize = getDataSize (IC_RESULT (ic));
3630 /* If the pushed data is bigger than the result,
3631 * simply discard unused bytes. Icky, but works.
3633 * Should we throw a warning here? We're losing data...
3635 while (size > getDataSize (IC_RESULT (ic)))
3637 emitcode (";", "discarding unused result byte.");
3638 emitcode ("pop", "acc");
3644 emitcode ("clr", "a");
3645 /* Conversly, we haven't pushed enough here.
3646 * just zero-pad, and all is well.
3648 while (size < rSize)
3650 emitcode ("push", "acc");
3658 emitcode ("pop", "acc");
3659 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3663 adjustArithmeticResult (ic);
3666 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3667 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3668 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3672 /*-----------------------------------------------------------------*/
3673 /* genMultbits :- multiplication of bits */
3674 /*-----------------------------------------------------------------*/
3676 genMultbits (operand * left,
3680 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3681 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3686 /*-----------------------------------------------------------------*/
3687 /* genMultOneByte : 8*8=8/16 bit multiplication */
3688 /*-----------------------------------------------------------------*/
3690 genMultOneByte (operand * left,
3694 sym_link *opetype = operandType (result);
3696 int size=AOP_SIZE(result);
3698 emitcode (";",__FUNCTION__);
3699 if (size<1 || size>2) {
3700 // this should never happen
3701 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3702 AOP_SIZE(result), __FUNCTION__, lineno);
3706 /* (if two literals: the value is computed before) */
3707 /* if one literal, literal on the right */
3708 if (AOP_TYPE (left) == AOP_LIT)
3713 emitcode (";", "swapped left and right");
3716 if (SPEC_USIGN(opetype)
3717 // ignore the sign of left and right, what else can we do?
3718 || (SPEC_USIGN(operandType(left)) &&
3719 SPEC_USIGN(operandType(right)))) {
3720 // just an unsigned 8*8=8/16 multiply
3721 //emitcode (";","unsigned");
3722 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3723 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3724 emitcode ("mul", "ab");
3725 aopPut (AOP (result), "a", 0);
3727 aopPut (AOP (result), "b", 1);
3732 // we have to do a signed multiply
3734 emitcode (";", "signed");
3735 emitcode ("clr", "F0"); // reset sign flag
3736 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3737 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3739 lbl=newiTempLabel(NULL);
3740 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3741 // left side is negative, 8-bit two's complement, this fails for -128
3742 emitcode ("setb", "F0"); // set sign flag
3743 emitcode ("cpl", "a");
3744 emitcode ("inc", "a");
3746 emitcode ("", "%05d$:", lbl->key+100);
3747 emitcode ("xch", "a,b");
3750 if (AOP_TYPE(right)==AOP_LIT) {
3751 /* AND literal negative */
3752 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3753 // two's complement for literal<0
3754 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3755 emitcode ("cpl", "a");
3756 emitcode ("inc", "a");
3759 lbl=newiTempLabel(NULL);
3760 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3761 // right side is negative, 8-bit two's complement
3762 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3763 emitcode ("cpl", "a");
3764 emitcode ("inc", "a");
3765 emitcode ("", "%05d$:", lbl->key+100);
3767 emitcode ("mul", "ab");
3769 lbl=newiTempLabel(NULL);
3770 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3771 // only ONE op was negative, we have to do a 8/16-bit two's complement
3772 emitcode ("cpl", "a"); // lsb
3774 emitcode ("inc", "a");
3776 emitcode ("add" "a,#1");
3777 emitcode ("xch", "a,b");
3778 emitcode ("cpl", "a"); // msb
3779 emitcode ("addc", "a,#0");
3780 emitcode ("xch", "a,b");
3783 emitcode ("", "%05d$:", lbl->key+100);
3784 aopPut (AOP (result), "a", 0);
3786 aopPut (AOP (result), "b", 1);
3790 /*-----------------------------------------------------------------*/
3791 /* genMult - generates code for multiplication */
3792 /*-----------------------------------------------------------------*/
3794 genMult (iCode * ic)
3796 operand *left = IC_LEFT (ic);
3797 operand *right = IC_RIGHT (ic);
3798 operand *result = IC_RESULT (ic);
3800 D (emitcode (";", "genMult ");
3803 /* assign the amsops */
3806 /* special cases first */
3808 if (AOP_TYPE (left) == AOP_CRY &&
3809 AOP_TYPE (right) == AOP_CRY)
3811 genMultbits (left, right, result);
3815 /* if both are of size == 1 */
3816 if (AOP_SIZE (left) == 1 &&
3817 AOP_SIZE (right) == 1)
3819 genMultOneByte (left, right, result);
3823 /* should have been converted to function call */
3827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3829 freeAsmop (result, NULL, ic, TRUE);
3832 /*-----------------------------------------------------------------*/
3833 /* genDivbits :- division of bits */
3834 /*-----------------------------------------------------------------*/
3836 genDivbits (operand * left,
3843 /* the result must be bit */
3844 LOAD_AB_FOR_DIV (left, right, l);
3845 emitcode ("div", "ab");
3846 emitcode ("rrc", "a");
3847 aopPut (AOP (result), "c", 0);
3850 /*-----------------------------------------------------------------*/
3851 /* genDivOneByte : 8 bit division */
3852 /*-----------------------------------------------------------------*/
3854 genDivOneByte (operand * left,
3858 sym_link *opetype = operandType (result);
3863 size = AOP_SIZE (result) - 1;
3865 /* signed or unsigned */
3866 if (SPEC_USIGN (opetype))
3868 /* unsigned is easy */
3869 LOAD_AB_FOR_DIV (left, right, l);
3870 emitcode ("div", "ab");
3871 aopPut (AOP (result), "a", 0);
3873 aopPut (AOP (result), zero, offset++);
3877 /* signed is a little bit more difficult */
3879 /* save the signs of the operands */
3880 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3882 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3883 emitcode ("push", "acc"); /* save it on the stack */
3885 /* now sign adjust for both left & right */
3886 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3888 lbl = newiTempLabel (NULL);
3889 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3890 emitcode ("cpl", "a");
3891 emitcode ("inc", "a");
3892 emitcode ("", "%05d$:", (lbl->key + 100));
3893 emitcode ("mov", "b,a");
3895 /* sign adjust left side */
3896 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3899 lbl = newiTempLabel (NULL);
3900 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3901 emitcode ("cpl", "a");
3902 emitcode ("inc", "a");
3903 emitcode ("", "%05d$:", (lbl->key + 100));
3905 /* now the division */
3906 emitcode ("nop", "; workaround for DS80C390 div bug.");
3907 emitcode ("div", "ab");
3908 /* we are interested in the lower order
3910 emitcode ("mov", "b,a");
3911 lbl = newiTempLabel (NULL);
3912 emitcode ("pop", "acc");
3913 /* if there was an over flow we don't
3914 adjust the sign of the result */
3915 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3916 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3918 emitcode ("clr", "a");
3919 emitcode ("subb", "a,b");
3920 emitcode ("mov", "b,a");
3921 emitcode ("", "%05d$:", (lbl->key + 100));
3923 /* now we are done */
3924 aopPut (AOP (result), "b", 0);
3927 emitcode ("mov", "c,b.7");
3928 emitcode ("subb", "a,acc");
3931 aopPut (AOP (result), "a", offset++);
3935 /*-----------------------------------------------------------------*/
3936 /* genDiv - generates code for division */
3937 /*-----------------------------------------------------------------*/
3941 operand *left = IC_LEFT (ic);
3942 operand *right = IC_RIGHT (ic);
3943 operand *result = IC_RESULT (ic);
3945 D (emitcode (";", "genDiv ");
3948 /* assign the amsops */
3951 /* special cases first */
3953 if (AOP_TYPE (left) == AOP_CRY &&
3954 AOP_TYPE (right) == AOP_CRY)
3956 genDivbits (left, right, result);
3960 /* if both are of size == 1 */
3961 if (AOP_SIZE (left) == 1 &&
3962 AOP_SIZE (right) == 1)
3964 genDivOneByte (left, right, result);
3968 /* should have been converted to function call */
3971 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3972 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3973 freeAsmop (result, NULL, ic, TRUE);
3976 /*-----------------------------------------------------------------*/
3977 /* genModbits :- modulus of bits */
3978 /*-----------------------------------------------------------------*/
3980 genModbits (operand * left,
3987 /* the result must be bit */
3988 LOAD_AB_FOR_DIV (left, right, l);
3989 emitcode ("div", "ab");
3990 emitcode ("mov", "a,b");
3991 emitcode ("rrc", "a");
3992 aopPut (AOP (result), "c", 0);
3995 /*-----------------------------------------------------------------*/
3996 /* genModOneByte : 8 bit modulus */
3997 /*-----------------------------------------------------------------*/
3999 genModOneByte (operand * left,
4003 sym_link *opetype = operandType (result);
4007 /* signed or unsigned */
4008 if (SPEC_USIGN (opetype))
4010 /* unsigned is easy */
4011 LOAD_AB_FOR_DIV (left, right, l);
4012 emitcode ("div", "ab");
4013 aopPut (AOP (result), "b", 0);
4017 /* signed is a little bit more difficult */
4019 /* save the signs of the operands */
4020 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4023 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4024 emitcode ("push", "acc"); /* save it on the stack */
4026 /* now sign adjust for both left & right */
4027 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4030 lbl = newiTempLabel (NULL);
4031 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4032 emitcode ("cpl", "a");
4033 emitcode ("inc", "a");
4034 emitcode ("", "%05d$:", (lbl->key + 100));
4035 emitcode ("mov", "b,a");
4037 /* sign adjust left side */
4038 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4041 lbl = newiTempLabel (NULL);
4042 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4043 emitcode ("cpl", "a");
4044 emitcode ("inc", "a");
4045 emitcode ("", "%05d$:", (lbl->key + 100));
4047 /* now the multiplication */
4048 emitcode ("nop", "; workaround for DS80C390 div bug.");
4049 emitcode ("div", "ab");
4050 /* we are interested in the lower order
4052 lbl = newiTempLabel (NULL);
4053 emitcode ("pop", "acc");
4054 /* if there was an over flow we don't
4055 adjust the sign of the result */
4056 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4057 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4059 emitcode ("clr", "a");
4060 emitcode ("subb", "a,b");
4061 emitcode ("mov", "b,a");
4062 emitcode ("", "%05d$:", (lbl->key + 100));
4064 /* now we are done */
4065 aopPut (AOP (result), "b", 0);
4069 /*-----------------------------------------------------------------*/
4070 /* genMod - generates code for division */
4071 /*-----------------------------------------------------------------*/
4075 operand *left = IC_LEFT (ic);
4076 operand *right = IC_RIGHT (ic);
4077 operand *result = IC_RESULT (ic);
4079 D (emitcode (";", "genMod ");
4082 /* assign the amsops */
4085 /* special cases first */
4087 if (AOP_TYPE (left) == AOP_CRY &&
4088 AOP_TYPE (right) == AOP_CRY)
4090 genModbits (left, right, result);
4094 /* if both are of size == 1 */
4095 if (AOP_SIZE (left) == 1 &&
4096 AOP_SIZE (right) == 1)
4098 genModOneByte (left, right, result);
4102 /* should have been converted to function call */
4106 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4107 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4108 freeAsmop (result, NULL, ic, TRUE);
4111 /*-----------------------------------------------------------------*/
4112 /* genIfxJump :- will create a jump depending on the ifx */
4113 /*-----------------------------------------------------------------*/
4115 genIfxJump (iCode * ic, char *jval)
4118 symbol *tlbl = newiTempLabel (NULL);
4121 D (emitcode (";", "genIfxJump ");
4124 /* if true label then we jump if condition
4128 jlbl = IC_TRUE (ic);
4129 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4130 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4134 /* false label is present */
4135 jlbl = IC_FALSE (ic);
4136 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4137 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4139 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4140 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4142 emitcode (inst, "%05d$", tlbl->key + 100);
4143 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4144 emitcode ("", "%05d$:", tlbl->key + 100);
4146 /* mark the icode as generated */
4150 /*-----------------------------------------------------------------*/
4151 /* genCmp :- greater or less than comparison */
4152 /*-----------------------------------------------------------------*/
4154 genCmp (operand * left, operand * right,
4155 iCode * ic, iCode * ifx, int sign)
4157 int size, offset = 0;
4158 unsigned long lit = 0L;
4161 D (emitcode (";", "genCmp");
4164 result = IC_RESULT (ic);
4166 /* if left & right are bit variables */
4167 if (AOP_TYPE (left) == AOP_CRY &&
4168 AOP_TYPE (right) == AOP_CRY)
4170 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4171 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4175 /* subtract right from left if at the
4176 end the carry flag is set then we know that
4177 left is greater than right */
4178 size = max (AOP_SIZE (left), AOP_SIZE (right));
4180 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4181 if ((size == 1) && !sign &&
4182 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4184 symbol *lbl = newiTempLabel (NULL);
4185 emitcode ("cjne", "%s,%s,%05d$",
4186 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4187 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4189 emitcode ("", "%05d$:", lbl->key + 100);
4193 if (AOP_TYPE (right) == AOP_LIT)
4195 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4196 /* optimize if(x < 0) or if(x >= 0) */
4205 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4207 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4208 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4210 aopOp (result, ic, FALSE, FALSE);
4212 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4214 freeAsmop (result, NULL, ic, TRUE);
4215 genIfxJump (ifx, "acc.7");
4220 emitcode ("rlc", "a");
4222 goto release_freedLR;
4230 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4231 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4232 emitcode (";", "genCmp #2");
4233 if (sign && (size == 0))
4235 emitcode (";", "genCmp #3");
4236 emitcode ("xrl", "a,#0x80");
4237 if (AOP_TYPE (right) == AOP_LIT)
4239 unsigned long lit = (unsigned long)
4240 floatFromVal (AOP (right)->aopu.aop_lit);
4241 emitcode (";", "genCmp #3.1");
4242 emitcode ("subb", "a,#0x%02x",
4243 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4247 emitcode (";", "genCmp #3.2");
4248 if (AOP_NEEDSACC (right))
4250 emitcode ("push", "acc");
4252 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4253 FALSE, FALSE, FALSE));
4254 emitcode ("xrl", "b,#0x80");
4255 if (AOP_NEEDSACC (right))
4257 emitcode ("pop", "acc");
4259 emitcode ("subb", "a,b");
4266 emitcode (";", "genCmp #4");
4267 if (AOP_NEEDSACC (right))
4270 emitcode (";", "genCmp #4.1");
4271 emitcode ("xch", "a, b");
4272 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4273 emitcode ("xch", "a, b");
4278 emitcode (";", "genCmp #4.2");
4279 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4282 emitcode ("subb", "a,%s", s);
4289 /* Don't need the left & right operands any more; do need the result. */
4290 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4291 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4293 aopOp (result, ic, FALSE, FALSE);
4297 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4303 /* if the result is used in the next
4304 ifx conditional branch then generate
4305 code a little differently */
4308 genIfxJump (ifx, "c");
4314 /* leave the result in acc */
4316 freeAsmop (result, NULL, ic, TRUE);
4319 /*-----------------------------------------------------------------*/
4320 /* genCmpGt :- greater than comparison */
4321 /*-----------------------------------------------------------------*/
4323 genCmpGt (iCode * ic, iCode * ifx)
4325 operand *left, *right;
4326 sym_link *letype, *retype;
4329 D (emitcode (";", "genCmpGt ");
4332 left = IC_LEFT (ic);
4333 right = IC_RIGHT (ic);
4335 letype = getSpec (operandType (left));
4336 retype = getSpec (operandType (right));
4337 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4339 /* assign the left & right amsops */
4342 genCmp (right, left, ic, ifx, sign);
4345 /*-----------------------------------------------------------------*/
4346 /* genCmpLt - less than comparisons */
4347 /*-----------------------------------------------------------------*/
4349 genCmpLt (iCode * ic, iCode * ifx)
4351 operand *left, *right;
4352 sym_link *letype, *retype;
4355 D (emitcode (";", "genCmpLt ");
4358 left = IC_LEFT (ic);
4359 right = IC_RIGHT (ic);
4361 letype = getSpec (operandType (left));
4362 retype = getSpec (operandType (right));
4363 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4365 /* assign the left & right amsops */
4368 genCmp (left, right, ic, ifx, sign);
4371 /*-----------------------------------------------------------------*/
4372 /* gencjneshort - compare and jump if not equal */
4373 /*-----------------------------------------------------------------*/
4375 gencjneshort (operand * left, operand * right, symbol * lbl)
4377 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4379 unsigned long lit = 0L;
4381 D (emitcode (";", "gencjneshort");
4384 /* if the left side is a literal or
4385 if the right is in a pointer register and left
4387 if ((AOP_TYPE (left) == AOP_LIT) ||
4388 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4395 if (AOP_TYPE (right) == AOP_LIT)
4396 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4398 if (opIsGptr (left) || opIsGptr (right))
4400 /* We are comparing a generic pointer to something.
4401 * Exclude the generic type byte from the comparison.
4404 D (emitcode (";", "cjneshort: generic ptr special case.");
4409 /* if the right side is a literal then anything goes */
4410 if (AOP_TYPE (right) == AOP_LIT &&
4411 AOP_TYPE (left) != AOP_DIR)
4415 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4417 emitcode ("cjne", "a,%s,%05d$",
4418 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4424 /* if the right side is in a register or in direct space or
4425 if the left is a pointer register & right is not */
4426 else if (AOP_TYPE (right) == AOP_REG ||
4427 AOP_TYPE (right) == AOP_DIR ||
4428 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4429 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4433 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4434 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4435 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4436 emitcode ("jnz", "%05d$", lbl->key + 100);
4438 emitcode ("cjne", "a,%s,%05d$",
4439 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4446 /* right is a pointer reg need both a & b */
4449 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4450 if (strcmp (l, "b"))
4451 emitcode ("mov", "b,%s", l);
4452 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4453 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4459 /*-----------------------------------------------------------------*/
4460 /* gencjne - compare and jump if not equal */
4461 /*-----------------------------------------------------------------*/
4463 gencjne (operand * left, operand * right, symbol * lbl)
4465 symbol *tlbl = newiTempLabel (NULL);
4467 D (emitcode (";", "gencjne");
4470 gencjneshort (left, right, lbl);
4472 emitcode ("mov", "a,%s", one);
4473 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4474 emitcode ("", "%05d$:", lbl->key + 100);
4475 emitcode ("clr", "a");
4476 emitcode ("", "%05d$:", tlbl->key + 100);
4479 /*-----------------------------------------------------------------*/
4480 /* genCmpEq - generates code for equal to */
4481 /*-----------------------------------------------------------------*/
4483 genCmpEq (iCode * ic, iCode * ifx)
4485 operand *left, *right, *result;
4487 D (emitcode (";", "genCmpEq ");
4491 AOP_SET_LOCALS (ic);
4493 /* if literal, literal on the right or
4494 if the right is in a pointer register and left
4496 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4497 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4499 operand *t = IC_RIGHT (ic);
4500 IC_RIGHT (ic) = IC_LEFT (ic);
4504 if (ifx && /* !AOP_SIZE(result) */
4505 OP_SYMBOL (result) &&
4506 OP_SYMBOL (result)->regType == REG_CND)
4509 /* if they are both bit variables */
4510 if (AOP_TYPE (left) == AOP_CRY &&
4511 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4513 if (AOP_TYPE (right) == AOP_LIT)
4515 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4519 emitcode ("cpl", "c");
4523 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4527 emitcode ("clr", "c");
4529 /* AOP_TYPE(right) == AOP_CRY */
4533 symbol *lbl = newiTempLabel (NULL);
4534 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4535 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4536 emitcode ("cpl", "c");
4537 emitcode ("", "%05d$:", (lbl->key + 100));
4539 /* if true label then we jump if condition
4541 tlbl = newiTempLabel (NULL);
4544 emitcode ("jnc", "%05d$", tlbl->key + 100);
4545 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4549 emitcode ("jc", "%05d$", tlbl->key + 100);
4550 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4552 emitcode ("", "%05d$:", tlbl->key + 100);
4556 tlbl = newiTempLabel (NULL);
4557 gencjneshort (left, right, tlbl);
4560 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4561 emitcode ("", "%05d$:", tlbl->key + 100);
4565 symbol *lbl = newiTempLabel (NULL);
4566 emitcode ("sjmp", "%05d$", lbl->key + 100);
4567 emitcode ("", "%05d$:", tlbl->key + 100);
4568 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4569 emitcode ("", "%05d$:", lbl->key + 100);
4572 /* mark the icode as generated */
4575 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4576 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4580 /* if they are both bit variables */
4581 if (AOP_TYPE (left) == AOP_CRY &&
4582 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4584 if (AOP_TYPE (right) == AOP_LIT)
4586 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4589 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4590 emitcode ("cpl", "c");
4594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4598 emitcode ("clr", "c");
4600 /* AOP_TYPE(right) == AOP_CRY */
4604 symbol *lbl = newiTempLabel (NULL);
4605 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4606 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4607 emitcode ("cpl", "c");
4608 emitcode ("", "%05d$:", (lbl->key + 100));
4611 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 aopOp (result, ic, TRUE, FALSE);
4617 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4624 genIfxJump (ifx, "c");
4627 /* if the result is used in an arithmetic operation
4628 then put the result in place */
4633 gencjne (left, right, newiTempLabel (NULL));
4635 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4638 aopOp (result, ic, TRUE, FALSE);
4640 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4642 aopPut (AOP (result), "a", 0);
4647 genIfxJump (ifx, "a");
4650 /* if the result is used in an arithmetic operation
4651 then put the result in place */
4652 if (AOP_TYPE (result) != AOP_CRY)
4654 /* leave the result in acc */
4658 freeAsmop (result, NULL, ic, TRUE);
4661 /*-----------------------------------------------------------------*/
4662 /* ifxForOp - returns the icode containing the ifx for operand */
4663 /*-----------------------------------------------------------------*/
4665 ifxForOp (operand * op, iCode * ic)
4667 /* if true symbol then needs to be assigned */
4668 if (IS_TRUE_SYMOP (op))
4671 /* if this has register type condition and
4672 the next instruction is ifx with the same operand
4673 and live to of the operand is upto the ifx only then */
4675 ic->next->op == IFX &&
4676 IC_COND (ic->next)->key == op->key &&
4677 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4682 /*-----------------------------------------------------------------*/
4683 /* genAndOp - for && operation */
4684 /*-----------------------------------------------------------------*/
4686 genAndOp (iCode * ic)
4688 operand *left, *right, *result;
4691 D (emitcode (";", "genAndOp ");
4694 /* note here that && operations that are in an
4695 if statement are taken away by backPatchLabels
4696 only those used in arthmetic operations remain */
4698 AOP_SET_LOCALS (ic);
4700 /* if both are bit variables */
4701 if (AOP_TYPE (left) == AOP_CRY &&
4702 AOP_TYPE (right) == AOP_CRY)
4704 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4705 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4710 tlbl = newiTempLabel (NULL);
4712 emitcode ("jz", "%05d$", tlbl->key + 100);
4714 emitcode ("", "%05d$:", tlbl->key + 100);
4718 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4719 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4720 freeAsmop (result, NULL, ic, TRUE);
4724 /*-----------------------------------------------------------------*/
4725 /* genOrOp - for || operation */
4726 /*-----------------------------------------------------------------*/
4728 genOrOp (iCode * ic)
4730 operand *left, *right, *result;
4733 D (emitcode (";", "genOrOp ");
4736 /* note here that || operations that are in an
4737 if statement are taken away by backPatchLabels
4738 only those used in arthmetic operations remain */
4740 AOP_SET_LOCALS (ic);
4742 /* if both are bit variables */
4743 if (AOP_TYPE (left) == AOP_CRY &&
4744 AOP_TYPE (right) == AOP_CRY)
4746 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4747 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4752 tlbl = newiTempLabel (NULL);
4754 emitcode ("jnz", "%05d$", tlbl->key + 100);
4756 emitcode ("", "%05d$:", tlbl->key + 100);
4760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4761 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4762 freeAsmop (result, NULL, ic, TRUE);
4765 /*-----------------------------------------------------------------*/
4766 /* isLiteralBit - test if lit == 2^n */
4767 /*-----------------------------------------------------------------*/
4769 isLiteralBit (unsigned long lit)
4771 unsigned long pw[32] =
4772 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4773 0x100L, 0x200L, 0x400L, 0x800L,
4774 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4775 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4776 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4777 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4778 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4781 for (idx = 0; idx < 32; idx++)
4787 /*-----------------------------------------------------------------*/
4788 /* continueIfTrue - */
4789 /*-----------------------------------------------------------------*/
4791 continueIfTrue (iCode * ic)
4794 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4798 /*-----------------------------------------------------------------*/
4800 /*-----------------------------------------------------------------*/
4802 jumpIfTrue (iCode * ic)
4805 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4809 /*-----------------------------------------------------------------*/
4810 /* jmpTrueOrFalse - */
4811 /*-----------------------------------------------------------------*/
4813 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4815 // ugly but optimized by peephole
4818 symbol *nlbl = newiTempLabel (NULL);
4819 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4820 emitcode ("", "%05d$:", tlbl->key + 100);
4821 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4822 emitcode ("", "%05d$:", nlbl->key + 100);
4826 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4827 emitcode ("", "%05d$:", tlbl->key + 100);
4832 /*-----------------------------------------------------------------*/
4833 /* genAnd - code for and */
4834 /*-----------------------------------------------------------------*/
4836 genAnd (iCode * ic, iCode * ifx)
4838 operand *left, *right, *result;
4839 int size, offset = 0;
4840 unsigned long lit = 0L;
4844 D (emitcode (";", "genAnd ");
4848 AOP_SET_LOCALS (ic);
4851 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4853 AOP_TYPE (left), AOP_TYPE (right));
4854 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4856 AOP_SIZE (left), AOP_SIZE (right));
4859 /* if left is a literal & right is not then exchange them */
4860 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4861 AOP_NEEDSACC (left))
4863 operand *tmp = right;
4868 /* if result = right then exchange them */
4869 if (sameRegs (AOP (result), AOP (right)))
4871 operand *tmp = right;
4876 /* if right is bit then exchange them */
4877 if (AOP_TYPE (right) == AOP_CRY &&
4878 AOP_TYPE (left) != AOP_CRY)
4880 operand *tmp = right;
4884 if (AOP_TYPE (right) == AOP_LIT)
4885 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4887 size = AOP_SIZE (result);
4890 // result = bit & yy;
4891 if (AOP_TYPE (left) == AOP_CRY)
4893 // c = bit & literal;
4894 if (AOP_TYPE (right) == AOP_LIT)
4898 if (size && sameRegs (AOP (result), AOP (left)))
4901 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4906 if (size && (AOP_TYPE (result) == AOP_CRY))
4908 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4911 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4916 emitcode ("clr", "c");
4921 if (AOP_TYPE (right) == AOP_CRY)
4924 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4925 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4930 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4932 emitcode ("rrc", "a");
4933 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4941 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4942 genIfxJump (ifx, "c");
4946 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4947 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4948 if ((AOP_TYPE (right) == AOP_LIT) &&
4949 (AOP_TYPE (result) == AOP_CRY) &&
4950 (AOP_TYPE (left) != AOP_CRY))
4952 int posbit = isLiteralBit (lit);
4957 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4960 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4966 sprintf (buffer, "acc.%d", posbit & 0x07);
4967 genIfxJump (ifx, buffer);
4974 symbol *tlbl = newiTempLabel (NULL);
4975 int sizel = AOP_SIZE (left);
4977 emitcode ("setb", "c");
4980 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4982 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4984 if ((posbit = isLiteralBit (bytelit)) != 0)
4985 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4988 if (bytelit != 0x0FFL)
4989 emitcode ("anl", "a,%s",
4990 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4991 emitcode ("jnz", "%05d$", tlbl->key + 100);
4996 // bit = left & literal
4999 emitcode ("clr", "c");
5000 emitcode ("", "%05d$:", tlbl->key + 100);
5002 // if(left & literal)
5006 jmpTrueOrFalse (ifx, tlbl);
5014 /* if left is same as result */
5015 if (sameRegs (AOP (result), AOP (left)))
5017 for (; size--; offset++)
5019 if (AOP_TYPE (right) == AOP_LIT)
5021 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5023 else if (bytelit == 0)
5024 aopPut (AOP (result), zero, offset);
5025 else if (IS_AOP_PREG (result))
5027 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5028 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5029 aopPut (AOP (result), "a", offset);
5032 emitcode ("anl", "%s,%s",
5033 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5034 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5038 if (AOP_TYPE (left) == AOP_ACC)
5039 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5042 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5043 if (IS_AOP_PREG (result))
5045 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5046 aopPut (AOP (result), "a", offset);
5050 emitcode ("anl", "%s,a",
5051 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5058 // left & result in different registers
5059 if (AOP_TYPE (result) == AOP_CRY)
5062 // if(size), result in bit
5063 // if(!size && ifx), conditional oper: if(left & right)
5064 symbol *tlbl = newiTempLabel (NULL);
5065 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5067 emitcode ("setb", "c");
5070 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5071 emitcode ("anl", "a,%s",
5072 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5073 emitcode ("jnz", "%05d$", tlbl->key + 100);
5079 emitcode ("", "%05d$:", tlbl->key + 100);
5083 jmpTrueOrFalse (ifx, tlbl);
5087 for (; (size--); offset++)
5090 // result = left & right
5091 if (AOP_TYPE (right) == AOP_LIT)
5093 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5095 aopPut (AOP (result),
5096 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5100 else if (bytelit == 0)
5102 aopPut (AOP (result), zero, offset);
5105 D (emitcode (";", "better literal AND.");
5107 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5108 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5109 FALSE, FALSE, FALSE));
5114 // faster than result <- left, anl result,right
5115 // and better if result is SFR
5116 if (AOP_TYPE (left) == AOP_ACC)
5118 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5119 FALSE, FALSE, FALSE));
5123 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5124 emitcode ("anl", "a,%s",
5125 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5128 aopPut (AOP (result), "a", offset);
5134 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 freeAsmop (result, NULL, ic, TRUE);
5139 /*-----------------------------------------------------------------*/
5140 /* genOr - code for or */
5141 /*-----------------------------------------------------------------*/
5143 genOr (iCode * ic, iCode * ifx)
5145 operand *left, *right, *result;
5146 int size, offset = 0;
5147 unsigned long lit = 0L;
5149 D (emitcode (";", "genOr ");
5153 AOP_SET_LOCALS (ic);
5156 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5158 AOP_TYPE (left), AOP_TYPE (right));
5159 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5161 AOP_SIZE (left), AOP_SIZE (right));
5164 /* if left is a literal & right is not then exchange them */
5165 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5166 AOP_NEEDSACC (left))
5168 operand *tmp = right;
5173 /* if result = right then exchange them */
5174 if (sameRegs (AOP (result), AOP (right)))
5176 operand *tmp = right;
5181 /* if right is bit then exchange them */
5182 if (AOP_TYPE (right) == AOP_CRY &&
5183 AOP_TYPE (left) != AOP_CRY)
5185 operand *tmp = right;
5189 if (AOP_TYPE (right) == AOP_LIT)
5190 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5192 size = AOP_SIZE (result);
5196 if (AOP_TYPE (left) == AOP_CRY)
5198 if (AOP_TYPE (right) == AOP_LIT)
5200 // c = bit & literal;
5203 // lit != 0 => result = 1
5204 if (AOP_TYPE (result) == AOP_CRY)
5207 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5209 continueIfTrue (ifx);
5212 emitcode ("setb", "c");
5216 // lit == 0 => result = left
5217 if (size && sameRegs (AOP (result), AOP (left)))
5219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5224 if (AOP_TYPE (right) == AOP_CRY)
5227 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5228 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5233 symbol *tlbl = newiTempLabel (NULL);
5234 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5235 emitcode ("setb", "c");
5236 emitcode ("jb", "%s,%05d$",
5237 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5239 emitcode ("jnz", "%05d$", tlbl->key + 100);
5240 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5242 jmpTrueOrFalse (ifx, tlbl);
5248 emitcode ("", "%05d$:", tlbl->key + 100);
5257 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5258 genIfxJump (ifx, "c");
5262 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5263 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5264 if ((AOP_TYPE (right) == AOP_LIT) &&
5265 (AOP_TYPE (result) == AOP_CRY) &&
5266 (AOP_TYPE (left) != AOP_CRY))
5272 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5274 continueIfTrue (ifx);
5279 // lit = 0, result = boolean(left)
5281 emitcode ("setb", "c");
5285 symbol *tlbl = newiTempLabel (NULL);
5286 emitcode ("jnz", "%05d$", tlbl->key + 100);
5288 emitcode ("", "%05d$:", tlbl->key + 100);
5292 genIfxJump (ifx, "a");
5300 /* if left is same as result */
5301 if (sameRegs (AOP (result), AOP (left)))
5303 for (; size--; offset++)
5305 if (AOP_TYPE (right) == AOP_LIT)
5307 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5313 if (IS_AOP_PREG (left))
5315 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5316 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5317 aopPut (AOP (result), "a", offset);
5321 emitcode ("orl", "%s,%s",
5322 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5323 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5329 if (AOP_TYPE (left) == AOP_ACC)
5331 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5335 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5336 if (IS_AOP_PREG (left))
5338 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5339 aopPut (AOP (result), "a", offset);
5343 emitcode ("orl", "%s,a",
5344 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5352 // left & result in different registers
5353 if (AOP_TYPE (result) == AOP_CRY)
5356 // if(size), result in bit
5357 // if(!size && ifx), conditional oper: if(left | right)
5358 symbol *tlbl = newiTempLabel (NULL);
5359 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5361 emitcode ("setb", "c");
5364 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5365 emitcode ("orl", "a,%s",
5366 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5367 emitcode ("jnz", "%05d$", tlbl->key + 100);
5373 emitcode ("", "%05d$:", tlbl->key + 100);
5377 jmpTrueOrFalse (ifx, tlbl);
5381 for (; (size--); offset++)
5384 // result = left & right
5385 if (AOP_TYPE (right) == AOP_LIT)
5387 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5389 aopPut (AOP (result),
5390 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5394 D (emitcode (";", "better literal OR.");
5396 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5397 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5398 FALSE, FALSE, FALSE));
5403 // faster than result <- left, anl result,right
5404 // and better if result is SFR
5405 if (AOP_TYPE (left) == AOP_ACC)
5407 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5408 FALSE, FALSE, FALSE));
5412 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5413 emitcode ("orl", "a,%s",
5414 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5417 aopPut (AOP (result), "a", offset);
5423 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5424 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5425 freeAsmop (result, NULL, ic, TRUE);
5428 /*-----------------------------------------------------------------*/
5429 /* genXor - code for xclusive or */
5430 /*-----------------------------------------------------------------*/
5432 genXor (iCode * ic, iCode * ifx)
5434 operand *left, *right, *result;
5435 int size, offset = 0;
5436 unsigned long lit = 0L;
5438 D (emitcode (";", "genXor ");
5442 AOP_SET_LOCALS (ic);
5445 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5447 AOP_TYPE (left), AOP_TYPE (right));
5448 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5450 AOP_SIZE (left), AOP_SIZE (right));
5453 /* if left is a literal & right is not ||
5454 if left needs acc & right does not */
5455 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5456 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5458 operand *tmp = right;
5463 /* if result = right then exchange them */
5464 if (sameRegs (AOP (result), AOP (right)))
5466 operand *tmp = right;
5471 /* if right is bit then exchange them */
5472 if (AOP_TYPE (right) == AOP_CRY &&
5473 AOP_TYPE (left) != AOP_CRY)
5475 operand *tmp = right;
5479 if (AOP_TYPE (right) == AOP_LIT)
5480 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5482 size = AOP_SIZE (result);
5486 if (AOP_TYPE (left) == AOP_CRY)
5488 if (AOP_TYPE (right) == AOP_LIT)
5490 // c = bit & literal;
5493 // lit>>1 != 0 => result = 1
5494 if (AOP_TYPE (result) == AOP_CRY)
5497 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5499 continueIfTrue (ifx);
5502 emitcode ("setb", "c");
5509 // lit == 0, result = left
5510 if (size && sameRegs (AOP (result), AOP (left)))
5512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5516 // lit == 1, result = not(left)
5517 if (size && sameRegs (AOP (result), AOP (left)))
5519 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5524 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5525 emitcode ("cpl", "c");
5534 symbol *tlbl = newiTempLabel (NULL);
5535 if (AOP_TYPE (right) == AOP_CRY)
5538 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5542 int sizer = AOP_SIZE (right);
5544 // if val>>1 != 0, result = 1
5545 emitcode ("setb", "c");
5548 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5550 // test the msb of the lsb
5551 emitcode ("anl", "a,#0xfe");
5552 emitcode ("jnz", "%05d$", tlbl->key + 100);
5556 emitcode ("rrc", "a");
5558 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5559 emitcode ("cpl", "c");
5560 emitcode ("", "%05d$:", (tlbl->key + 100));
5567 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5568 genIfxJump (ifx, "c");
5572 if (sameRegs (AOP (result), AOP (left)))
5574 /* if left is same as result */
5575 for (; size--; offset++)
5577 if (AOP_TYPE (right) == AOP_LIT)
5579 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5581 else if (IS_AOP_PREG (left))
5583 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5584 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5585 aopPut (AOP (result), "a", offset);
5588 emitcode ("xrl", "%s,%s",
5589 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5590 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5594 if (AOP_TYPE (left) == AOP_ACC)
5595 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5598 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5599 if (IS_AOP_PREG (left))
5601 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5602 aopPut (AOP (result), "a", offset);
5605 emitcode ("xrl", "%s,a",
5606 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5613 // left & result in different registers
5614 if (AOP_TYPE (result) == AOP_CRY)
5617 // if(size), result in bit
5618 // if(!size && ifx), conditional oper: if(left ^ right)
5619 symbol *tlbl = newiTempLabel (NULL);
5620 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5622 emitcode ("setb", "c");
5625 if ((AOP_TYPE (right) == AOP_LIT) &&
5626 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5628 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5632 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5633 emitcode ("xrl", "a,%s",
5634 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5636 emitcode ("jnz", "%05d$", tlbl->key + 100);
5642 emitcode ("", "%05d$:", tlbl->key + 100);
5646 jmpTrueOrFalse (ifx, tlbl);
5649 for (; (size--); offset++)
5652 // result = left & right
5653 if (AOP_TYPE (right) == AOP_LIT)
5655 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5657 aopPut (AOP (result),
5658 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5662 D (emitcode (";", "better literal XOR.");
5664 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5665 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5666 FALSE, FALSE, FALSE));
5670 // faster than result <- left, anl result,right
5671 // and better if result is SFR
5672 if (AOP_TYPE (left) == AOP_ACC)
5674 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5675 FALSE, FALSE, FALSE));
5679 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5680 emitcode ("xrl", "a,%s",
5681 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5684 aopPut (AOP (result), "a", offset);
5689 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5690 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5691 freeAsmop (result, NULL, ic, TRUE);
5694 /*-----------------------------------------------------------------*/
5695 /* genInline - write the inline code out */
5696 /*-----------------------------------------------------------------*/
5698 genInline (iCode * ic)
5700 char buffer[MAX_INLINEASM];
5704 D (emitcode (";", "genInline ");
5707 _G.inLine += (!options.asmpeep);
5708 strcpy (buffer, IC_INLINE (ic));
5710 /* emit each line as a code */
5735 /* emitcode("",buffer); */
5736 _G.inLine -= (!options.asmpeep);
5739 /*-----------------------------------------------------------------*/
5740 /* genRRC - rotate right with carry */
5741 /*-----------------------------------------------------------------*/
5745 operand *left, *result;
5746 int size, offset = 0;
5749 D (emitcode (";", "genRRC ");
5752 /* rotate right with carry */
5753 left = IC_LEFT (ic);
5754 result = IC_RESULT (ic);
5755 aopOp (left, ic, FALSE, FALSE);
5756 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5758 /* move it to the result */
5759 size = AOP_SIZE (result);
5763 _startLazyDPSEvaluation ();
5766 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5768 emitcode ("rrc", "a");
5769 if (AOP_SIZE (result) > 1)
5770 aopPut (AOP (result), "a", offset--);
5772 _endLazyDPSEvaluation ();
5774 /* now we need to put the carry into the
5775 highest order byte of the result */
5776 if (AOP_SIZE (result) > 1)
5778 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5781 emitcode ("mov", "acc.7,c");
5782 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5783 freeAsmop (left, NULL, ic, TRUE);
5784 freeAsmop (result, NULL, ic, TRUE);
5787 /*-----------------------------------------------------------------*/
5788 /* genRLC - generate code for rotate left with carry */
5789 /*-----------------------------------------------------------------*/
5793 operand *left, *result;
5794 int size, offset = 0;
5797 D (emitcode (";", "genRLC ");
5800 /* rotate right with carry */
5801 left = IC_LEFT (ic);
5802 result = IC_RESULT (ic);
5803 aopOp (left, ic, FALSE, FALSE);
5804 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5806 /* move it to the result */
5807 size = AOP_SIZE (result);
5811 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5813 emitcode ("add", "a,acc");
5814 if (AOP_SIZE (result) > 1)
5816 aopPut (AOP (result), "a", offset++);
5819 _startLazyDPSEvaluation ();
5822 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5824 emitcode ("rlc", "a");
5825 if (AOP_SIZE (result) > 1)
5826 aopPut (AOP (result), "a", offset++);
5828 _endLazyDPSEvaluation ();
5830 /* now we need to put the carry into the
5831 highest order byte of the result */
5832 if (AOP_SIZE (result) > 1)
5834 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5837 emitcode ("mov", "acc.0,c");
5838 aopPut (AOP (result), "a", 0);
5839 freeAsmop (left, NULL, ic, TRUE);
5840 freeAsmop (result, NULL, ic, TRUE);
5843 /*-----------------------------------------------------------------*/
5844 /* genGetHbit - generates code get highest order bit */
5845 /*-----------------------------------------------------------------*/
5847 genGetHbit (iCode * ic)
5849 operand *left, *result;
5850 left = IC_LEFT (ic);
5851 result = IC_RESULT (ic);
5852 aopOp (left, ic, FALSE, FALSE);
5853 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5855 D (emitcode (";", "genGetHbit ");
5858 /* get the highest order byte into a */
5859 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5860 if (AOP_TYPE (result) == AOP_CRY)
5862 emitcode ("rlc", "a");
5867 emitcode ("rl", "a");
5868 emitcode ("anl", "a,#0x01");
5873 freeAsmop (left, NULL, ic, TRUE);
5874 freeAsmop (result, NULL, ic, TRUE);
5877 /*-----------------------------------------------------------------*/
5878 /* AccRol - rotate left accumulator by known count */
5879 /*-----------------------------------------------------------------*/
5881 AccRol (int shCount)
5883 shCount &= 0x0007; // shCount : 0..7
5890 emitcode ("rl", "a");
5893 emitcode ("rl", "a");
5894 emitcode ("rl", "a");
5897 emitcode ("swap", "a");
5898 emitcode ("rr", "a");
5901 emitcode ("swap", "a");
5904 emitcode ("swap", "a");
5905 emitcode ("rl", "a");
5908 emitcode ("rr", "a");
5909 emitcode ("rr", "a");
5912 emitcode ("rr", "a");
5917 /*-----------------------------------------------------------------*/
5918 /* AccLsh - left shift accumulator by known count */
5919 /*-----------------------------------------------------------------*/
5921 AccLsh (int shCount)
5926 emitcode ("add", "a,acc");
5927 else if (shCount == 2)
5929 emitcode ("add", "a,acc");
5930 emitcode ("add", "a,acc");
5934 /* rotate left accumulator */
5936 /* and kill the lower order bits */
5937 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5942 /*-----------------------------------------------------------------*/
5943 /* AccRsh - right shift accumulator by known count */
5944 /*-----------------------------------------------------------------*/
5946 AccRsh (int shCount)
5953 emitcode ("rrc", "a");
5957 /* rotate right accumulator */
5958 AccRol (8 - shCount);
5959 /* and kill the higher order bits */
5960 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5967 /*-----------------------------------------------------------------*/
5968 /* AccSRsh - signed right shift accumulator by known count */
5969 /*-----------------------------------------------------------------*/
5971 AccSRsh (int shCount)
5978 emitcode ("mov", "c,acc.7");
5979 emitcode ("rrc", "a");
5981 else if (shCount == 2)
5983 emitcode ("mov", "c,acc.7");
5984 emitcode ("rrc", "a");
5985 emitcode ("mov", "c,acc.7");
5986 emitcode ("rrc", "a");
5990 tlbl = newiTempLabel (NULL);
5991 /* rotate right accumulator */
5992 AccRol (8 - shCount);
5993 /* and kill the higher order bits */
5994 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5995 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5996 emitcode ("orl", "a,#0x%02x",
5997 (unsigned char) ~SRMask[shCount]);
5998 emitcode ("", "%05d$:", tlbl->key + 100);
6006 /*-----------------------------------------------------------------*/
6007 /* shiftR1Left2Result - shift right one byte from left to result */
6008 /*-----------------------------------------------------------------*/
6010 shiftR1Left2Result (operand * left, int offl,
6011 operand * result, int offr,
6012 int shCount, int sign)
6014 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6015 /* shift right accumulator */
6020 aopPut (AOP (result), "a", offr);
6026 /*-----------------------------------------------------------------*/
6027 /* shiftL1Left2Result - shift left one byte from left to result */
6028 /*-----------------------------------------------------------------*/
6030 shiftL1Left2Result (operand * left, int offl,
6031 operand * result, int offr, int shCount)
6034 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6036 /* shift left accumulator */
6038 aopPut (AOP (result), "a", offr);
6044 /*-----------------------------------------------------------------*/
6045 /* movLeft2Result - move byte from left to result */
6046 /*-----------------------------------------------------------------*/
6048 movLeft2Result (operand * left, int offl,
6049 operand * result, int offr, int sign)
6052 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6054 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6056 if (*l == '@' && (IS_AOP_PREG (result)))
6058 emitcode ("mov", "a,%s", l);
6059 aopPut (AOP (result), "a", offr);
6064 aopPut (AOP (result), l, offr);
6067 /* MSB sign in acc.7 ! */
6068 if (getDataSize (left) == offl + 1)
6070 emitcode ("mov", "a,%s", l);
6071 aopPut (AOP (result), "a", offr);
6081 /*-----------------------------------------------------------------*/
6082 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6083 /*-----------------------------------------------------------------*/
6087 emitcode ("rrc", "a");
6088 emitcode ("xch", "a,%s", x);
6089 emitcode ("rrc", "a");
6090 emitcode ("xch", "a,%s", x);
6096 /*-----------------------------------------------------------------*/
6097 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6098 /*-----------------------------------------------------------------*/
6102 emitcode ("xch", "a,%s", x);
6103 emitcode ("rlc", "a");
6104 emitcode ("xch", "a,%s", x);
6105 emitcode ("rlc", "a");
6111 /*-----------------------------------------------------------------*/
6112 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6113 /*-----------------------------------------------------------------*/
6117 emitcode ("xch", "a,%s", x);
6118 emitcode ("add", "a,acc");
6119 emitcode ("xch", "a,%s", x);
6120 emitcode ("rlc", "a");
6126 /*-----------------------------------------------------------------*/
6127 /* AccAXLsh - left shift a:x by known count (0..7) */
6128 /*-----------------------------------------------------------------*/
6130 AccAXLsh (char *x, int shCount)
6145 case 5: // AAAAABBB:CCCCCDDD
6147 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6149 emitcode ("anl", "a,#0x%02x",
6150 SLMask[shCount]); // BBB00000:CCCCCDDD
6152 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6154 AccRol (shCount); // DDDCCCCC:BBB00000
6156 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6158 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6160 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6162 emitcode ("anl", "a,#0x%02x",
6163 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6165 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6167 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6170 case 6: // AAAAAABB:CCCCCCDD
6171 emitcode ("anl", "a,#0x%02x",
6172 SRMask[shCount]); // 000000BB:CCCCCCDD
6173 emitcode ("mov", "c,acc.0"); // c = B
6174 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6176 AccAXRrl1 (x); // BCCCCCCD:D000000B
6177 AccAXRrl1 (x); // BBCCCCCC:DD000000
6179 emitcode("rrc","a");
6180 emitcode("xch","a,%s", x);
6181 emitcode("rrc","a");
6182 emitcode("mov","c,acc.0"); //<< get correct bit
6183 emitcode("xch","a,%s", x);
6185 emitcode("rrc","a");
6186 emitcode("xch","a,%s", x);
6187 emitcode("rrc","a");
6188 emitcode("xch","a,%s", x);
6191 case 7: // a:x <<= 7
6193 emitcode ("anl", "a,#0x%02x",
6194 SRMask[shCount]); // 0000000B:CCCCCCCD
6196 emitcode ("mov", "c,acc.0"); // c = B
6198 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6200 AccAXRrl1 (x); // BCCCCCCC:D0000000
6211 /*-----------------------------------------------------------------*/
6212 /* AccAXRsh - right shift a:x known count (0..7) */
6213 /*-----------------------------------------------------------------*/
6215 AccAXRsh (char *x, int shCount)
6223 AccAXRrl1 (x); // 0->a:x
6228 AccAXRrl1 (x); // 0->a:x
6231 AccAXRrl1 (x); // 0->a:x
6236 case 5: // AAAAABBB:CCCCCDDD = a:x
6238 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6240 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6242 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6244 emitcode ("anl", "a,#0x%02x",
6245 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6247 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6249 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6251 emitcode ("anl", "a,#0x%02x",
6252 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6254 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6256 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6258 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6261 case 6: // AABBBBBB:CCDDDDDD
6263 emitcode ("mov", "c,acc.7");
6264 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6266 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6268 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6270 emitcode ("anl", "a,#0x%02x",
6271 SRMask[shCount]); // 000000AA:BBBBBBCC
6274 case 7: // ABBBBBBB:CDDDDDDD
6276 emitcode ("mov", "c,acc.7"); // c = A
6278 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6280 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6282 emitcode ("anl", "a,#0x%02x",
6283 SRMask[shCount]); // 0000000A:BBBBBBBC
6294 /*-----------------------------------------------------------------*/
6295 /* AccAXRshS - right shift signed a:x known count (0..7) */
6296 /*-----------------------------------------------------------------*/
6298 AccAXRshS (char *x, int shCount)
6306 emitcode ("mov", "c,acc.7");
6307 AccAXRrl1 (x); // s->a:x
6311 emitcode ("mov", "c,acc.7");
6312 AccAXRrl1 (x); // s->a:x
6314 emitcode ("mov", "c,acc.7");
6315 AccAXRrl1 (x); // s->a:x
6320 case 5: // AAAAABBB:CCCCCDDD = a:x
6322 tlbl = newiTempLabel (NULL);
6323 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6325 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6327 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6329 emitcode ("anl", "a,#0x%02x",
6330 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6332 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6334 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6336 emitcode ("anl", "a,#0x%02x",
6337 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6339 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6341 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6343 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6345 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6346 emitcode ("orl", "a,#0x%02x",
6347 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6349 emitcode ("", "%05d$:", tlbl->key + 100);
6350 break; // SSSSAAAA:BBBCCCCC
6352 case 6: // AABBBBBB:CCDDDDDD
6354 tlbl = newiTempLabel (NULL);
6355 emitcode ("mov", "c,acc.7");
6356 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6358 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6360 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6362 emitcode ("anl", "a,#0x%02x",
6363 SRMask[shCount]); // 000000AA:BBBBBBCC
6365 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6366 emitcode ("orl", "a,#0x%02x",
6367 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6369 emitcode ("", "%05d$:", tlbl->key + 100);
6371 case 7: // ABBBBBBB:CDDDDDDD
6373 tlbl = newiTempLabel (NULL);
6374 emitcode ("mov", "c,acc.7"); // c = A
6376 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6378 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6380 emitcode ("anl", "a,#0x%02x",
6381 SRMask[shCount]); // 0000000A:BBBBBBBC
6383 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6384 emitcode ("orl", "a,#0x%02x",
6385 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6387 emitcode ("", "%05d$:", tlbl->key + 100);
6397 /*-----------------------------------------------------------------*/
6398 /* shiftL2Left2Result - shift left two bytes from left to result */
6399 /*-----------------------------------------------------------------*/
6401 shiftL2Left2Result (operand * left, int offl,
6402 operand * result, int offr, int shCount)
6404 if (sameRegs (AOP (result), AOP (left)) &&
6405 ((offl + MSB16) == offr))
6407 /* don't crash result[offr] */
6408 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6409 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6413 movLeft2Result (left, offl, result, offr, 0);
6414 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6416 /* ax << shCount (x = lsb(result)) */
6417 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6418 aopPut (AOP (result), "a", offr + MSB16);
6424 /*-----------------------------------------------------------------*/
6425 /* shiftR2Left2Result - shift right two bytes from left to result */
6426 /*-----------------------------------------------------------------*/
6428 shiftR2Left2Result (operand * left, int offl,
6429 operand * result, int offr,
6430 int shCount, int sign)
6432 if (sameRegs (AOP (result), AOP (left)) &&
6433 ((offl + MSB16) == offr))
6435 /* don't crash result[offr] */
6436 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6437 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6441 movLeft2Result (left, offl, result, offr, 0);
6442 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6444 /* a:x >> shCount (x = lsb(result)) */
6446 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6448 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6449 if (getDataSize (result) > 1)
6450 aopPut (AOP (result), "a", offr + MSB16);
6456 /*-----------------------------------------------------------------*/
6457 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6458 /*-----------------------------------------------------------------*/
6460 shiftLLeftOrResult (operand * left, int offl,
6461 operand * result, int offr, int shCount)
6463 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6464 /* shift left accumulator */
6466 /* or with result */
6467 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6468 /* back to result */
6469 aopPut (AOP (result), "a", offr);
6475 /*-----------------------------------------------------------------*/
6476 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6477 /*-----------------------------------------------------------------*/
6479 shiftRLeftOrResult (operand * left, int offl,
6480 operand * result, int offr, int shCount)
6482 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6483 /* shift right accumulator */
6485 /* or with result */
6486 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6487 /* back to result */
6488 aopPut (AOP (result), "a", offr);
6494 /*-----------------------------------------------------------------*/
6495 /* genlshOne - left shift a one byte quantity by known count */
6496 /*-----------------------------------------------------------------*/
6498 genlshOne (operand * result, operand * left, int shCount)
6500 D (emitcode (";", "genlshOne ");
6502 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6508 /*-----------------------------------------------------------------*/
6509 /* genlshTwo - left shift two bytes by known amount != 0 */
6510 /*-----------------------------------------------------------------*/
6512 genlshTwo (operand * result, operand * left, int shCount)
6516 D (emitcode (";", "genlshTwo ");
6519 size = getDataSize (result);
6521 /* if shCount >= 8 */
6529 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6531 movLeft2Result (left, LSB, result, MSB16, 0);
6533 aopPut (AOP (result), zero, LSB);
6536 /* 1 <= shCount <= 7 */
6540 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6542 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6549 /*-----------------------------------------------------------------*/
6550 /* shiftLLong - shift left one long from left to result */
6551 /* offl = LSB or MSB16 */
6552 /*-----------------------------------------------------------------*/
6554 shiftLLong (operand * left, operand * result, int offr)
6557 int size = AOP_SIZE (result);
6559 if (size >= LSB + offr)
6561 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6563 emitcode ("add", "a,acc");
6564 if (sameRegs (AOP (left), AOP (result)) &&
6565 size >= MSB16 + offr && offr != LSB)
6566 emitcode ("xch", "a,%s",
6567 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6569 aopPut (AOP (result), "a", LSB + offr);
6572 if (size >= MSB16 + offr)
6574 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6576 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6579 emitcode ("rlc", "a");
6580 if (sameRegs (AOP (left), AOP (result)) &&
6581 size >= MSB24 + offr && offr != LSB)
6582 emitcode ("xch", "a,%s",
6583 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6585 aopPut (AOP (result), "a", MSB16 + offr);
6588 if (size >= MSB24 + offr)
6590 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6592 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6595 emitcode ("rlc", "a");
6596 if (sameRegs (AOP (left), AOP (result)) &&
6597 size >= MSB32 + offr && offr != LSB)
6598 emitcode ("xch", "a,%s",
6599 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6601 aopPut (AOP (result), "a", MSB24 + offr);
6604 if (size > MSB32 + offr)
6606 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6608 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6611 emitcode ("rlc", "a");
6612 aopPut (AOP (result), "a", MSB32 + offr);
6615 aopPut (AOP (result), zero, LSB);
6621 /*-----------------------------------------------------------------*/
6622 /* genlshFour - shift four byte by a known amount != 0 */
6623 /*-----------------------------------------------------------------*/
6625 genlshFour (operand * result, operand * left, int shCount)
6629 D (emitcode (";", "genlshFour ");
6632 size = AOP_SIZE (result);
6634 /* if shifting more that 3 bytes */
6639 /* lowest order of left goes to the highest
6640 order of the destination */
6641 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6643 movLeft2Result (left, LSB, result, MSB32, 0);
6644 aopPut (AOP (result), zero, LSB);
6645 aopPut (AOP (result), zero, MSB16);
6646 aopPut (AOP (result), zero, MSB32);
6650 /* more than two bytes */
6651 else if (shCount >= 16)
6653 /* lower order two bytes goes to higher order two bytes */
6655 /* if some more remaining */
6657 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6660 movLeft2Result (left, MSB16, result, MSB32, 0);
6661 movLeft2Result (left, LSB, result, MSB24, 0);
6663 aopPut (AOP (result), zero, MSB16);
6664 aopPut (AOP (result), zero, LSB);
6668 /* if more than 1 byte */
6669 else if (shCount >= 8)
6671 /* lower order three bytes goes to higher order three bytes */
6676 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6678 movLeft2Result (left, LSB, result, MSB16, 0);
6684 movLeft2Result (left, MSB24, result, MSB32, 0);
6685 movLeft2Result (left, MSB16, result, MSB24, 0);
6686 movLeft2Result (left, LSB, result, MSB16, 0);
6687 aopPut (AOP (result), zero, LSB);
6689 else if (shCount == 1)
6690 shiftLLong (left, result, MSB16);
6693 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6694 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6695 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6696 aopPut (AOP (result), zero, LSB);
6701 /* 1 <= shCount <= 7 */
6702 else if (shCount <= 2)
6704 shiftLLong (left, result, LSB);
6706 shiftLLong (result, result, LSB);
6708 /* 3 <= shCount <= 7, optimize */
6711 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6712 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6713 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6720 /*-----------------------------------------------------------------*/
6721 /* genLeftShiftLiteral - left shifting by known count */
6722 /*-----------------------------------------------------------------*/
6724 genLeftShiftLiteral (operand * left,
6729 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6732 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6735 freeAsmop (right, NULL, ic, TRUE);
6737 aopOp (left, ic, FALSE, FALSE);
6738 aopOp (result, ic, FALSE, TRUE);
6740 size = getSize (operandType (result));
6743 emitcode ("; shift left ", "result %d, left %d", size,
6747 /* I suppose that the left size >= result size */
6752 movLeft2Result (left, size, result, size, 0);
6756 else if (shCount >= (size * 8))
6758 aopPut (AOP (result), zero, size);
6764 genlshOne (result, left, shCount);
6768 case 3: /* bug: this is for generic pointers, I bet. */
6769 genlshTwo (result, left, shCount);
6773 genlshFour (result, left, shCount);
6777 freeAsmop (left, NULL, ic, TRUE);
6778 freeAsmop (result, NULL, ic, TRUE);
6782 /*-----------------------------------------------------------------*/
6783 /* genLeftShift - generates code for left shifting */
6784 /*-----------------------------------------------------------------*/
6786 genLeftShift (iCode * ic)
6788 operand *left, *right, *result;
6791 symbol *tlbl, *tlbl1;
6793 D (emitcode (";", "genLeftShift ");
6796 right = IC_RIGHT (ic);
6797 left = IC_LEFT (ic);
6798 result = IC_RESULT (ic);
6800 aopOp (right, ic, FALSE, FALSE);
6803 /* if the shift count is known then do it
6804 as efficiently as possible */
6805 if (AOP_TYPE (right) == AOP_LIT)
6807 genLeftShiftLiteral (left, right, result, ic);
6812 /* shift count is unknown then we have to form
6813 a loop get the loop count in B : Note: we take
6814 only the lower order byte since shifting
6815 more that 32 bits make no sense anyway, ( the
6816 largest size of an object can be only 32 bits ) */
6818 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6819 emitcode ("inc", "b");
6820 freeAsmop (right, NULL, ic, TRUE);
6821 aopOp (left, ic, FALSE, FALSE);
6822 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6824 /* now move the left to the result if they are not the
6826 if (!sameRegs (AOP (left), AOP (result)) &&
6827 AOP_SIZE (result) > 1)
6830 size = AOP_SIZE (result);
6832 _startLazyDPSEvaluation ();
6835 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6836 if (*l == '@' && (IS_AOP_PREG (result)))
6839 emitcode ("mov", "a,%s", l);
6840 aopPut (AOP (result), "a", offset);
6843 aopPut (AOP (result), l, offset);
6846 _endLazyDPSEvaluation ();
6849 tlbl = newiTempLabel (NULL);
6850 size = AOP_SIZE (result);
6852 tlbl1 = newiTempLabel (NULL);
6854 /* if it is only one byte then */
6857 symbol *tlbl1 = newiTempLabel (NULL);
6859 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6861 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6862 emitcode ("", "%05d$:", tlbl->key + 100);
6863 emitcode ("add", "a,acc");
6864 emitcode ("", "%05d$:", tlbl1->key + 100);
6865 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6866 aopPut (AOP (result), "a", 0);
6870 reAdjustPreg (AOP (result));
6872 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6873 emitcode ("", "%05d$:", tlbl->key + 100);
6874 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6876 emitcode ("add", "a,acc");
6877 aopPut (AOP (result), "a", offset++);
6878 _startLazyDPSEvaluation ();
6881 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6883 emitcode ("rlc", "a");
6884 aopPut (AOP (result), "a", offset++);
6886 _endLazyDPSEvaluation ();
6887 reAdjustPreg (AOP (result));
6889 emitcode ("", "%05d$:", tlbl1->key + 100);
6890 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6892 freeAsmop (left, NULL, ic, TRUE);
6893 freeAsmop (result, NULL, ic, TRUE);
6898 /*-----------------------------------------------------------------*/
6899 /* genrshOne - right shift a one byte quantity by known count */
6900 /*-----------------------------------------------------------------*/
6902 genrshOne (operand * result, operand * left,
6903 int shCount, int sign)
6905 D (emitcode (";", "genrshOne");
6907 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6913 /*-----------------------------------------------------------------*/
6914 /* genrshTwo - right shift two bytes by known amount != 0 */
6915 /*-----------------------------------------------------------------*/
6917 genrshTwo (operand * result, operand * left,
6918 int shCount, int sign)
6920 D (emitcode (";", "genrshTwo");
6923 /* if shCount >= 8 */
6928 shiftR1Left2Result (left, MSB16, result, LSB,
6931 movLeft2Result (left, MSB16, result, LSB, sign);
6932 addSign (result, MSB16, sign);
6935 /* 1 <= shCount <= 7 */
6937 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6943 /*-----------------------------------------------------------------*/
6944 /* shiftRLong - shift right one long from left to result */
6945 /* offl = LSB or MSB16 */
6946 /*-----------------------------------------------------------------*/
6948 shiftRLong (operand * left, int offl,
6949 operand * result, int sign)
6952 emitcode ("clr", "c");
6953 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6955 emitcode ("mov", "c,acc.7");
6956 emitcode ("rrc", "a");
6957 aopPut (AOP (result), "a", MSB32 - offl);
6959 /* add sign of "a" */
6960 addSign (result, MSB32, sign);
6962 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6963 emitcode ("rrc", "a");
6964 aopPut (AOP (result), "a", MSB24 - offl);
6966 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6967 emitcode ("rrc", "a");
6968 aopPut (AOP (result), "a", MSB16 - offl);
6972 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6973 emitcode ("rrc", "a");
6974 aopPut (AOP (result), "a", LSB);
6981 /*-----------------------------------------------------------------*/
6982 /* genrshFour - shift four byte by a known amount != 0 */
6983 /*-----------------------------------------------------------------*/
6985 genrshFour (operand * result, operand * left,
6986 int shCount, int sign)
6988 D (emitcode (";", "genrshFour");
6991 /* if shifting more that 3 bytes */
6996 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6998 movLeft2Result (left, MSB32, result, LSB, sign);
6999 addSign (result, MSB16, sign);
7001 else if (shCount >= 16)
7005 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7008 movLeft2Result (left, MSB24, result, LSB, 0);
7009 movLeft2Result (left, MSB32, result, MSB16, sign);
7011 addSign (result, MSB24, sign);
7013 else if (shCount >= 8)
7017 shiftRLong (left, MSB16, result, sign);
7018 else if (shCount == 0)
7020 movLeft2Result (left, MSB16, result, LSB, 0);
7021 movLeft2Result (left, MSB24, result, MSB16, 0);
7022 movLeft2Result (left, MSB32, result, MSB24, sign);
7023 addSign (result, MSB32, sign);
7027 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7028 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7029 /* the last shift is signed */
7030 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7031 addSign (result, MSB32, sign);
7035 { /* 1 <= shCount <= 7 */
7038 shiftRLong (left, LSB, result, sign);
7040 shiftRLong (result, LSB, result, sign);
7044 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7045 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7046 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7054 /*-----------------------------------------------------------------*/
7055 /* genRightShiftLiteral - right shifting by known count */
7056 /*-----------------------------------------------------------------*/
7058 genRightShiftLiteral (operand * left,
7064 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7067 D (emitcode (";", "genRightShiftLiteral");
7070 freeAsmop (right, NULL, ic, TRUE);
7072 aopOp (left, ic, FALSE, FALSE);
7073 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7076 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7080 size = getDataSize (left);
7081 /* test the LEFT size !!! */
7083 /* I suppose that the left size >= result size */
7086 size = getDataSize (result);
7088 movLeft2Result (left, size, result, size, 0);
7091 else if (shCount >= (size * 8))
7094 /* get sign in acc.7 */
7095 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7096 addSign (result, LSB, sign);
7103 genrshOne (result, left, shCount, sign);
7107 genrshTwo (result, left, shCount, sign);
7111 genrshFour (result, left, shCount, sign);
7117 freeAsmop (left, NULL, ic, TRUE);
7118 freeAsmop (result, NULL, ic, TRUE);
7123 /*-----------------------------------------------------------------*/
7124 /* genSignedRightShift - right shift of signed number */
7125 /*-----------------------------------------------------------------*/
7127 genSignedRightShift (iCode * ic)
7129 operand *right, *left, *result;
7132 symbol *tlbl, *tlbl1;
7134 D (emitcode (";", "genSignedRightShift ");
7137 /* we do it the hard way put the shift count in b
7138 and loop thru preserving the sign */
7140 right = IC_RIGHT (ic);
7141 left = IC_LEFT (ic);
7142 result = IC_RESULT (ic);
7144 aopOp (right, ic, FALSE, FALSE);
7147 if (AOP_TYPE (right) == AOP_LIT)
7149 genRightShiftLiteral (left, right, result, ic, 1);
7153 /* shift count is unknown then we have to form
7154 a loop get the loop count in B : Note: we take
7155 only the lower order byte since shifting
7156 more that 32 bits make no sense anyway, ( the
7157 largest size of an object can be only 32 bits ) */
7159 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7160 emitcode ("inc", "b");
7161 freeAsmop (right, NULL, ic, TRUE);
7162 aopOp (left, ic, FALSE, FALSE);
7163 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7165 /* now move the left to the result if they are not the
7167 if (!sameRegs (AOP (left), AOP (result)) &&
7168 AOP_SIZE (result) > 1)
7171 size = AOP_SIZE (result);
7173 _startLazyDPSEvaluation ();
7176 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7177 if (*l == '@' && IS_AOP_PREG (result))
7180 emitcode ("mov", "a,%s", l);
7181 aopPut (AOP (result), "a", offset);
7184 aopPut (AOP (result), l, offset);
7187 _endLazyDPSEvaluation ();
7190 /* mov the highest order bit to OVR */
7191 tlbl = newiTempLabel (NULL);
7192 tlbl1 = newiTempLabel (NULL);
7194 size = AOP_SIZE (result);
7196 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7197 emitcode ("rlc", "a");
7198 emitcode ("mov", "ov,c");
7199 /* if it is only one byte then */
7202 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7204 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7205 emitcode ("", "%05d$:", tlbl->key + 100);
7206 emitcode ("mov", "c,ov");
7207 emitcode ("rrc", "a");
7208 emitcode ("", "%05d$:", tlbl1->key + 100);
7209 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7210 aopPut (AOP (result), "a", 0);
7214 reAdjustPreg (AOP (result));
7215 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7216 emitcode ("", "%05d$:", tlbl->key + 100);
7217 emitcode ("mov", "c,ov");
7218 _startLazyDPSEvaluation ();
7221 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7223 emitcode ("rrc", "a");
7224 aopPut (AOP (result), "a", offset--);
7226 _endLazyDPSEvaluation ();
7227 reAdjustPreg (AOP (result));
7228 emitcode ("", "%05d$:", tlbl1->key + 100);
7229 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7232 freeAsmop (left, NULL, ic, TRUE);
7233 freeAsmop (result, NULL, ic, TRUE);
7236 /*-----------------------------------------------------------------*/
7237 /* genRightShift - generate code for right shifting */
7238 /*-----------------------------------------------------------------*/
7240 genRightShift (iCode * ic)
7242 operand *right, *left, *result;
7246 symbol *tlbl, *tlbl1;
7248 D (emitcode (";", "genRightShift ");
7251 /* if signed then we do it the hard way preserve the
7252 sign bit moving it inwards */
7253 retype = getSpec (operandType (IC_RESULT (ic)));
7255 if (!SPEC_USIGN (retype))
7257 genSignedRightShift (ic);
7261 /* signed & unsigned types are treated the same : i.e. the
7262 signed is NOT propagated inwards : quoting from the
7263 ANSI - standard : "for E1 >> E2, is equivalent to division
7264 by 2**E2 if unsigned or if it has a non-negative value,
7265 otherwise the result is implementation defined ", MY definition
7266 is that the sign does not get propagated */
7268 right = IC_RIGHT (ic);
7269 left = IC_LEFT (ic);
7270 result = IC_RESULT (ic);
7272 aopOp (right, ic, FALSE, FALSE);
7275 /* if the shift count is known then do it
7276 as efficiently as possible */
7277 if (AOP_TYPE (right) == AOP_LIT)
7279 genRightShiftLiteral (left, right, result, ic, 0);
7284 /* shift count is unknown then we have to form
7285 a loop get the loop count in B : Note: we take
7286 only the lower order byte since shifting
7287 more that 32 bits make no sense anyway, ( the
7288 largest size of an object can be only 32 bits ) */
7290 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7291 emitcode ("inc", "b");
7292 freeAsmop (right, NULL, ic, TRUE);
7293 aopOp (left, ic, FALSE, FALSE);
7294 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7296 /* now move the left to the result if they are not the
7298 if (!sameRegs (AOP (left), AOP (result)) &&
7299 AOP_SIZE (result) > 1)
7302 size = AOP_SIZE (result);
7304 _startLazyDPSEvaluation ();
7307 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7308 if (*l == '@' && IS_AOP_PREG (result))
7311 emitcode ("mov", "a,%s", l);
7312 aopPut (AOP (result), "a", offset);
7315 aopPut (AOP (result), l, offset);
7318 _endLazyDPSEvaluation ();
7321 tlbl = newiTempLabel (NULL);
7322 tlbl1 = newiTempLabel (NULL);
7323 size = AOP_SIZE (result);
7326 /* if it is only one byte then */
7329 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7331 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7332 emitcode ("", "%05d$:", tlbl->key + 100);
7334 emitcode ("rrc", "a");
7335 emitcode ("", "%05d$:", tlbl1->key + 100);
7336 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7337 aopPut (AOP (result), "a", 0);
7341 reAdjustPreg (AOP (result));
7342 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7343 emitcode ("", "%05d$:", tlbl->key + 100);
7345 _startLazyDPSEvaluation ();
7348 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7350 emitcode ("rrc", "a");
7351 aopPut (AOP (result), "a", offset--);
7353 _endLazyDPSEvaluation ();
7354 reAdjustPreg (AOP (result));
7356 emitcode ("", "%05d$:", tlbl1->key + 100);
7357 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7360 freeAsmop (left, NULL, ic, TRUE);
7361 freeAsmop (result, NULL, ic, TRUE);
7364 /*-----------------------------------------------------------------*/
7365 /* genUnpackBits - generates code for unpacking bits */
7366 /*-----------------------------------------------------------------*/
7368 genUnpackBits (operand * result, char *rname, int ptype)
7375 D (emitcode (";", "genUnpackBits ");
7378 etype = getSpec (operandType (result));
7380 /* read the first byte */
7386 emitcode ("mov", "a,@%s", rname);
7390 emitcode ("movx", "a,@%s", rname);
7394 emitcode ("movx", "a,@dptr");
7398 emitcode ("clr", "a");
7399 emitcode ("movc", "a", "@a+dptr");
7403 emitcode ("lcall", "__gptrget");
7407 /* if we have bitdisplacement then it fits */
7408 /* into this byte completely or if length is */
7409 /* less than a byte */
7410 if ((shCnt = SPEC_BSTR (etype)) ||
7411 (SPEC_BLEN (etype) <= 8))
7414 /* shift right acc */
7417 emitcode ("anl", "a,#0x%02x",
7418 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7419 aopPut (AOP (result), "a", offset);
7423 /* bit field did not fit in a byte */
7424 rlen = SPEC_BLEN (etype) - 8;
7425 aopPut (AOP (result), "a", offset++);
7434 emitcode ("inc", "%s", rname);
7435 emitcode ("mov", "a,@%s", rname);
7439 emitcode ("inc", "%s", rname);
7440 emitcode ("movx", "a,@%s", rname);
7444 emitcode ("inc", "dptr");
7445 emitcode ("movx", "a,@dptr");
7449 emitcode ("clr", "a");
7450 emitcode ("inc", "dptr");
7451 emitcode ("movc", "a", "@a+dptr");
7455 emitcode ("inc", "dptr");
7456 emitcode ("lcall", "__gptrget");
7461 /* if we are done */
7465 aopPut (AOP (result), "a", offset++);
7471 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7472 aopPut (AOP (result), "a", offset);
7479 /*-----------------------------------------------------------------*/
7480 /* genDataPointerGet - generates code when ptr offset is known */
7481 /*-----------------------------------------------------------------*/
7483 genDataPointerGet (operand * left,
7489 int size, offset = 0;
7490 aopOp (result, ic, TRUE, FALSE);
7492 /* get the string representation of the name */
7493 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7494 size = AOP_SIZE (result);
7495 _startLazyDPSEvaluation ();
7499 sprintf (buffer, "(%s + %d)", l + 1, offset);
7501 sprintf (buffer, "%s", l + 1);
7502 aopPut (AOP (result), buffer, offset++);
7504 _endLazyDPSEvaluation ();
7506 freeAsmop (left, NULL, ic, TRUE);
7507 freeAsmop (result, NULL, ic, TRUE);
7510 /*-----------------------------------------------------------------*/
7511 /* genNearPointerGet - emitcode for near pointer fetch */
7512 /*-----------------------------------------------------------------*/
7514 genNearPointerGet (operand * left,
7521 sym_link *rtype, *retype, *letype;
7522 sym_link *ltype = operandType (left);
7525 rtype = operandType (result);
7526 retype = getSpec (rtype);
7527 letype = getSpec (ltype);
7529 aopOp (left, ic, FALSE, FALSE);
7531 /* if left is rematerialisable and
7532 result is not bit variable type and
7533 the left is pointer to data space i.e
7534 lower 128 bytes of space */
7535 if (AOP_TYPE (left) == AOP_IMMD &&
7536 !IS_BITVAR (retype) &&
7537 !IS_BITVAR (letype) &&
7538 DCL_TYPE (ltype) == POINTER)
7540 genDataPointerGet (left, result, ic);
7544 /* if the value is already in a pointer register
7545 then don't need anything more */
7546 if (!AOP_INPREG (AOP (left)))
7548 /* otherwise get a free pointer register */
7550 preg = getFreePtr (ic, &aop, FALSE);
7551 emitcode ("mov", "%s,%s",
7553 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7557 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7559 freeAsmop (left, NULL, ic, TRUE);
7560 aopOp (result, ic, FALSE, FALSE);
7562 /* if bitfield then unpack the bits */
7563 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7564 genUnpackBits (result, rname, POINTER);
7567 /* we have can just get the values */
7568 int size = AOP_SIZE (result);
7573 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7576 emitcode ("mov", "a,@%s", rname);
7577 aopPut (AOP (result), "a", offset);
7581 sprintf (buffer, "@%s", rname);
7582 aopPut (AOP (result), buffer, offset);
7586 emitcode ("inc", "%s", rname);
7590 /* now some housekeeping stuff */
7593 /* we had to allocate for this iCode */
7594 freeAsmop (NULL, aop, ic, TRUE);
7598 /* we did not allocate which means left
7599 already in a pointer register, then
7600 if size > 0 && this could be used again
7601 we have to point it back to where it
7603 if (AOP_SIZE (result) > 1 &&
7604 !OP_SYMBOL (left)->remat &&
7605 (OP_SYMBOL (left)->liveTo > ic->seq ||
7608 int size = AOP_SIZE (result) - 1;
7610 emitcode ("dec", "%s", rname);
7615 freeAsmop (result, NULL, ic, TRUE);
7619 /*-----------------------------------------------------------------*/
7620 /* genPagedPointerGet - emitcode for paged pointer fetch */
7621 /*-----------------------------------------------------------------*/
7623 genPagedPointerGet (operand * left,
7630 sym_link *rtype, *retype, *letype;
7632 rtype = operandType (result);
7633 retype = getSpec (rtype);
7634 letype = getSpec (operandType (left));
7635 aopOp (left, ic, FALSE, FALSE);
7637 /* if the value is already in a pointer register
7638 then don't need anything more */
7639 if (!AOP_INPREG (AOP (left)))
7641 /* otherwise get a free pointer register */
7643 preg = getFreePtr (ic, &aop, FALSE);
7644 emitcode ("mov", "%s,%s",
7646 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7650 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7652 freeAsmop (left, NULL, ic, TRUE);
7653 aopOp (result, ic, FALSE, FALSE);
7655 /* if bitfield then unpack the bits */
7656 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7657 genUnpackBits (result, rname, PPOINTER);
7660 /* we have can just get the values */
7661 int size = AOP_SIZE (result);
7667 emitcode ("movx", "a,@%s", rname);
7668 aopPut (AOP (result), "a", offset);
7673 emitcode ("inc", "%s", rname);
7677 /* now some housekeeping stuff */
7680 /* we had to allocate for this iCode */
7681 freeAsmop (NULL, aop, ic, TRUE);
7685 /* we did not allocate which means left
7686 already in a pointer register, then
7687 if size > 0 && this could be used again
7688 we have to point it back to where it
7690 if (AOP_SIZE (result) > 1 &&
7691 !OP_SYMBOL (left)->remat &&
7692 (OP_SYMBOL (left)->liveTo > ic->seq ||
7695 int size = AOP_SIZE (result) - 1;
7697 emitcode ("dec", "%s", rname);
7702 freeAsmop (result, NULL, ic, TRUE);
7707 /*-----------------------------------------------------------------*/
7708 /* genFarPointerGet - gget value from far space */
7709 /*-----------------------------------------------------------------*/
7711 genFarPointerGet (operand * left,
7712 operand * result, iCode * ic)
7715 sym_link *retype = getSpec (operandType (result));
7716 sym_link *letype = getSpec (operandType (left));
7717 D (emitcode (";", "genFarPointerGet");
7720 aopOp (left, ic, FALSE, FALSE);
7722 /* if the operand is already in dptr
7723 then we do nothing else we move the value to dptr */
7724 if (AOP_TYPE (left) != AOP_STR)
7726 /* if this is remateriazable */
7727 if (AOP_TYPE (left) == AOP_IMMD)
7729 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7733 /* we need to get it byte by byte */
7734 _startLazyDPSEvaluation ();
7735 if (AOP_TYPE (left) != AOP_DPTR)
7737 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7738 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7739 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7743 /* We need to generate a load to DPTR indirect through DPTR. */
7744 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7746 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7747 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7748 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7749 emitcode ("pop", "dph");
7750 emitcode ("pop", "dpl");
7752 _endLazyDPSEvaluation ();
7755 /* so dptr know contains the address */
7756 freeAsmop (left, NULL, ic, TRUE);
7757 aopOp (result, ic, FALSE, TRUE);
7759 /* if bit then unpack */
7760 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7761 genUnpackBits (result, "dptr", FPOINTER);
7764 size = AOP_SIZE (result);
7767 _startLazyDPSEvaluation ();
7774 emitcode ("movx", "a,@dptr");
7776 emitcode ("inc", "dptr");
7778 aopPut (AOP (result), "a", offset++);
7780 _endLazyDPSEvaluation ();
7783 freeAsmop (result, NULL, ic, TRUE);
7786 /*-----------------------------------------------------------------*/
7787 /* emitcodePointerGet - gget value from code space */
7788 /*-----------------------------------------------------------------*/
7790 emitcodePointerGet (operand * left,
7791 operand * result, iCode * ic)
7794 sym_link *retype = getSpec (operandType (result));
7796 aopOp (left, ic, FALSE, FALSE);
7798 /* if the operand is already in dptr
7799 then we do nothing else we move the value to dptr */
7800 if (AOP_TYPE (left) != AOP_STR)
7802 /* if this is remateriazable */
7803 if (AOP_TYPE (left) == AOP_IMMD)
7805 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7808 { /* we need to get it byte by byte */
7809 _startLazyDPSEvaluation ();
7810 if (AOP_TYPE (left) != AOP_DPTR)
7812 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7813 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7814 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7818 /* We need to generate a load to DPTR indirect through DPTR. */
7819 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7821 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7822 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7823 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7824 emitcode ("pop", "dph");
7825 emitcode ("pop", "dpl");
7827 _endLazyDPSEvaluation ();
7830 /* so dptr know contains the address */
7831 freeAsmop (left, NULL, ic, TRUE);
7832 aopOp (result, ic, FALSE, TRUE);
7834 /* if bit then unpack */
7835 if (IS_BITVAR (retype))
7836 genUnpackBits (result, "dptr", CPOINTER);
7839 size = AOP_SIZE (result);
7842 _startLazyDPSEvaluation ();
7848 emitcode ("clr", "a");
7849 emitcode ("movc", "a,@a+dptr");
7851 emitcode ("inc", "dptr");
7852 aopPut (AOP (result), "a", offset++);
7854 _endLazyDPSEvaluation ();
7857 freeAsmop (result, NULL, ic, TRUE);
7860 /*-----------------------------------------------------------------*/
7861 /* genGenPointerGet - gget value from generic pointer space */
7862 /*-----------------------------------------------------------------*/
7864 genGenPointerGet (operand * left,
7865 operand * result, iCode * ic)
7868 sym_link *retype = getSpec (operandType (result));
7869 sym_link *letype = getSpec (operandType (left));
7871 D (emitcode (";", "genGenPointerGet "); );
7873 aopOp (left, ic, FALSE, TRUE);
7875 /* if the operand is already in dptr
7876 then we do nothing else we move the value to dptr */
7877 if (AOP_TYPE (left) != AOP_STR)
7879 /* if this is remateriazable */
7880 if (AOP_TYPE (left) == AOP_IMMD)
7882 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7883 emitcode ("mov", "b,#%d", pointerCode (retype));
7886 { /* we need to get it byte by byte */
7887 _startLazyDPSEvaluation ();
7888 if (AOP(left)->type==AOP_DPTR2) {
7890 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7893 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7894 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7897 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7898 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7901 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7902 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7904 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7905 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7906 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7907 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7909 _endLazyDPSEvaluation ();
7912 /* so dptr know contains the address */
7913 freeAsmop (left, NULL, ic, TRUE);
7914 aopOp (result, ic, FALSE, TRUE);
7916 /* if bit then unpack */
7917 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7918 genUnpackBits (result, "dptr", GPOINTER);
7921 size = AOP_SIZE (result);
7926 emitcode ("lcall", "__gptrget");
7927 aopPut (AOP (result), "a", offset++);
7929 emitcode ("inc", "dptr");
7933 freeAsmop (result, NULL, ic, TRUE);
7936 /*-----------------------------------------------------------------*/
7937 /* genPointerGet - generate code for pointer get */
7938 /*-----------------------------------------------------------------*/
7940 genPointerGet (iCode * ic)
7942 operand *left, *result;
7943 sym_link *type, *etype;
7946 D (emitcode (";", "genPointerGet ");
7949 left = IC_LEFT (ic);
7950 result = IC_RESULT (ic);
7952 /* depending on the type of pointer we need to
7953 move it to the correct pointer register */
7954 type = operandType (left);
7955 etype = getSpec (type);
7956 /* if left is of type of pointer then it is simple */
7957 if (IS_PTR (type) && !IS_FUNC (type->next))
7958 p_type = DCL_TYPE (type);
7961 /* we have to go by the storage class */
7962 p_type = PTR_TYPE (SPEC_OCLS (etype));
7965 /* now that we have the pointer type we assign
7966 the pointer values */
7972 genNearPointerGet (left, result, ic);
7976 genPagedPointerGet (left, result, ic);
7980 genFarPointerGet (left, result, ic);
7984 emitcodePointerGet (left, result, ic);
7988 genGenPointerGet (left, result, ic);
7994 /*-----------------------------------------------------------------*/
7995 /* genPackBits - generates code for packed bit storage */
7996 /*-----------------------------------------------------------------*/
7998 genPackBits (sym_link * etype,
8000 char *rname, int p_type)
8008 blen = SPEC_BLEN (etype);
8009 bstr = SPEC_BSTR (etype);
8011 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8014 /* if the bit lenth is less than or */
8015 /* it exactly fits a byte then */
8016 if (SPEC_BLEN (etype) <= 8)
8018 shCount = SPEC_BSTR (etype);
8020 /* shift left acc */
8023 if (SPEC_BLEN (etype) < 8)
8024 { /* if smaller than a byte */
8030 emitcode ("mov", "b,a");
8031 emitcode ("mov", "a,@%s", rname);
8035 emitcode ("mov", "b,a");
8036 emitcode ("movx", "a,@dptr");
8040 emitcode ("push", "b");
8041 emitcode ("push", "acc");
8042 emitcode ("lcall", "__gptrget");
8043 emitcode ("pop", "b");
8047 emitcode ("anl", "a,#0x%02x", (unsigned char)
8048 ((unsigned char) (0xFF << (blen + bstr)) |
8049 (unsigned char) (0xFF >> (8 - bstr))));
8050 emitcode ("orl", "a,b");
8051 if (p_type == GPOINTER)
8052 emitcode ("pop", "b");
8059 emitcode ("mov", "@%s,a", rname);
8063 emitcode ("movx", "@dptr,a");
8067 emitcode ("lcall", "__gptrput");
8072 if (SPEC_BLEN (etype) <= 8)
8075 emitcode ("inc", "%s", rname);
8076 rLen = SPEC_BLEN (etype);
8078 /* now generate for lengths greater than one byte */
8082 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8094 emitcode ("mov", "@%s,a", rname);
8097 emitcode ("mov", "@%s,%s", rname, l);
8102 emitcode ("movx", "@dptr,a");
8107 emitcode ("lcall", "__gptrput");
8110 emitcode ("inc", "%s", rname);
8115 /* last last was not complete */
8118 /* save the byte & read byte */
8122 emitcode ("mov", "b,a");
8123 emitcode ("mov", "a,@%s", rname);
8127 emitcode ("mov", "b,a");
8128 emitcode ("movx", "a,@dptr");
8132 emitcode ("push", "b");
8133 emitcode ("push", "acc");
8134 emitcode ("lcall", "__gptrget");
8135 emitcode ("pop", "b");
8139 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8140 emitcode ("orl", "a,b");
8143 if (p_type == GPOINTER)
8144 emitcode ("pop", "b");
8150 emitcode ("mov", "@%s,a", rname);
8154 emitcode ("movx", "@dptr,a");
8158 emitcode ("lcall", "__gptrput");
8162 /*-----------------------------------------------------------------*/
8163 /* genDataPointerSet - remat pointer to data space */
8164 /*-----------------------------------------------------------------*/
8166 genDataPointerSet (operand * right,
8170 int size, offset = 0;
8171 char *l, buffer[256];
8173 aopOp (right, ic, FALSE, FALSE);
8175 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8176 size = AOP_SIZE (right);
8180 sprintf (buffer, "(%s + %d)", l + 1, offset);
8182 sprintf (buffer, "%s", l + 1);
8183 emitcode ("mov", "%s,%s", buffer,
8184 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8187 freeAsmop (right, NULL, ic, TRUE);
8188 freeAsmop (result, NULL, ic, TRUE);
8191 /*-----------------------------------------------------------------*/
8192 /* genNearPointerSet - emitcode for near pointer put */
8193 /*-----------------------------------------------------------------*/
8195 genNearPointerSet (operand * right,
8202 sym_link *retype, *letype;
8203 sym_link *ptype = operandType (result);
8205 retype = getSpec (operandType (right));
8206 letype = getSpec (ptype);
8208 aopOp (result, ic, FALSE, FALSE);
8210 /* if the result is rematerializable &
8211 in data space & not a bit variable */
8212 if (AOP_TYPE (result) == AOP_IMMD &&
8213 DCL_TYPE (ptype) == POINTER &&
8214 !IS_BITVAR (retype) &&
8215 !IS_BITVAR (letype))
8217 genDataPointerSet (right, result, ic);
8221 /* if the value is already in a pointer register
8222 then don't need anything more */
8223 if (!AOP_INPREG (AOP (result)))
8225 /* otherwise get a free pointer register */
8227 preg = getFreePtr (ic, &aop, FALSE);
8228 emitcode ("mov", "%s,%s",
8230 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8234 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8236 freeAsmop (result, NULL, ic, TRUE);
8237 aopOp (right, ic, FALSE, FALSE);
8239 /* if bitfield then unpack the bits */
8240 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8241 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8244 /* we have can just get the values */
8245 int size = AOP_SIZE (right);
8250 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8254 emitcode ("mov", "@%s,a", rname);
8257 emitcode ("mov", "@%s,%s", rname, l);
8259 emitcode ("inc", "%s", rname);
8264 /* now some housekeeping stuff */
8267 /* we had to allocate for this iCode */
8268 freeAsmop (NULL, aop, ic, TRUE);
8272 /* we did not allocate which means left
8273 already in a pointer register, then
8274 if size > 0 && this could be used again
8275 we have to point it back to where it
8277 if (AOP_SIZE (right) > 1 &&
8278 !OP_SYMBOL (result)->remat &&
8279 (OP_SYMBOL (result)->liveTo > ic->seq ||
8282 int size = AOP_SIZE (right) - 1;
8284 emitcode ("dec", "%s", rname);
8289 freeAsmop (right, NULL, ic, TRUE);
8294 /*-----------------------------------------------------------------*/
8295 /* genPagedPointerSet - emitcode for Paged pointer put */
8296 /*-----------------------------------------------------------------*/
8298 genPagedPointerSet (operand * right,
8305 sym_link *retype, *letype;
8307 retype = getSpec (operandType (right));
8308 letype = getSpec (operandType (result));
8310 aopOp (result, ic, FALSE, FALSE);
8312 /* if the value is already in a pointer register
8313 then don't need anything more */
8314 if (!AOP_INPREG (AOP (result)))
8316 /* otherwise get a free pointer register */
8318 preg = getFreePtr (ic, &aop, FALSE);
8319 emitcode ("mov", "%s,%s",
8321 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8325 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8327 freeAsmop (result, NULL, ic, TRUE);
8328 aopOp (right, ic, FALSE, FALSE);
8330 /* if bitfield then unpack the bits */
8331 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8332 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8335 /* we have can just get the values */
8336 int size = AOP_SIZE (right);
8341 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8344 emitcode ("movx", "@%s,a", rname);
8347 emitcode ("inc", "%s", rname);
8353 /* now some housekeeping stuff */
8356 /* we had to allocate for this iCode */
8357 freeAsmop (NULL, aop, ic, TRUE);
8361 /* we did not allocate which means left
8362 already in a pointer register, then
8363 if size > 0 && this could be used again
8364 we have to point it back to where it
8366 if (AOP_SIZE (right) > 1 &&
8367 !OP_SYMBOL (result)->remat &&
8368 (OP_SYMBOL (result)->liveTo > ic->seq ||
8371 int size = AOP_SIZE (right) - 1;
8373 emitcode ("dec", "%s", rname);
8378 freeAsmop (right, NULL, ic, TRUE);
8383 /*-----------------------------------------------------------------*/
8384 /* genFarPointerSet - set value from far space */
8385 /*-----------------------------------------------------------------*/
8387 genFarPointerSet (operand * right,
8388 operand * result, iCode * ic)
8391 sym_link *retype = getSpec (operandType (right));
8392 sym_link *letype = getSpec (operandType (result));
8394 aopOp (result, ic, FALSE, FALSE);
8396 /* if the operand is already in dptr
8397 then we do nothing else we move the value to dptr */
8398 if (AOP_TYPE (result) != AOP_STR)
8400 /* if this is remateriazable */
8401 if (AOP_TYPE (result) == AOP_IMMD)
8402 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8405 /* we need to get it byte by byte */
8406 _startLazyDPSEvaluation ();
8407 if (AOP_TYPE (result) != AOP_DPTR)
8409 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8410 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8411 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8415 /* We need to generate a load to DPTR indirect through DPTR. */
8416 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8418 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8419 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8420 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8421 emitcode ("pop", "dph");
8422 emitcode ("pop", "dpl");
8424 _endLazyDPSEvaluation ();
8427 /* so dptr know contains the address */
8428 freeAsmop (result, NULL, ic, TRUE);
8429 aopOp (right, ic, FALSE, TRUE);
8431 /* if bit then unpack */
8432 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8433 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8436 size = AOP_SIZE (right);
8439 _startLazyDPSEvaluation ();
8442 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8448 emitcode ("movx", "@dptr,a");
8450 emitcode ("inc", "dptr");
8452 _endLazyDPSEvaluation ();
8455 freeAsmop (right, NULL, ic, TRUE);
8458 /*-----------------------------------------------------------------*/
8459 /* genGenPointerSet - set value from generic pointer space */
8460 /*-----------------------------------------------------------------*/
8462 genGenPointerSet (operand * right,
8463 operand * result, iCode * ic)
8466 sym_link *retype = getSpec (operandType (right));
8467 sym_link *letype = getSpec (operandType (result));
8469 aopOp (result, ic, FALSE, TRUE);
8471 /* if the operand is already in dptr
8472 then we do nothing else we move the value to dptr */
8473 if (AOP_TYPE (result) != AOP_STR)
8475 _startLazyDPSEvaluation ();
8476 /* if this is remateriazable */
8477 if (AOP_TYPE (result) == AOP_IMMD)
8479 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8480 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8483 { /* we need to get it byte by byte */
8484 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8485 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8486 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8487 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8489 _endLazyDPSEvaluation ();
8491 /* so dptr know contains the address */
8492 freeAsmop (result, NULL, ic, TRUE);
8493 aopOp (right, ic, FALSE, TRUE);
8495 /* if bit then unpack */
8496 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8497 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8500 size = AOP_SIZE (right);
8503 _startLazyDPSEvaluation ();
8506 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8512 emitcode ("lcall", "__gptrput");
8514 emitcode ("inc", "dptr");
8516 _endLazyDPSEvaluation ();
8519 freeAsmop (right, NULL, ic, TRUE);
8522 /*-----------------------------------------------------------------*/
8523 /* genPointerSet - stores the value into a pointer location */
8524 /*-----------------------------------------------------------------*/
8526 genPointerSet (iCode * ic)
8528 operand *right, *result;
8529 sym_link *type, *etype;
8532 D (emitcode (";", "genPointerSet ");
8535 right = IC_RIGHT (ic);
8536 result = IC_RESULT (ic);
8538 /* depending on the type of pointer we need to
8539 move it to the correct pointer register */
8540 type = operandType (result);
8541 etype = getSpec (type);
8542 /* if left is of type of pointer then it is simple */
8543 if (IS_PTR (type) && !IS_FUNC (type->next))
8545 p_type = DCL_TYPE (type);
8549 /* we have to go by the storage class */
8550 p_type = PTR_TYPE (SPEC_OCLS (etype));
8553 /* now that we have the pointer type we assign
8554 the pointer values */
8560 genNearPointerSet (right, result, ic);
8564 genPagedPointerSet (right, result, ic);
8568 genFarPointerSet (right, result, ic);
8572 genGenPointerSet (right, result, ic);
8578 /*-----------------------------------------------------------------*/
8579 /* genIfx - generate code for Ifx statement */
8580 /*-----------------------------------------------------------------*/
8582 genIfx (iCode * ic, iCode * popIc)
8584 operand *cond = IC_COND (ic);
8587 D (emitcode (";", "genIfx ");
8590 aopOp (cond, ic, FALSE, FALSE);
8592 /* get the value into acc */
8593 if (AOP_TYPE (cond) != AOP_CRY)
8597 /* the result is now in the accumulator */
8598 freeAsmop (cond, NULL, ic, TRUE);
8600 /* if there was something to be popped then do it */
8604 /* if the condition is a bit variable */
8605 if (isbit && IS_ITEMP (cond) &&
8607 genIfxJump (ic, SPIL_LOC (cond)->rname);
8608 else if (isbit && !IS_ITEMP (cond))
8609 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8611 genIfxJump (ic, "a");
8616 /*-----------------------------------------------------------------*/
8617 /* genAddrOf - generates code for address of */
8618 /*-----------------------------------------------------------------*/
8620 genAddrOf (iCode * ic)
8622 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8625 D (emitcode (";", "genAddrOf ");
8628 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8630 /* if the operand is on the stack then we
8631 need to get the stack offset of this
8635 /* if it has an offset then we need to compute
8639 emitcode ("mov", "a,_bp");
8640 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8641 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8645 /* we can just move _bp */
8646 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8648 /* fill the result with zero */
8649 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8652 if (options.stack10bit && size < (FPTRSIZE - 1))
8655 "*** warning: pointer to stack var truncated.\n");
8662 if (options.stack10bit && offset == 2)
8664 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8668 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8675 /* object not on stack then we need the name */
8676 size = AOP_SIZE (IC_RESULT (ic));
8681 char s[SDCC_NAME_MAX];
8683 sprintf (s, "#(%s >> %d)",
8687 sprintf (s, "#%s", sym->rname);
8688 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8692 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8696 /*-----------------------------------------------------------------*/
8697 /* genFarFarAssign - assignment when both are in far space */
8698 /*-----------------------------------------------------------------*/
8700 genFarFarAssign (operand * result, operand * right, iCode * ic)
8702 int size = AOP_SIZE (right);
8708 /* This is a net loss for size == 1, but a big gain
8711 D (emitcode (";", "genFarFarAssign (improved)");
8714 aopOp (result, ic, TRUE, TRUE);
8716 _startLazyDPSEvaluation ();
8719 aopPut (AOP (result),
8720 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8723 _endLazyDPSEvaluation ();
8724 freeAsmop (result, NULL, ic, FALSE);
8725 freeAsmop (right, NULL, ic, FALSE);
8729 D (emitcode (";", "genFarFarAssign ");
8732 /* first push the right side on to the stack */
8733 _startLazyDPSEvaluation ();
8736 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8738 emitcode ("push", "acc");
8741 freeAsmop (right, NULL, ic, FALSE);
8742 /* now assign DPTR to result */
8743 aopOp (result, ic, FALSE, FALSE);
8744 size = AOP_SIZE (result);
8747 emitcode ("pop", "acc");
8748 aopPut (AOP (result), "a", --offset);
8750 freeAsmop (result, NULL, ic, FALSE);
8751 _endLazyDPSEvaluation ();
8755 /*-----------------------------------------------------------------*/
8756 /* genAssign - generate code for assignment */
8757 /*-----------------------------------------------------------------*/
8759 genAssign (iCode * ic)
8761 operand *result, *right;
8763 unsigned long lit = 0L;
8765 D (emitcode (";", "genAssign ");
8768 result = IC_RESULT (ic);
8769 right = IC_RIGHT (ic);
8771 /* if they are the same */
8772 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8775 aopOp (right, ic, FALSE, FALSE);
8777 emitcode (";", "genAssign: resultIsFar = %s",
8778 isOperandInFarSpace (result) ?
8781 /* special case both in far space */
8782 if ((AOP_TYPE (right) == AOP_DPTR ||
8783 AOP_TYPE (right) == AOP_DPTR2) &&
8784 /* IS_TRUE_SYMOP(result) && */
8785 isOperandInFarSpace (result))
8787 genFarFarAssign (result, right, ic);
8791 aopOp (result, ic, TRUE, FALSE);
8793 /* if they are the same registers */
8794 if (sameRegs (AOP (right), AOP (result)))
8797 /* if the result is a bit */
8798 if (AOP_TYPE (result) == AOP_CRY)
8801 /* if the right size is a literal then
8802 we know what the value is */
8803 if (AOP_TYPE (right) == AOP_LIT)
8805 if (((int) operandLitValue (right)))
8806 aopPut (AOP (result), one, 0);
8808 aopPut (AOP (result), zero, 0);
8812 /* the right is also a bit variable */
8813 if (AOP_TYPE (right) == AOP_CRY)
8815 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8816 aopPut (AOP (result), "c", 0);
8822 aopPut (AOP (result), "a", 0);
8826 /* bit variables done */
8828 size = AOP_SIZE (result);
8830 if (AOP_TYPE (right) == AOP_LIT)
8831 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8834 (AOP_TYPE (result) != AOP_REG) &&
8835 (AOP_TYPE (right) == AOP_LIT) &&
8836 !IS_FLOAT (operandType (right)))
8838 D (emitcode (";", "Kevin's better literal load code");
8840 _startLazyDPSEvaluation ();
8841 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8843 aopPut (AOP (result),
8844 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8849 /* And now fill the rest with zeros. */
8852 emitcode ("clr", "a");
8856 aopPut (AOP (result), "a", offset++);
8858 _endLazyDPSEvaluation ();
8862 _startLazyDPSEvaluation ();
8865 aopPut (AOP (result),
8866 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8870 _endLazyDPSEvaluation ();
8874 freeAsmop (right, NULL, ic, FALSE);
8875 freeAsmop (result, NULL, ic, TRUE);
8878 /*-----------------------------------------------------------------*/
8879 /* genJumpTab - generates code for jump table */
8880 /*-----------------------------------------------------------------*/
8882 genJumpTab (iCode * ic)
8887 D (emitcode (";", "genJumpTab ");
8890 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8891 /* get the condition into accumulator */
8892 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8894 /* multiply by four! */
8895 emitcode ("add", "a,acc");
8896 emitcode ("add", "a,acc");
8897 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8899 jtab = newiTempLabel (NULL);
8900 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8901 emitcode ("jmp", "@a+dptr");
8902 emitcode ("", "%05d$:", jtab->key + 100);
8903 /* now generate the jump labels */
8904 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8905 jtab = setNextItem (IC_JTLABELS (ic)))
8906 emitcode ("ljmp", "%05d$", jtab->key + 100);
8910 /*-----------------------------------------------------------------*/
8911 /* genCast - gen code for casting */
8912 /*-----------------------------------------------------------------*/
8914 genCast (iCode * ic)
8916 operand *result = IC_RESULT (ic);
8917 sym_link *ctype = operandType (IC_LEFT (ic));
8918 sym_link *rtype = operandType (IC_RIGHT (ic));
8919 operand *right = IC_RIGHT (ic);
8922 D (emitcode (";", "genCast ");
8925 /* if they are equivalent then do nothing */
8926 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8929 aopOp (right, ic, FALSE, FALSE);
8930 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8932 /* if the result is a bit */
8933 if (AOP_TYPE (result) == AOP_CRY)
8935 /* if the right size is a literal then
8936 we know what the value is */
8937 if (AOP_TYPE (right) == AOP_LIT)
8939 if (((int) operandLitValue (right)))
8940 aopPut (AOP (result), one, 0);
8942 aopPut (AOP (result), zero, 0);
8947 /* the right is also a bit variable */
8948 if (AOP_TYPE (right) == AOP_CRY)
8950 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8951 aopPut (AOP (result), "c", 0);
8957 aopPut (AOP (result), "a", 0);
8961 /* if they are the same size : or less */
8962 if (AOP_SIZE (result) <= AOP_SIZE (right))
8965 /* if they are in the same place */
8966 if (sameRegs (AOP (right), AOP (result)))
8969 /* if they in different places then copy */
8970 size = AOP_SIZE (result);
8972 _startLazyDPSEvaluation ();
8975 aopPut (AOP (result),
8976 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8980 _endLazyDPSEvaluation ();
8985 /* if the result is of type pointer */
8990 sym_link *type = operandType (right);
8992 /* pointer to generic pointer */
8993 if (IS_GENPTR (ctype))
8999 p_type = DCL_TYPE (type);
9003 #if OLD_CAST_BEHAVIOR
9004 /* KV: we are converting a non-pointer type to
9005 * a generic pointer. This (ifdef'd out) code
9006 * says that the resulting generic pointer
9007 * should have the same class as the storage
9008 * location of the non-pointer variable.
9010 * For example, converting an int (which happens
9011 * to be stored in DATA space) to a pointer results
9012 * in a DATA generic pointer; if the original int
9013 * in XDATA space, so will be the resulting pointer.
9015 * I don't like that behavior, and thus this change:
9016 * all such conversions will be forced to XDATA and
9017 * throw a warning. If you want some non-XDATA
9018 * type, or you want to suppress the warning, you
9019 * must go through an intermediate cast, like so:
9021 * char _generic *gp = (char _xdata *)(intVar);
9023 sym_link *etype = getSpec (type);
9025 /* we have to go by the storage class */
9026 if (SPEC_OCLS (etype) != generic)
9028 p_type = PTR_TYPE (SPEC_OCLS (etype));
9033 /* Converting unknown class (i.e. register variable)
9034 * to generic pointer. This is not good, but
9035 * we'll make a guess (and throw a warning).
9038 werror (W_INT_TO_GEN_PTR_CAST);
9042 /* the first two bytes are known */
9043 size = GPTRSIZE - 1;
9045 _startLazyDPSEvaluation ();
9048 aopPut (AOP (result),
9049 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9053 _endLazyDPSEvaluation ();
9055 /* the last byte depending on type */
9073 /* this should never happen */
9074 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9075 "got unknown pointer type");
9078 aopPut (AOP (result), l, GPTRSIZE - 1);
9082 /* just copy the pointers */
9083 size = AOP_SIZE (result);
9085 _startLazyDPSEvaluation ();
9088 aopPut (AOP (result),
9089 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9093 _endLazyDPSEvaluation ();
9097 /* so we now know that the size of destination is greater
9098 than the size of the source */
9099 /* we move to result for the size of source */
9100 size = AOP_SIZE (right);
9102 _startLazyDPSEvaluation ();
9105 aopPut (AOP (result),
9106 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9110 _endLazyDPSEvaluation ();
9112 /* now depending on the sign of the source && destination */
9113 size = AOP_SIZE (result) - AOP_SIZE (right);
9114 /* if unsigned or not an integral type */
9115 /* also, if the source is a bit, we don't need to sign extend, because
9116 * it can't possibly have set the sign bit.
9118 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9122 aopPut (AOP (result), zero, offset++);
9127 /* we need to extend the sign :{ */
9128 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9129 FALSE, FALSE, TRUE);
9131 emitcode ("rlc", "a");
9132 emitcode ("subb", "a,acc");
9134 aopPut (AOP (result), "a", offset++);
9137 /* we are done hurray !!!! */
9140 freeAsmop (right, NULL, ic, TRUE);
9141 freeAsmop (result, NULL, ic, TRUE);
9145 /*-----------------------------------------------------------------*/
9146 /* genDjnz - generate decrement & jump if not zero instrucion */
9147 /*-----------------------------------------------------------------*/
9149 genDjnz (iCode * ic, iCode * ifx)
9155 /* if the if condition has a false label
9156 then we cannot save */
9160 /* if the minus is not of the form
9162 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9163 !IS_OP_LITERAL (IC_RIGHT (ic)))
9166 if (operandLitValue (IC_RIGHT (ic)) != 1)
9169 /* if the size of this greater than one then no
9171 if (getSize (operandType (IC_RESULT (ic))) > 1)
9174 /* otherwise we can save BIG */
9175 lbl = newiTempLabel (NULL);
9176 lbl1 = newiTempLabel (NULL);
9178 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9180 if (IS_AOP_PREG (IC_RESULT (ic)))
9182 emitcode ("dec", "%s",
9183 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9184 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9185 emitcode ("jnz", "%05d$", lbl->key + 100);
9189 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9192 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9193 emitcode ("", "%05d$:", lbl->key + 100);
9194 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9195 emitcode ("", "%05d$:", lbl1->key + 100);
9197 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9202 /*-----------------------------------------------------------------*/
9203 /* genReceive - generate code for a receive iCode */
9204 /*-----------------------------------------------------------------*/
9206 genReceive (iCode * ic)
9209 D (emitcode (";", "genReceive ");
9212 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9213 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9214 IS_TRUE_SYMOP (IC_RESULT (ic))))
9216 int size = getSize (operandType (IC_RESULT (ic)));
9217 int offset = fReturnSizeDS390 - size;
9220 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9221 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9224 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9225 size = AOP_SIZE (IC_RESULT (ic));
9229 emitcode ("pop", "acc");
9230 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9237 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9239 assignResultValue (IC_RESULT (ic));
9242 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9245 /*-----------------------------------------------------------------*/
9246 /* gen390Code - generate code for Dallas 390 based controllers */
9247 /*-----------------------------------------------------------------*/
9249 gen390Code (iCode * lic)
9254 lineHead = lineCurr = NULL;
9258 /* print the allocation information */
9260 printAllocInfo (currFunc, codeOutFile);
9262 /* if debug information required */
9263 if (options.debug && currFunc)
9265 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9267 if (IS_STATIC (currFunc->etype))
9268 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9270 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9273 /* stack pointer name */
9274 if (options.useXstack)
9280 for (ic = lic; ic; ic = ic->next)
9283 if (cln != ic->lineno)
9288 emitcode ("", "C$%s$%d$%d$%d ==.",
9289 FileBaseName (ic->filename), ic->lineno,
9290 ic->level, ic->block);
9293 emitcode (";", "%s %d", ic->filename, ic->lineno);
9296 /* if the result is marked as
9297 spilt and rematerializable or code for
9298 this has already been generated then
9300 if (resultRemat (ic) || ic->generated)
9303 /* depending on the operation */
9323 /* IPOP happens only when trying to restore a
9324 spilt live range, if there is an ifx statement
9325 following this pop then the if statement might
9326 be using some of the registers being popped which
9327 would destory the contents of the register so
9328 we need to check for this condition and handle it */
9330 ic->next->op == IFX &&
9331 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9332 genIfx (ic->next, ic);
9350 genEndFunction (ic);
9370 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9387 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9391 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9398 /* note these two are xlated by algebraic equivalence
9399 during parsing SDCC.y */
9400 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9401 "got '>=' or '<=' shouldn't have come here");
9405 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9417 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9421 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9425 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9452 case GET_VALUE_AT_ADDRESS:
9457 if (POINTER_SET (ic))
9484 addSet (&_G.sendSet, ic);
9489 /* piCode(ic,stdout); */
9495 /* now we are ready to call the
9496 peep hole optimizer */
9497 if (!options.nopeep)
9498 peepHole (&lineHead);
9500 /* now do the actual printing */
9501 printLine (lineHead, codeOutFile);