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
3773 emitcode ("inc", "a");
3775 emitcode ("xch", "a,b");
3776 emitcode ("cpl", "a"); // msb
3777 emitcode ("addc", "a,#0");
3778 emitcode ("xch", "a,b");
3781 emitcode ("", "%05d$:", lbl->key+100);
3782 aopPut (AOP (result), "a", 0);
3784 aopPut (AOP (result), "b", 1);
3788 /*-----------------------------------------------------------------*/
3789 /* genMult - generates code for multiplication */
3790 /*-----------------------------------------------------------------*/
3792 genMult (iCode * ic)
3794 operand *left = IC_LEFT (ic);
3795 operand *right = IC_RIGHT (ic);
3796 operand *result = IC_RESULT (ic);
3798 D (emitcode (";", "genMult ");
3801 /* assign the amsops */
3804 /* special cases first */
3806 if (AOP_TYPE (left) == AOP_CRY &&
3807 AOP_TYPE (right) == AOP_CRY)
3809 genMultbits (left, right, result);
3813 /* if both are of size == 1 */
3814 if (AOP_SIZE (left) == 1 &&
3815 AOP_SIZE (right) == 1)
3817 genMultOneByte (left, right, result);
3821 /* should have been converted to function call */
3825 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3826 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3827 freeAsmop (result, NULL, ic, TRUE);
3830 /*-----------------------------------------------------------------*/
3831 /* genDivbits :- division of bits */
3832 /*-----------------------------------------------------------------*/
3834 genDivbits (operand * left,
3841 /* the result must be bit */
3842 LOAD_AB_FOR_DIV (left, right, l);
3843 emitcode ("div", "ab");
3844 emitcode ("rrc", "a");
3845 aopPut (AOP (result), "c", 0);
3848 /*-----------------------------------------------------------------*/
3849 /* genDivOneByte : 8 bit division */
3850 /*-----------------------------------------------------------------*/
3852 genDivOneByte (operand * left,
3856 sym_link *opetype = operandType (result);
3861 size = AOP_SIZE (result) - 1;
3863 /* signed or unsigned */
3864 if (SPEC_USIGN (opetype))
3866 /* unsigned is easy */
3867 LOAD_AB_FOR_DIV (left, right, l);
3868 emitcode ("div", "ab");
3869 aopPut (AOP (result), "a", 0);
3871 aopPut (AOP (result), zero, offset++);
3875 /* signed is a little bit more difficult */
3877 /* save the signs of the operands */
3878 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3880 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3881 emitcode ("push", "acc"); /* save it on the stack */
3883 /* now sign adjust for both left & right */
3884 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3886 lbl = newiTempLabel (NULL);
3887 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3888 emitcode ("cpl", "a");
3889 emitcode ("inc", "a");
3890 emitcode ("", "%05d$:", (lbl->key + 100));
3891 emitcode ("mov", "b,a");
3893 /* sign adjust left side */
3894 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3897 lbl = newiTempLabel (NULL);
3898 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3899 emitcode ("cpl", "a");
3900 emitcode ("inc", "a");
3901 emitcode ("", "%05d$:", (lbl->key + 100));
3903 /* now the division */
3904 emitcode ("nop", "; workaround for DS80C390 div bug.");
3905 emitcode ("div", "ab");
3906 /* we are interested in the lower order
3908 emitcode ("mov", "b,a");
3909 lbl = newiTempLabel (NULL);
3910 emitcode ("pop", "acc");
3911 /* if there was an over flow we don't
3912 adjust the sign of the result */
3913 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3914 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3916 emitcode ("clr", "a");
3917 emitcode ("subb", "a,b");
3918 emitcode ("mov", "b,a");
3919 emitcode ("", "%05d$:", (lbl->key + 100));
3921 /* now we are done */
3922 aopPut (AOP (result), "b", 0);
3925 emitcode ("mov", "c,b.7");
3926 emitcode ("subb", "a,acc");
3929 aopPut (AOP (result), "a", offset++);
3933 /*-----------------------------------------------------------------*/
3934 /* genDiv - generates code for division */
3935 /*-----------------------------------------------------------------*/
3939 operand *left = IC_LEFT (ic);
3940 operand *right = IC_RIGHT (ic);
3941 operand *result = IC_RESULT (ic);
3943 D (emitcode (";", "genDiv ");
3946 /* assign the amsops */
3949 /* special cases first */
3951 if (AOP_TYPE (left) == AOP_CRY &&
3952 AOP_TYPE (right) == AOP_CRY)
3954 genDivbits (left, right, result);
3958 /* if both are of size == 1 */
3959 if (AOP_SIZE (left) == 1 &&
3960 AOP_SIZE (right) == 1)
3962 genDivOneByte (left, right, result);
3966 /* should have been converted to function call */
3969 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3970 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3971 freeAsmop (result, NULL, ic, TRUE);
3974 /*-----------------------------------------------------------------*/
3975 /* genModbits :- modulus of bits */
3976 /*-----------------------------------------------------------------*/
3978 genModbits (operand * left,
3985 /* the result must be bit */
3986 LOAD_AB_FOR_DIV (left, right, l);
3987 emitcode ("div", "ab");
3988 emitcode ("mov", "a,b");
3989 emitcode ("rrc", "a");
3990 aopPut (AOP (result), "c", 0);
3993 /*-----------------------------------------------------------------*/
3994 /* genModOneByte : 8 bit modulus */
3995 /*-----------------------------------------------------------------*/
3997 genModOneByte (operand * left,
4001 sym_link *opetype = operandType (result);
4005 /* signed or unsigned */
4006 if (SPEC_USIGN (opetype))
4008 /* unsigned is easy */
4009 LOAD_AB_FOR_DIV (left, right, l);
4010 emitcode ("div", "ab");
4011 aopPut (AOP (result), "b", 0);
4015 /* signed is a little bit more difficult */
4017 /* save the signs of the operands */
4018 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4021 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4022 emitcode ("push", "acc"); /* save it on the stack */
4024 /* now sign adjust for both left & right */
4025 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4028 lbl = newiTempLabel (NULL);
4029 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4030 emitcode ("cpl", "a");
4031 emitcode ("inc", "a");
4032 emitcode ("", "%05d$:", (lbl->key + 100));
4033 emitcode ("mov", "b,a");
4035 /* sign adjust left side */
4036 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4039 lbl = newiTempLabel (NULL);
4040 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4041 emitcode ("cpl", "a");
4042 emitcode ("inc", "a");
4043 emitcode ("", "%05d$:", (lbl->key + 100));
4045 /* now the multiplication */
4046 emitcode ("nop", "; workaround for DS80C390 div bug.");
4047 emitcode ("div", "ab");
4048 /* we are interested in the lower order
4050 lbl = newiTempLabel (NULL);
4051 emitcode ("pop", "acc");
4052 /* if there was an over flow we don't
4053 adjust the sign of the result */
4054 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4055 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4057 emitcode ("clr", "a");
4058 emitcode ("subb", "a,b");
4059 emitcode ("mov", "b,a");
4060 emitcode ("", "%05d$:", (lbl->key + 100));
4062 /* now we are done */
4063 aopPut (AOP (result), "b", 0);
4067 /*-----------------------------------------------------------------*/
4068 /* genMod - generates code for division */
4069 /*-----------------------------------------------------------------*/
4073 operand *left = IC_LEFT (ic);
4074 operand *right = IC_RIGHT (ic);
4075 operand *result = IC_RESULT (ic);
4077 D (emitcode (";", "genMod ");
4080 /* assign the amsops */
4083 /* special cases first */
4085 if (AOP_TYPE (left) == AOP_CRY &&
4086 AOP_TYPE (right) == AOP_CRY)
4088 genModbits (left, right, result);
4092 /* if both are of size == 1 */
4093 if (AOP_SIZE (left) == 1 &&
4094 AOP_SIZE (right) == 1)
4096 genModOneByte (left, right, result);
4100 /* should have been converted to function call */
4104 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4105 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4106 freeAsmop (result, NULL, ic, TRUE);
4109 /*-----------------------------------------------------------------*/
4110 /* genIfxJump :- will create a jump depending on the ifx */
4111 /*-----------------------------------------------------------------*/
4113 genIfxJump (iCode * ic, char *jval)
4116 symbol *tlbl = newiTempLabel (NULL);
4119 D (emitcode (";", "genIfxJump ");
4122 /* if true label then we jump if condition
4126 jlbl = IC_TRUE (ic);
4127 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4128 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4132 /* false label is present */
4133 jlbl = IC_FALSE (ic);
4134 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4135 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4137 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4138 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4140 emitcode (inst, "%05d$", tlbl->key + 100);
4141 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4142 emitcode ("", "%05d$:", tlbl->key + 100);
4144 /* mark the icode as generated */
4148 /*-----------------------------------------------------------------*/
4149 /* genCmp :- greater or less than comparison */
4150 /*-----------------------------------------------------------------*/
4152 genCmp (operand * left, operand * right,
4153 iCode * ic, iCode * ifx, int sign)
4155 int size, offset = 0;
4156 unsigned long lit = 0L;
4159 D (emitcode (";", "genCmp");
4162 result = IC_RESULT (ic);
4164 /* if left & right are bit variables */
4165 if (AOP_TYPE (left) == AOP_CRY &&
4166 AOP_TYPE (right) == AOP_CRY)
4168 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4169 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4173 /* subtract right from left if at the
4174 end the carry flag is set then we know that
4175 left is greater than right */
4176 size = max (AOP_SIZE (left), AOP_SIZE (right));
4178 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4179 if ((size == 1) && !sign &&
4180 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4182 symbol *lbl = newiTempLabel (NULL);
4183 emitcode ("cjne", "%s,%s,%05d$",
4184 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4185 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4187 emitcode ("", "%05d$:", lbl->key + 100);
4191 if (AOP_TYPE (right) == AOP_LIT)
4193 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4194 /* optimize if(x < 0) or if(x >= 0) */
4203 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4205 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4206 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4208 aopOp (result, ic, FALSE, FALSE);
4210 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4212 freeAsmop (result, NULL, ic, TRUE);
4213 genIfxJump (ifx, "acc.7");
4218 emitcode ("rlc", "a");
4220 goto release_freedLR;
4228 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4229 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4230 emitcode (";", "genCmp #2");
4231 if (sign && (size == 0))
4233 emitcode (";", "genCmp #3");
4234 emitcode ("xrl", "a,#0x80");
4235 if (AOP_TYPE (right) == AOP_LIT)
4237 unsigned long lit = (unsigned long)
4238 floatFromVal (AOP (right)->aopu.aop_lit);
4239 emitcode (";", "genCmp #3.1");
4240 emitcode ("subb", "a,#0x%02x",
4241 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4245 emitcode (";", "genCmp #3.2");
4246 if (AOP_NEEDSACC (right))
4248 emitcode ("push", "acc");
4250 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4251 FALSE, FALSE, FALSE));
4252 emitcode ("xrl", "b,#0x80");
4253 if (AOP_NEEDSACC (right))
4255 emitcode ("pop", "acc");
4257 emitcode ("subb", "a,b");
4264 emitcode (";", "genCmp #4");
4265 if (AOP_NEEDSACC (right))
4268 emitcode (";", "genCmp #4.1");
4269 emitcode ("xch", "a, b");
4270 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4271 emitcode ("xch", "a, b");
4276 emitcode (";", "genCmp #4.2");
4277 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4280 emitcode ("subb", "a,%s", s);
4287 /* Don't need the left & right operands any more; do need the result. */
4288 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4289 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4291 aopOp (result, ic, FALSE, FALSE);
4295 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4301 /* if the result is used in the next
4302 ifx conditional branch then generate
4303 code a little differently */
4306 genIfxJump (ifx, "c");
4312 /* leave the result in acc */
4314 freeAsmop (result, NULL, ic, TRUE);
4317 /*-----------------------------------------------------------------*/
4318 /* genCmpGt :- greater than comparison */
4319 /*-----------------------------------------------------------------*/
4321 genCmpGt (iCode * ic, iCode * ifx)
4323 operand *left, *right;
4324 sym_link *letype, *retype;
4327 D (emitcode (";", "genCmpGt ");
4330 left = IC_LEFT (ic);
4331 right = IC_RIGHT (ic);
4333 letype = getSpec (operandType (left));
4334 retype = getSpec (operandType (right));
4335 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4337 /* assign the left & right amsops */
4340 genCmp (right, left, ic, ifx, sign);
4343 /*-----------------------------------------------------------------*/
4344 /* genCmpLt - less than comparisons */
4345 /*-----------------------------------------------------------------*/
4347 genCmpLt (iCode * ic, iCode * ifx)
4349 operand *left, *right;
4350 sym_link *letype, *retype;
4353 D (emitcode (";", "genCmpLt ");
4356 left = IC_LEFT (ic);
4357 right = IC_RIGHT (ic);
4359 letype = getSpec (operandType (left));
4360 retype = getSpec (operandType (right));
4361 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4363 /* assign the left & right amsops */
4366 genCmp (left, right, ic, ifx, sign);
4369 /*-----------------------------------------------------------------*/
4370 /* gencjneshort - compare and jump if not equal */
4371 /*-----------------------------------------------------------------*/
4373 gencjneshort (operand * left, operand * right, symbol * lbl)
4375 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4377 unsigned long lit = 0L;
4379 D (emitcode (";", "gencjneshort");
4382 /* if the left side is a literal or
4383 if the right is in a pointer register and left
4385 if ((AOP_TYPE (left) == AOP_LIT) ||
4386 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4393 if (AOP_TYPE (right) == AOP_LIT)
4394 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4396 if (opIsGptr (left) || opIsGptr (right))
4398 /* We are comparing a generic pointer to something.
4399 * Exclude the generic type byte from the comparison.
4402 D (emitcode (";", "cjneshort: generic ptr special case.");
4407 /* if the right side is a literal then anything goes */
4408 if (AOP_TYPE (right) == AOP_LIT &&
4409 AOP_TYPE (left) != AOP_DIR)
4413 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4415 emitcode ("cjne", "a,%s,%05d$",
4416 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4422 /* if the right side is in a register or in direct space or
4423 if the left is a pointer register & right is not */
4424 else if (AOP_TYPE (right) == AOP_REG ||
4425 AOP_TYPE (right) == AOP_DIR ||
4426 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4427 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4431 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4432 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4433 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4434 emitcode ("jnz", "%05d$", lbl->key + 100);
4436 emitcode ("cjne", "a,%s,%05d$",
4437 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4444 /* right is a pointer reg need both a & b */
4447 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4448 if (strcmp (l, "b"))
4449 emitcode ("mov", "b,%s", l);
4450 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4451 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4457 /*-----------------------------------------------------------------*/
4458 /* gencjne - compare and jump if not equal */
4459 /*-----------------------------------------------------------------*/
4461 gencjne (operand * left, operand * right, symbol * lbl)
4463 symbol *tlbl = newiTempLabel (NULL);
4465 D (emitcode (";", "gencjne");
4468 gencjneshort (left, right, lbl);
4470 emitcode ("mov", "a,%s", one);
4471 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4472 emitcode ("", "%05d$:", lbl->key + 100);
4473 emitcode ("clr", "a");
4474 emitcode ("", "%05d$:", tlbl->key + 100);
4477 /*-----------------------------------------------------------------*/
4478 /* genCmpEq - generates code for equal to */
4479 /*-----------------------------------------------------------------*/
4481 genCmpEq (iCode * ic, iCode * ifx)
4483 operand *left, *right, *result;
4485 D (emitcode (";", "genCmpEq ");
4489 AOP_SET_LOCALS (ic);
4491 /* if literal, literal on the right or
4492 if the right is in a pointer register and left
4494 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4495 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4497 operand *t = IC_RIGHT (ic);
4498 IC_RIGHT (ic) = IC_LEFT (ic);
4502 if (ifx && /* !AOP_SIZE(result) */
4503 OP_SYMBOL (result) &&
4504 OP_SYMBOL (result)->regType == REG_CND)
4507 /* if they are both bit variables */
4508 if (AOP_TYPE (left) == AOP_CRY &&
4509 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4511 if (AOP_TYPE (right) == AOP_LIT)
4513 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4516 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4517 emitcode ("cpl", "c");
4521 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4525 emitcode ("clr", "c");
4527 /* AOP_TYPE(right) == AOP_CRY */
4531 symbol *lbl = newiTempLabel (NULL);
4532 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4533 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4534 emitcode ("cpl", "c");
4535 emitcode ("", "%05d$:", (lbl->key + 100));
4537 /* if true label then we jump if condition
4539 tlbl = newiTempLabel (NULL);
4542 emitcode ("jnc", "%05d$", tlbl->key + 100);
4543 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4547 emitcode ("jc", "%05d$", tlbl->key + 100);
4548 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4550 emitcode ("", "%05d$:", tlbl->key + 100);
4554 tlbl = newiTempLabel (NULL);
4555 gencjneshort (left, right, tlbl);
4558 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4559 emitcode ("", "%05d$:", tlbl->key + 100);
4563 symbol *lbl = newiTempLabel (NULL);
4564 emitcode ("sjmp", "%05d$", lbl->key + 100);
4565 emitcode ("", "%05d$:", tlbl->key + 100);
4566 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4567 emitcode ("", "%05d$:", lbl->key + 100);
4570 /* mark the icode as generated */
4573 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4574 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 /* if they are both bit variables */
4579 if (AOP_TYPE (left) == AOP_CRY &&
4580 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4582 if (AOP_TYPE (right) == AOP_LIT)
4584 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4588 emitcode ("cpl", "c");
4592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4596 emitcode ("clr", "c");
4598 /* AOP_TYPE(right) == AOP_CRY */
4602 symbol *lbl = newiTempLabel (NULL);
4603 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4604 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4605 emitcode ("cpl", "c");
4606 emitcode ("", "%05d$:", (lbl->key + 100));
4609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612 aopOp (result, ic, TRUE, FALSE);
4615 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4622 genIfxJump (ifx, "c");
4625 /* if the result is used in an arithmetic operation
4626 then put the result in place */
4631 gencjne (left, right, newiTempLabel (NULL));
4633 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4634 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 aopOp (result, ic, TRUE, FALSE);
4638 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4640 aopPut (AOP (result), "a", 0);
4645 genIfxJump (ifx, "a");
4648 /* if the result is used in an arithmetic operation
4649 then put the result in place */
4650 if (AOP_TYPE (result) != AOP_CRY)
4652 /* leave the result in acc */
4656 freeAsmop (result, NULL, ic, TRUE);
4659 /*-----------------------------------------------------------------*/
4660 /* ifxForOp - returns the icode containing the ifx for operand */
4661 /*-----------------------------------------------------------------*/
4663 ifxForOp (operand * op, iCode * ic)
4665 /* if true symbol then needs to be assigned */
4666 if (IS_TRUE_SYMOP (op))
4669 /* if this has register type condition and
4670 the next instruction is ifx with the same operand
4671 and live to of the operand is upto the ifx only then */
4673 ic->next->op == IFX &&
4674 IC_COND (ic->next)->key == op->key &&
4675 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4680 /*-----------------------------------------------------------------*/
4681 /* genAndOp - for && operation */
4682 /*-----------------------------------------------------------------*/
4684 genAndOp (iCode * ic)
4686 operand *left, *right, *result;
4689 D (emitcode (";", "genAndOp ");
4692 /* note here that && operations that are in an
4693 if statement are taken away by backPatchLabels
4694 only those used in arthmetic operations remain */
4696 AOP_SET_LOCALS (ic);
4698 /* if both are bit variables */
4699 if (AOP_TYPE (left) == AOP_CRY &&
4700 AOP_TYPE (right) == AOP_CRY)
4702 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4703 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4708 tlbl = newiTempLabel (NULL);
4710 emitcode ("jz", "%05d$", tlbl->key + 100);
4712 emitcode ("", "%05d$:", tlbl->key + 100);
4716 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4717 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4718 freeAsmop (result, NULL, ic, TRUE);
4722 /*-----------------------------------------------------------------*/
4723 /* genOrOp - for || operation */
4724 /*-----------------------------------------------------------------*/
4726 genOrOp (iCode * ic)
4728 operand *left, *right, *result;
4731 D (emitcode (";", "genOrOp ");
4734 /* note here that || operations that are in an
4735 if statement are taken away by backPatchLabels
4736 only those used in arthmetic operations remain */
4738 AOP_SET_LOCALS (ic);
4740 /* if both are bit variables */
4741 if (AOP_TYPE (left) == AOP_CRY &&
4742 AOP_TYPE (right) == AOP_CRY)
4744 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4745 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4750 tlbl = newiTempLabel (NULL);
4752 emitcode ("jnz", "%05d$", tlbl->key + 100);
4754 emitcode ("", "%05d$:", tlbl->key + 100);
4758 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4759 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4760 freeAsmop (result, NULL, ic, TRUE);
4763 /*-----------------------------------------------------------------*/
4764 /* isLiteralBit - test if lit == 2^n */
4765 /*-----------------------------------------------------------------*/
4767 isLiteralBit (unsigned long lit)
4769 unsigned long pw[32] =
4770 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4771 0x100L, 0x200L, 0x400L, 0x800L,
4772 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4773 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4774 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4775 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4776 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4779 for (idx = 0; idx < 32; idx++)
4785 /*-----------------------------------------------------------------*/
4786 /* continueIfTrue - */
4787 /*-----------------------------------------------------------------*/
4789 continueIfTrue (iCode * ic)
4792 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4796 /*-----------------------------------------------------------------*/
4798 /*-----------------------------------------------------------------*/
4800 jumpIfTrue (iCode * ic)
4803 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4807 /*-----------------------------------------------------------------*/
4808 /* jmpTrueOrFalse - */
4809 /*-----------------------------------------------------------------*/
4811 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4813 // ugly but optimized by peephole
4816 symbol *nlbl = newiTempLabel (NULL);
4817 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4818 emitcode ("", "%05d$:", tlbl->key + 100);
4819 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4820 emitcode ("", "%05d$:", nlbl->key + 100);
4824 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4825 emitcode ("", "%05d$:", tlbl->key + 100);
4830 /*-----------------------------------------------------------------*/
4831 /* genAnd - code for and */
4832 /*-----------------------------------------------------------------*/
4834 genAnd (iCode * ic, iCode * ifx)
4836 operand *left, *right, *result;
4837 int size, offset = 0;
4838 unsigned long lit = 0L;
4842 D (emitcode (";", "genAnd ");
4846 AOP_SET_LOCALS (ic);
4849 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4851 AOP_TYPE (left), AOP_TYPE (right));
4852 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4854 AOP_SIZE (left), AOP_SIZE (right));
4857 /* if left is a literal & right is not then exchange them */
4858 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4859 AOP_NEEDSACC (left))
4861 operand *tmp = right;
4866 /* if result = right then exchange them */
4867 if (sameRegs (AOP (result), AOP (right)))
4869 operand *tmp = right;
4874 /* if right is bit then exchange them */
4875 if (AOP_TYPE (right) == AOP_CRY &&
4876 AOP_TYPE (left) != AOP_CRY)
4878 operand *tmp = right;
4882 if (AOP_TYPE (right) == AOP_LIT)
4883 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4885 size = AOP_SIZE (result);
4888 // result = bit & yy;
4889 if (AOP_TYPE (left) == AOP_CRY)
4891 // c = bit & literal;
4892 if (AOP_TYPE (right) == AOP_LIT)
4896 if (size && sameRegs (AOP (result), AOP (left)))
4899 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4904 if (size && (AOP_TYPE (result) == AOP_CRY))
4906 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4909 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4914 emitcode ("clr", "c");
4919 if (AOP_TYPE (right) == AOP_CRY)
4922 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4923 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4928 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4930 emitcode ("rrc", "a");
4931 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4939 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4940 genIfxJump (ifx, "c");
4944 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4945 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4946 if ((AOP_TYPE (right) == AOP_LIT) &&
4947 (AOP_TYPE (result) == AOP_CRY) &&
4948 (AOP_TYPE (left) != AOP_CRY))
4950 int posbit = isLiteralBit (lit);
4955 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4958 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4964 sprintf (buffer, "acc.%d", posbit & 0x07);
4965 genIfxJump (ifx, buffer);
4972 symbol *tlbl = newiTempLabel (NULL);
4973 int sizel = AOP_SIZE (left);
4975 emitcode ("setb", "c");
4978 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4980 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4982 if ((posbit = isLiteralBit (bytelit)) != 0)
4983 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4986 if (bytelit != 0x0FFL)
4987 emitcode ("anl", "a,%s",
4988 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4989 emitcode ("jnz", "%05d$", tlbl->key + 100);
4994 // bit = left & literal
4997 emitcode ("clr", "c");
4998 emitcode ("", "%05d$:", tlbl->key + 100);
5000 // if(left & literal)
5004 jmpTrueOrFalse (ifx, tlbl);
5012 /* if left is same as result */
5013 if (sameRegs (AOP (result), AOP (left)))
5015 for (; size--; offset++)
5017 if (AOP_TYPE (right) == AOP_LIT)
5019 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5021 else if (bytelit == 0)
5022 aopPut (AOP (result), zero, offset);
5023 else if (IS_AOP_PREG (result))
5025 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5026 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5027 aopPut (AOP (result), "a", offset);
5030 emitcode ("anl", "%s,%s",
5031 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5032 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5036 if (AOP_TYPE (left) == AOP_ACC)
5037 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5040 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5041 if (IS_AOP_PREG (result))
5043 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5044 aopPut (AOP (result), "a", offset);
5048 emitcode ("anl", "%s,a",
5049 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5056 // left & result in different registers
5057 if (AOP_TYPE (result) == AOP_CRY)
5060 // if(size), result in bit
5061 // if(!size && ifx), conditional oper: if(left & right)
5062 symbol *tlbl = newiTempLabel (NULL);
5063 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5065 emitcode ("setb", "c");
5068 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5069 emitcode ("anl", "a,%s",
5070 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5071 emitcode ("jnz", "%05d$", tlbl->key + 100);
5077 emitcode ("", "%05d$:", tlbl->key + 100);
5081 jmpTrueOrFalse (ifx, tlbl);
5085 for (; (size--); offset++)
5088 // result = left & right
5089 if (AOP_TYPE (right) == AOP_LIT)
5091 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5093 aopPut (AOP (result),
5094 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5098 else if (bytelit == 0)
5100 aopPut (AOP (result), zero, offset);
5103 D (emitcode (";", "better literal AND.");
5105 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5106 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5107 FALSE, FALSE, FALSE));
5112 // faster than result <- left, anl result,right
5113 // and better if result is SFR
5114 if (AOP_TYPE (left) == AOP_ACC)
5116 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5117 FALSE, FALSE, FALSE));
5121 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5122 emitcode ("anl", "a,%s",
5123 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5126 aopPut (AOP (result), "a", offset);
5132 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5133 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134 freeAsmop (result, NULL, ic, TRUE);
5137 /*-----------------------------------------------------------------*/
5138 /* genOr - code for or */
5139 /*-----------------------------------------------------------------*/
5141 genOr (iCode * ic, iCode * ifx)
5143 operand *left, *right, *result;
5144 int size, offset = 0;
5145 unsigned long lit = 0L;
5147 D (emitcode (";", "genOr ");
5151 AOP_SET_LOCALS (ic);
5154 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5156 AOP_TYPE (left), AOP_TYPE (right));
5157 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5159 AOP_SIZE (left), AOP_SIZE (right));
5162 /* if left is a literal & right is not then exchange them */
5163 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5164 AOP_NEEDSACC (left))
5166 operand *tmp = right;
5171 /* if result = right then exchange them */
5172 if (sameRegs (AOP (result), AOP (right)))
5174 operand *tmp = right;
5179 /* if right is bit then exchange them */
5180 if (AOP_TYPE (right) == AOP_CRY &&
5181 AOP_TYPE (left) != AOP_CRY)
5183 operand *tmp = right;
5187 if (AOP_TYPE (right) == AOP_LIT)
5188 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5190 size = AOP_SIZE (result);
5194 if (AOP_TYPE (left) == AOP_CRY)
5196 if (AOP_TYPE (right) == AOP_LIT)
5198 // c = bit & literal;
5201 // lit != 0 => result = 1
5202 if (AOP_TYPE (result) == AOP_CRY)
5205 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5207 continueIfTrue (ifx);
5210 emitcode ("setb", "c");
5214 // lit == 0 => result = left
5215 if (size && sameRegs (AOP (result), AOP (left)))
5217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5222 if (AOP_TYPE (right) == AOP_CRY)
5225 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5226 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5231 symbol *tlbl = newiTempLabel (NULL);
5232 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5233 emitcode ("setb", "c");
5234 emitcode ("jb", "%s,%05d$",
5235 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5237 emitcode ("jnz", "%05d$", tlbl->key + 100);
5238 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5240 jmpTrueOrFalse (ifx, tlbl);
5246 emitcode ("", "%05d$:", tlbl->key + 100);
5255 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5256 genIfxJump (ifx, "c");
5260 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5261 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5262 if ((AOP_TYPE (right) == AOP_LIT) &&
5263 (AOP_TYPE (result) == AOP_CRY) &&
5264 (AOP_TYPE (left) != AOP_CRY))
5270 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5272 continueIfTrue (ifx);
5277 // lit = 0, result = boolean(left)
5279 emitcode ("setb", "c");
5283 symbol *tlbl = newiTempLabel (NULL);
5284 emitcode ("jnz", "%05d$", tlbl->key + 100);
5286 emitcode ("", "%05d$:", tlbl->key + 100);
5290 genIfxJump (ifx, "a");
5298 /* if left is same as result */
5299 if (sameRegs (AOP (result), AOP (left)))
5301 for (; size--; offset++)
5303 if (AOP_TYPE (right) == AOP_LIT)
5305 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5311 if (IS_AOP_PREG (left))
5313 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5314 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5315 aopPut (AOP (result), "a", offset);
5319 emitcode ("orl", "%s,%s",
5320 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5321 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5327 if (AOP_TYPE (left) == AOP_ACC)
5329 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5334 if (IS_AOP_PREG (left))
5336 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5337 aopPut (AOP (result), "a", offset);
5341 emitcode ("orl", "%s,a",
5342 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5350 // left & result in different registers
5351 if (AOP_TYPE (result) == AOP_CRY)
5354 // if(size), result in bit
5355 // if(!size && ifx), conditional oper: if(left | right)
5356 symbol *tlbl = newiTempLabel (NULL);
5357 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5359 emitcode ("setb", "c");
5362 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5363 emitcode ("orl", "a,%s",
5364 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5365 emitcode ("jnz", "%05d$", tlbl->key + 100);
5371 emitcode ("", "%05d$:", tlbl->key + 100);
5375 jmpTrueOrFalse (ifx, tlbl);
5379 for (; (size--); offset++)
5382 // result = left & right
5383 if (AOP_TYPE (right) == AOP_LIT)
5385 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5387 aopPut (AOP (result),
5388 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5392 D (emitcode (";", "better literal OR.");
5394 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5395 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5396 FALSE, FALSE, FALSE));
5401 // faster than result <- left, anl result,right
5402 // and better if result is SFR
5403 if (AOP_TYPE (left) == AOP_ACC)
5405 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5406 FALSE, FALSE, FALSE));
5410 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5411 emitcode ("orl", "a,%s",
5412 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5415 aopPut (AOP (result), "a", offset);
5421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423 freeAsmop (result, NULL, ic, TRUE);
5426 /*-----------------------------------------------------------------*/
5427 /* genXor - code for xclusive or */
5428 /*-----------------------------------------------------------------*/
5430 genXor (iCode * ic, iCode * ifx)
5432 operand *left, *right, *result;
5433 int size, offset = 0;
5434 unsigned long lit = 0L;
5436 D (emitcode (";", "genXor ");
5440 AOP_SET_LOCALS (ic);
5443 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5445 AOP_TYPE (left), AOP_TYPE (right));
5446 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5448 AOP_SIZE (left), AOP_SIZE (right));
5451 /* if left is a literal & right is not ||
5452 if left needs acc & right does not */
5453 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5454 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5456 operand *tmp = right;
5461 /* if result = right then exchange them */
5462 if (sameRegs (AOP (result), AOP (right)))
5464 operand *tmp = right;
5469 /* if right is bit then exchange them */
5470 if (AOP_TYPE (right) == AOP_CRY &&
5471 AOP_TYPE (left) != AOP_CRY)
5473 operand *tmp = right;
5477 if (AOP_TYPE (right) == AOP_LIT)
5478 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5480 size = AOP_SIZE (result);
5484 if (AOP_TYPE (left) == AOP_CRY)
5486 if (AOP_TYPE (right) == AOP_LIT)
5488 // c = bit & literal;
5491 // lit>>1 != 0 => result = 1
5492 if (AOP_TYPE (result) == AOP_CRY)
5495 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5497 continueIfTrue (ifx);
5500 emitcode ("setb", "c");
5507 // lit == 0, result = left
5508 if (size && sameRegs (AOP (result), AOP (left)))
5510 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5514 // lit == 1, result = not(left)
5515 if (size && sameRegs (AOP (result), AOP (left)))
5517 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5522 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5523 emitcode ("cpl", "c");
5532 symbol *tlbl = newiTempLabel (NULL);
5533 if (AOP_TYPE (right) == AOP_CRY)
5536 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5540 int sizer = AOP_SIZE (right);
5542 // if val>>1 != 0, result = 1
5543 emitcode ("setb", "c");
5546 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5548 // test the msb of the lsb
5549 emitcode ("anl", "a,#0xfe");
5550 emitcode ("jnz", "%05d$", tlbl->key + 100);
5554 emitcode ("rrc", "a");
5556 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5557 emitcode ("cpl", "c");
5558 emitcode ("", "%05d$:", (tlbl->key + 100));
5565 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5566 genIfxJump (ifx, "c");
5570 if (sameRegs (AOP (result), AOP (left)))
5572 /* if left is same as result */
5573 for (; size--; offset++)
5575 if (AOP_TYPE (right) == AOP_LIT)
5577 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5579 else if (IS_AOP_PREG (left))
5581 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5582 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5583 aopPut (AOP (result), "a", offset);
5586 emitcode ("xrl", "%s,%s",
5587 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5588 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5592 if (AOP_TYPE (left) == AOP_ACC)
5593 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5596 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5597 if (IS_AOP_PREG (left))
5599 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5600 aopPut (AOP (result), "a", offset);
5603 emitcode ("xrl", "%s,a",
5604 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5611 // left & result in different registers
5612 if (AOP_TYPE (result) == AOP_CRY)
5615 // if(size), result in bit
5616 // if(!size && ifx), conditional oper: if(left ^ right)
5617 symbol *tlbl = newiTempLabel (NULL);
5618 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5620 emitcode ("setb", "c");
5623 if ((AOP_TYPE (right) == AOP_LIT) &&
5624 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5626 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5630 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5631 emitcode ("xrl", "a,%s",
5632 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5634 emitcode ("jnz", "%05d$", tlbl->key + 100);
5640 emitcode ("", "%05d$:", tlbl->key + 100);
5644 jmpTrueOrFalse (ifx, tlbl);
5647 for (; (size--); offset++)
5650 // result = left & right
5651 if (AOP_TYPE (right) == AOP_LIT)
5653 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5655 aopPut (AOP (result),
5656 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5660 D (emitcode (";", "better literal XOR.");
5662 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5663 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5664 FALSE, FALSE, FALSE));
5668 // faster than result <- left, anl result,right
5669 // and better if result is SFR
5670 if (AOP_TYPE (left) == AOP_ACC)
5672 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5673 FALSE, FALSE, FALSE));
5677 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5678 emitcode ("xrl", "a,%s",
5679 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5682 aopPut (AOP (result), "a", offset);
5687 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5688 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689 freeAsmop (result, NULL, ic, TRUE);
5692 /*-----------------------------------------------------------------*/
5693 /* genInline - write the inline code out */
5694 /*-----------------------------------------------------------------*/
5696 genInline (iCode * ic)
5698 char buffer[MAX_INLINEASM];
5702 D (emitcode (";", "genInline ");
5705 _G.inLine += (!options.asmpeep);
5706 strcpy (buffer, IC_INLINE (ic));
5708 /* emit each line as a code */
5733 /* emitcode("",buffer); */
5734 _G.inLine -= (!options.asmpeep);
5737 /*-----------------------------------------------------------------*/
5738 /* genRRC - rotate right with carry */
5739 /*-----------------------------------------------------------------*/
5743 operand *left, *result;
5744 int size, offset = 0;
5747 D (emitcode (";", "genRRC ");
5750 /* rotate right with carry */
5751 left = IC_LEFT (ic);
5752 result = IC_RESULT (ic);
5753 aopOp (left, ic, FALSE, FALSE);
5754 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5756 /* move it to the result */
5757 size = AOP_SIZE (result);
5761 _startLazyDPSEvaluation ();
5764 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5766 emitcode ("rrc", "a");
5767 if (AOP_SIZE (result) > 1)
5768 aopPut (AOP (result), "a", offset--);
5770 _endLazyDPSEvaluation ();
5772 /* now we need to put the carry into the
5773 highest order byte of the result */
5774 if (AOP_SIZE (result) > 1)
5776 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5779 emitcode ("mov", "acc.7,c");
5780 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5781 freeAsmop (left, NULL, ic, TRUE);
5782 freeAsmop (result, NULL, ic, TRUE);
5785 /*-----------------------------------------------------------------*/
5786 /* genRLC - generate code for rotate left with carry */
5787 /*-----------------------------------------------------------------*/
5791 operand *left, *result;
5792 int size, offset = 0;
5795 D (emitcode (";", "genRLC ");
5798 /* rotate right with carry */
5799 left = IC_LEFT (ic);
5800 result = IC_RESULT (ic);
5801 aopOp (left, ic, FALSE, FALSE);
5802 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5804 /* move it to the result */
5805 size = AOP_SIZE (result);
5809 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5811 emitcode ("add", "a,acc");
5812 if (AOP_SIZE (result) > 1)
5814 aopPut (AOP (result), "a", offset++);
5817 _startLazyDPSEvaluation ();
5820 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5822 emitcode ("rlc", "a");
5823 if (AOP_SIZE (result) > 1)
5824 aopPut (AOP (result), "a", offset++);
5826 _endLazyDPSEvaluation ();
5828 /* now we need to put the carry into the
5829 highest order byte of the result */
5830 if (AOP_SIZE (result) > 1)
5832 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5835 emitcode ("mov", "acc.0,c");
5836 aopPut (AOP (result), "a", 0);
5837 freeAsmop (left, NULL, ic, TRUE);
5838 freeAsmop (result, NULL, ic, TRUE);
5841 /*-----------------------------------------------------------------*/
5842 /* genGetHbit - generates code get highest order bit */
5843 /*-----------------------------------------------------------------*/
5845 genGetHbit (iCode * ic)
5847 operand *left, *result;
5848 left = IC_LEFT (ic);
5849 result = IC_RESULT (ic);
5850 aopOp (left, ic, FALSE, FALSE);
5851 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5853 D (emitcode (";", "genGetHbit ");
5856 /* get the highest order byte into a */
5857 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5858 if (AOP_TYPE (result) == AOP_CRY)
5860 emitcode ("rlc", "a");
5865 emitcode ("rl", "a");
5866 emitcode ("anl", "a,#0x01");
5871 freeAsmop (left, NULL, ic, TRUE);
5872 freeAsmop (result, NULL, ic, TRUE);
5875 /*-----------------------------------------------------------------*/
5876 /* AccRol - rotate left accumulator by known count */
5877 /*-----------------------------------------------------------------*/
5879 AccRol (int shCount)
5881 shCount &= 0x0007; // shCount : 0..7
5888 emitcode ("rl", "a");
5891 emitcode ("rl", "a");
5892 emitcode ("rl", "a");
5895 emitcode ("swap", "a");
5896 emitcode ("rr", "a");
5899 emitcode ("swap", "a");
5902 emitcode ("swap", "a");
5903 emitcode ("rl", "a");
5906 emitcode ("rr", "a");
5907 emitcode ("rr", "a");
5910 emitcode ("rr", "a");
5915 /*-----------------------------------------------------------------*/
5916 /* AccLsh - left shift accumulator by known count */
5917 /*-----------------------------------------------------------------*/
5919 AccLsh (int shCount)
5924 emitcode ("add", "a,acc");
5925 else if (shCount == 2)
5927 emitcode ("add", "a,acc");
5928 emitcode ("add", "a,acc");
5932 /* rotate left accumulator */
5934 /* and kill the lower order bits */
5935 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5940 /*-----------------------------------------------------------------*/
5941 /* AccRsh - right shift accumulator by known count */
5942 /*-----------------------------------------------------------------*/
5944 AccRsh (int shCount)
5951 emitcode ("rrc", "a");
5955 /* rotate right accumulator */
5956 AccRol (8 - shCount);
5957 /* and kill the higher order bits */
5958 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5965 /*-----------------------------------------------------------------*/
5966 /* AccSRsh - signed right shift accumulator by known count */
5967 /*-----------------------------------------------------------------*/
5969 AccSRsh (int shCount)
5976 emitcode ("mov", "c,acc.7");
5977 emitcode ("rrc", "a");
5979 else if (shCount == 2)
5981 emitcode ("mov", "c,acc.7");
5982 emitcode ("rrc", "a");
5983 emitcode ("mov", "c,acc.7");
5984 emitcode ("rrc", "a");
5988 tlbl = newiTempLabel (NULL);
5989 /* rotate right accumulator */
5990 AccRol (8 - shCount);
5991 /* and kill the higher order bits */
5992 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5993 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5994 emitcode ("orl", "a,#0x%02x",
5995 (unsigned char) ~SRMask[shCount]);
5996 emitcode ("", "%05d$:", tlbl->key + 100);
6004 /*-----------------------------------------------------------------*/
6005 /* shiftR1Left2Result - shift right one byte from left to result */
6006 /*-----------------------------------------------------------------*/
6008 shiftR1Left2Result (operand * left, int offl,
6009 operand * result, int offr,
6010 int shCount, int sign)
6012 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6013 /* shift right accumulator */
6018 aopPut (AOP (result), "a", offr);
6024 /*-----------------------------------------------------------------*/
6025 /* shiftL1Left2Result - shift left one byte from left to result */
6026 /*-----------------------------------------------------------------*/
6028 shiftL1Left2Result (operand * left, int offl,
6029 operand * result, int offr, int shCount)
6032 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6034 /* shift left accumulator */
6036 aopPut (AOP (result), "a", offr);
6042 /*-----------------------------------------------------------------*/
6043 /* movLeft2Result - move byte from left to result */
6044 /*-----------------------------------------------------------------*/
6046 movLeft2Result (operand * left, int offl,
6047 operand * result, int offr, int sign)
6050 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6052 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6054 if (*l == '@' && (IS_AOP_PREG (result)))
6056 emitcode ("mov", "a,%s", l);
6057 aopPut (AOP (result), "a", offr);
6062 aopPut (AOP (result), l, offr);
6065 /* MSB sign in acc.7 ! */
6066 if (getDataSize (left) == offl + 1)
6068 emitcode ("mov", "a,%s", l);
6069 aopPut (AOP (result), "a", offr);
6079 /*-----------------------------------------------------------------*/
6080 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6081 /*-----------------------------------------------------------------*/
6085 emitcode ("rrc", "a");
6086 emitcode ("xch", "a,%s", x);
6087 emitcode ("rrc", "a");
6088 emitcode ("xch", "a,%s", x);
6094 /*-----------------------------------------------------------------*/
6095 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6096 /*-----------------------------------------------------------------*/
6100 emitcode ("xch", "a,%s", x);
6101 emitcode ("rlc", "a");
6102 emitcode ("xch", "a,%s", x);
6103 emitcode ("rlc", "a");
6109 /*-----------------------------------------------------------------*/
6110 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6111 /*-----------------------------------------------------------------*/
6115 emitcode ("xch", "a,%s", x);
6116 emitcode ("add", "a,acc");
6117 emitcode ("xch", "a,%s", x);
6118 emitcode ("rlc", "a");
6124 /*-----------------------------------------------------------------*/
6125 /* AccAXLsh - left shift a:x by known count (0..7) */
6126 /*-----------------------------------------------------------------*/
6128 AccAXLsh (char *x, int shCount)
6143 case 5: // AAAAABBB:CCCCCDDD
6145 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6147 emitcode ("anl", "a,#0x%02x",
6148 SLMask[shCount]); // BBB00000:CCCCCDDD
6150 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6152 AccRol (shCount); // DDDCCCCC:BBB00000
6154 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6156 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6158 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6160 emitcode ("anl", "a,#0x%02x",
6161 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6163 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6165 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6168 case 6: // AAAAAABB:CCCCCCDD
6169 emitcode ("anl", "a,#0x%02x",
6170 SRMask[shCount]); // 000000BB:CCCCCCDD
6171 emitcode ("mov", "c,acc.0"); // c = B
6172 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6174 AccAXRrl1 (x); // BCCCCCCD:D000000B
6175 AccAXRrl1 (x); // BBCCCCCC:DD000000
6177 emitcode("rrc","a");
6178 emitcode("xch","a,%s", x);
6179 emitcode("rrc","a");
6180 emitcode("mov","c,acc.0"); //<< get correct bit
6181 emitcode("xch","a,%s", x);
6183 emitcode("rrc","a");
6184 emitcode("xch","a,%s", x);
6185 emitcode("rrc","a");
6186 emitcode("xch","a,%s", x);
6189 case 7: // a:x <<= 7
6191 emitcode ("anl", "a,#0x%02x",
6192 SRMask[shCount]); // 0000000B:CCCCCCCD
6194 emitcode ("mov", "c,acc.0"); // c = B
6196 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6198 AccAXRrl1 (x); // BCCCCCCC:D0000000
6209 /*-----------------------------------------------------------------*/
6210 /* AccAXRsh - right shift a:x known count (0..7) */
6211 /*-----------------------------------------------------------------*/
6213 AccAXRsh (char *x, int shCount)
6221 AccAXRrl1 (x); // 0->a:x
6226 AccAXRrl1 (x); // 0->a:x
6229 AccAXRrl1 (x); // 0->a:x
6234 case 5: // AAAAABBB:CCCCCDDD = a:x
6236 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6238 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6240 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6242 emitcode ("anl", "a,#0x%02x",
6243 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6245 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6247 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6249 emitcode ("anl", "a,#0x%02x",
6250 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6252 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6254 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6256 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6259 case 6: // AABBBBBB:CCDDDDDD
6261 emitcode ("mov", "c,acc.7");
6262 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6264 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6266 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6268 emitcode ("anl", "a,#0x%02x",
6269 SRMask[shCount]); // 000000AA:BBBBBBCC
6272 case 7: // ABBBBBBB:CDDDDDDD
6274 emitcode ("mov", "c,acc.7"); // c = A
6276 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6278 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6280 emitcode ("anl", "a,#0x%02x",
6281 SRMask[shCount]); // 0000000A:BBBBBBBC
6292 /*-----------------------------------------------------------------*/
6293 /* AccAXRshS - right shift signed a:x known count (0..7) */
6294 /*-----------------------------------------------------------------*/
6296 AccAXRshS (char *x, int shCount)
6304 emitcode ("mov", "c,acc.7");
6305 AccAXRrl1 (x); // s->a:x
6309 emitcode ("mov", "c,acc.7");
6310 AccAXRrl1 (x); // s->a:x
6312 emitcode ("mov", "c,acc.7");
6313 AccAXRrl1 (x); // s->a:x
6318 case 5: // AAAAABBB:CCCCCDDD = a:x
6320 tlbl = newiTempLabel (NULL);
6321 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6323 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6325 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6327 emitcode ("anl", "a,#0x%02x",
6328 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6330 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6332 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6334 emitcode ("anl", "a,#0x%02x",
6335 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6337 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6339 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6341 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6343 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6344 emitcode ("orl", "a,#0x%02x",
6345 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6347 emitcode ("", "%05d$:", tlbl->key + 100);
6348 break; // SSSSAAAA:BBBCCCCC
6350 case 6: // AABBBBBB:CCDDDDDD
6352 tlbl = newiTempLabel (NULL);
6353 emitcode ("mov", "c,acc.7");
6354 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6356 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6358 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6360 emitcode ("anl", "a,#0x%02x",
6361 SRMask[shCount]); // 000000AA:BBBBBBCC
6363 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6364 emitcode ("orl", "a,#0x%02x",
6365 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6367 emitcode ("", "%05d$:", tlbl->key + 100);
6369 case 7: // ABBBBBBB:CDDDDDDD
6371 tlbl = newiTempLabel (NULL);
6372 emitcode ("mov", "c,acc.7"); // c = A
6374 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6376 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6378 emitcode ("anl", "a,#0x%02x",
6379 SRMask[shCount]); // 0000000A:BBBBBBBC
6381 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6382 emitcode ("orl", "a,#0x%02x",
6383 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6385 emitcode ("", "%05d$:", tlbl->key + 100);
6395 /*-----------------------------------------------------------------*/
6396 /* shiftL2Left2Result - shift left two bytes from left to result */
6397 /*-----------------------------------------------------------------*/
6399 shiftL2Left2Result (operand * left, int offl,
6400 operand * result, int offr, int shCount)
6402 if (sameRegs (AOP (result), AOP (left)) &&
6403 ((offl + MSB16) == offr))
6405 /* don't crash result[offr] */
6406 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6407 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6411 movLeft2Result (left, offl, result, offr, 0);
6412 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6414 /* ax << shCount (x = lsb(result)) */
6415 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6416 aopPut (AOP (result), "a", offr + MSB16);
6422 /*-----------------------------------------------------------------*/
6423 /* shiftR2Left2Result - shift right two bytes from left to result */
6424 /*-----------------------------------------------------------------*/
6426 shiftR2Left2Result (operand * left, int offl,
6427 operand * result, int offr,
6428 int shCount, int sign)
6430 if (sameRegs (AOP (result), AOP (left)) &&
6431 ((offl + MSB16) == offr))
6433 /* don't crash result[offr] */
6434 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6435 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6439 movLeft2Result (left, offl, result, offr, 0);
6440 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6442 /* a:x >> shCount (x = lsb(result)) */
6444 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6446 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6447 if (getDataSize (result) > 1)
6448 aopPut (AOP (result), "a", offr + MSB16);
6454 /*-----------------------------------------------------------------*/
6455 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6456 /*-----------------------------------------------------------------*/
6458 shiftLLeftOrResult (operand * left, int offl,
6459 operand * result, int offr, int shCount)
6461 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6462 /* shift left accumulator */
6464 /* or with result */
6465 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6466 /* back to result */
6467 aopPut (AOP (result), "a", offr);
6473 /*-----------------------------------------------------------------*/
6474 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6475 /*-----------------------------------------------------------------*/
6477 shiftRLeftOrResult (operand * left, int offl,
6478 operand * result, int offr, int shCount)
6480 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6481 /* shift right accumulator */
6483 /* or with result */
6484 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6485 /* back to result */
6486 aopPut (AOP (result), "a", offr);
6492 /*-----------------------------------------------------------------*/
6493 /* genlshOne - left shift a one byte quantity by known count */
6494 /*-----------------------------------------------------------------*/
6496 genlshOne (operand * result, operand * left, int shCount)
6498 D (emitcode (";", "genlshOne ");
6500 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6506 /*-----------------------------------------------------------------*/
6507 /* genlshTwo - left shift two bytes by known amount != 0 */
6508 /*-----------------------------------------------------------------*/
6510 genlshTwo (operand * result, operand * left, int shCount)
6514 D (emitcode (";", "genlshTwo ");
6517 size = getDataSize (result);
6519 /* if shCount >= 8 */
6527 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6529 movLeft2Result (left, LSB, result, MSB16, 0);
6531 aopPut (AOP (result), zero, LSB);
6534 /* 1 <= shCount <= 7 */
6538 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6540 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6547 /*-----------------------------------------------------------------*/
6548 /* shiftLLong - shift left one long from left to result */
6549 /* offl = LSB or MSB16 */
6550 /*-----------------------------------------------------------------*/
6552 shiftLLong (operand * left, operand * result, int offr)
6555 int size = AOP_SIZE (result);
6557 if (size >= LSB + offr)
6559 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6561 emitcode ("add", "a,acc");
6562 if (sameRegs (AOP (left), AOP (result)) &&
6563 size >= MSB16 + offr && offr != LSB)
6564 emitcode ("xch", "a,%s",
6565 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6567 aopPut (AOP (result), "a", LSB + offr);
6570 if (size >= MSB16 + offr)
6572 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6574 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6577 emitcode ("rlc", "a");
6578 if (sameRegs (AOP (left), AOP (result)) &&
6579 size >= MSB24 + offr && offr != LSB)
6580 emitcode ("xch", "a,%s",
6581 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6583 aopPut (AOP (result), "a", MSB16 + offr);
6586 if (size >= MSB24 + offr)
6588 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6590 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6593 emitcode ("rlc", "a");
6594 if (sameRegs (AOP (left), AOP (result)) &&
6595 size >= MSB32 + offr && offr != LSB)
6596 emitcode ("xch", "a,%s",
6597 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6599 aopPut (AOP (result), "a", MSB24 + offr);
6602 if (size > MSB32 + offr)
6604 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6606 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6609 emitcode ("rlc", "a");
6610 aopPut (AOP (result), "a", MSB32 + offr);
6613 aopPut (AOP (result), zero, LSB);
6619 /*-----------------------------------------------------------------*/
6620 /* genlshFour - shift four byte by a known amount != 0 */
6621 /*-----------------------------------------------------------------*/
6623 genlshFour (operand * result, operand * left, int shCount)
6627 D (emitcode (";", "genlshFour ");
6630 size = AOP_SIZE (result);
6632 /* if shifting more that 3 bytes */
6637 /* lowest order of left goes to the highest
6638 order of the destination */
6639 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6641 movLeft2Result (left, LSB, result, MSB32, 0);
6642 aopPut (AOP (result), zero, LSB);
6643 aopPut (AOP (result), zero, MSB16);
6644 aopPut (AOP (result), zero, MSB32);
6648 /* more than two bytes */
6649 else if (shCount >= 16)
6651 /* lower order two bytes goes to higher order two bytes */
6653 /* if some more remaining */
6655 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6658 movLeft2Result (left, MSB16, result, MSB32, 0);
6659 movLeft2Result (left, LSB, result, MSB24, 0);
6661 aopPut (AOP (result), zero, MSB16);
6662 aopPut (AOP (result), zero, LSB);
6666 /* if more than 1 byte */
6667 else if (shCount >= 8)
6669 /* lower order three bytes goes to higher order three bytes */
6674 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6676 movLeft2Result (left, LSB, result, MSB16, 0);
6682 movLeft2Result (left, MSB24, result, MSB32, 0);
6683 movLeft2Result (left, MSB16, result, MSB24, 0);
6684 movLeft2Result (left, LSB, result, MSB16, 0);
6685 aopPut (AOP (result), zero, LSB);
6687 else if (shCount == 1)
6688 shiftLLong (left, result, MSB16);
6691 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6692 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6693 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6694 aopPut (AOP (result), zero, LSB);
6699 /* 1 <= shCount <= 7 */
6700 else if (shCount <= 2)
6702 shiftLLong (left, result, LSB);
6704 shiftLLong (result, result, LSB);
6706 /* 3 <= shCount <= 7, optimize */
6709 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6710 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6711 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6718 /*-----------------------------------------------------------------*/
6719 /* genLeftShiftLiteral - left shifting by known count */
6720 /*-----------------------------------------------------------------*/
6722 genLeftShiftLiteral (operand * left,
6727 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6730 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6733 freeAsmop (right, NULL, ic, TRUE);
6735 aopOp (left, ic, FALSE, FALSE);
6736 aopOp (result, ic, FALSE, TRUE);
6738 size = getSize (operandType (result));
6741 emitcode ("; shift left ", "result %d, left %d", size,
6745 /* I suppose that the left size >= result size */
6750 movLeft2Result (left, size, result, size, 0);
6754 else if (shCount >= (size * 8))
6756 aopPut (AOP (result), zero, size);
6762 genlshOne (result, left, shCount);
6766 case 3: /* bug: this is for generic pointers, I bet. */
6767 genlshTwo (result, left, shCount);
6771 genlshFour (result, left, shCount);
6775 freeAsmop (left, NULL, ic, TRUE);
6776 freeAsmop (result, NULL, ic, TRUE);
6780 /*-----------------------------------------------------------------*/
6781 /* genLeftShift - generates code for left shifting */
6782 /*-----------------------------------------------------------------*/
6784 genLeftShift (iCode * ic)
6786 operand *left, *right, *result;
6789 symbol *tlbl, *tlbl1;
6791 D (emitcode (";", "genLeftShift ");
6794 right = IC_RIGHT (ic);
6795 left = IC_LEFT (ic);
6796 result = IC_RESULT (ic);
6798 aopOp (right, ic, FALSE, FALSE);
6801 /* if the shift count is known then do it
6802 as efficiently as possible */
6803 if (AOP_TYPE (right) == AOP_LIT)
6805 genLeftShiftLiteral (left, right, result, ic);
6810 /* shift count is unknown then we have to form
6811 a loop get the loop count in B : Note: we take
6812 only the lower order byte since shifting
6813 more that 32 bits make no sense anyway, ( the
6814 largest size of an object can be only 32 bits ) */
6816 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6817 emitcode ("inc", "b");
6818 freeAsmop (right, NULL, ic, TRUE);
6819 aopOp (left, ic, FALSE, FALSE);
6820 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6822 /* now move the left to the result if they are not the
6824 if (!sameRegs (AOP (left), AOP (result)) &&
6825 AOP_SIZE (result) > 1)
6828 size = AOP_SIZE (result);
6830 _startLazyDPSEvaluation ();
6833 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6834 if (*l == '@' && (IS_AOP_PREG (result)))
6837 emitcode ("mov", "a,%s", l);
6838 aopPut (AOP (result), "a", offset);
6841 aopPut (AOP (result), l, offset);
6844 _endLazyDPSEvaluation ();
6847 tlbl = newiTempLabel (NULL);
6848 size = AOP_SIZE (result);
6850 tlbl1 = newiTempLabel (NULL);
6852 /* if it is only one byte then */
6855 symbol *tlbl1 = newiTempLabel (NULL);
6857 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6859 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6860 emitcode ("", "%05d$:", tlbl->key + 100);
6861 emitcode ("add", "a,acc");
6862 emitcode ("", "%05d$:", tlbl1->key + 100);
6863 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6864 aopPut (AOP (result), "a", 0);
6868 reAdjustPreg (AOP (result));
6870 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6871 emitcode ("", "%05d$:", tlbl->key + 100);
6872 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6874 emitcode ("add", "a,acc");
6875 aopPut (AOP (result), "a", offset++);
6876 _startLazyDPSEvaluation ();
6879 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6881 emitcode ("rlc", "a");
6882 aopPut (AOP (result), "a", offset++);
6884 _endLazyDPSEvaluation ();
6885 reAdjustPreg (AOP (result));
6887 emitcode ("", "%05d$:", tlbl1->key + 100);
6888 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6890 freeAsmop (left, NULL, ic, TRUE);
6891 freeAsmop (result, NULL, ic, TRUE);
6896 /*-----------------------------------------------------------------*/
6897 /* genrshOne - right shift a one byte quantity by known count */
6898 /*-----------------------------------------------------------------*/
6900 genrshOne (operand * result, operand * left,
6901 int shCount, int sign)
6903 D (emitcode (";", "genrshOne");
6905 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6911 /*-----------------------------------------------------------------*/
6912 /* genrshTwo - right shift two bytes by known amount != 0 */
6913 /*-----------------------------------------------------------------*/
6915 genrshTwo (operand * result, operand * left,
6916 int shCount, int sign)
6918 D (emitcode (";", "genrshTwo");
6921 /* if shCount >= 8 */
6926 shiftR1Left2Result (left, MSB16, result, LSB,
6929 movLeft2Result (left, MSB16, result, LSB, sign);
6930 addSign (result, MSB16, sign);
6933 /* 1 <= shCount <= 7 */
6935 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6941 /*-----------------------------------------------------------------*/
6942 /* shiftRLong - shift right one long from left to result */
6943 /* offl = LSB or MSB16 */
6944 /*-----------------------------------------------------------------*/
6946 shiftRLong (operand * left, int offl,
6947 operand * result, int sign)
6950 emitcode ("clr", "c");
6951 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6953 emitcode ("mov", "c,acc.7");
6954 emitcode ("rrc", "a");
6955 aopPut (AOP (result), "a", MSB32 - offl);
6957 /* add sign of "a" */
6958 addSign (result, MSB32, sign);
6960 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6961 emitcode ("rrc", "a");
6962 aopPut (AOP (result), "a", MSB24 - offl);
6964 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6965 emitcode ("rrc", "a");
6966 aopPut (AOP (result), "a", MSB16 - offl);
6970 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6971 emitcode ("rrc", "a");
6972 aopPut (AOP (result), "a", LSB);
6979 /*-----------------------------------------------------------------*/
6980 /* genrshFour - shift four byte by a known amount != 0 */
6981 /*-----------------------------------------------------------------*/
6983 genrshFour (operand * result, operand * left,
6984 int shCount, int sign)
6986 D (emitcode (";", "genrshFour");
6989 /* if shifting more that 3 bytes */
6994 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6996 movLeft2Result (left, MSB32, result, LSB, sign);
6997 addSign (result, MSB16, sign);
6999 else if (shCount >= 16)
7003 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7006 movLeft2Result (left, MSB24, result, LSB, 0);
7007 movLeft2Result (left, MSB32, result, MSB16, sign);
7009 addSign (result, MSB24, sign);
7011 else if (shCount >= 8)
7015 shiftRLong (left, MSB16, result, sign);
7016 else if (shCount == 0)
7018 movLeft2Result (left, MSB16, result, LSB, 0);
7019 movLeft2Result (left, MSB24, result, MSB16, 0);
7020 movLeft2Result (left, MSB32, result, MSB24, sign);
7021 addSign (result, MSB32, sign);
7025 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7026 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7027 /* the last shift is signed */
7028 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7029 addSign (result, MSB32, sign);
7033 { /* 1 <= shCount <= 7 */
7036 shiftRLong (left, LSB, result, sign);
7038 shiftRLong (result, LSB, result, sign);
7042 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7043 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7044 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7052 /*-----------------------------------------------------------------*/
7053 /* genRightShiftLiteral - right shifting by known count */
7054 /*-----------------------------------------------------------------*/
7056 genRightShiftLiteral (operand * left,
7062 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7065 D (emitcode (";", "genRightShiftLiteral");
7068 freeAsmop (right, NULL, ic, TRUE);
7070 aopOp (left, ic, FALSE, FALSE);
7071 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7074 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7078 size = getDataSize (left);
7079 /* test the LEFT size !!! */
7081 /* I suppose that the left size >= result size */
7084 size = getDataSize (result);
7086 movLeft2Result (left, size, result, size, 0);
7089 else if (shCount >= (size * 8))
7092 /* get sign in acc.7 */
7093 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7094 addSign (result, LSB, sign);
7101 genrshOne (result, left, shCount, sign);
7105 genrshTwo (result, left, shCount, sign);
7109 genrshFour (result, left, shCount, sign);
7115 freeAsmop (left, NULL, ic, TRUE);
7116 freeAsmop (result, NULL, ic, TRUE);
7121 /*-----------------------------------------------------------------*/
7122 /* genSignedRightShift - right shift of signed number */
7123 /*-----------------------------------------------------------------*/
7125 genSignedRightShift (iCode * ic)
7127 operand *right, *left, *result;
7130 symbol *tlbl, *tlbl1;
7132 D (emitcode (";", "genSignedRightShift ");
7135 /* we do it the hard way put the shift count in b
7136 and loop thru preserving the sign */
7138 right = IC_RIGHT (ic);
7139 left = IC_LEFT (ic);
7140 result = IC_RESULT (ic);
7142 aopOp (right, ic, FALSE, FALSE);
7145 if (AOP_TYPE (right) == AOP_LIT)
7147 genRightShiftLiteral (left, right, result, ic, 1);
7151 /* shift count is unknown then we have to form
7152 a loop get the loop count in B : Note: we take
7153 only the lower order byte since shifting
7154 more that 32 bits make no sense anyway, ( the
7155 largest size of an object can be only 32 bits ) */
7157 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7158 emitcode ("inc", "b");
7159 freeAsmop (right, NULL, ic, TRUE);
7160 aopOp (left, ic, FALSE, FALSE);
7161 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7163 /* now move the left to the result if they are not the
7165 if (!sameRegs (AOP (left), AOP (result)) &&
7166 AOP_SIZE (result) > 1)
7169 size = AOP_SIZE (result);
7171 _startLazyDPSEvaluation ();
7174 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7175 if (*l == '@' && IS_AOP_PREG (result))
7178 emitcode ("mov", "a,%s", l);
7179 aopPut (AOP (result), "a", offset);
7182 aopPut (AOP (result), l, offset);
7185 _endLazyDPSEvaluation ();
7188 /* mov the highest order bit to OVR */
7189 tlbl = newiTempLabel (NULL);
7190 tlbl1 = newiTempLabel (NULL);
7192 size = AOP_SIZE (result);
7194 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7195 emitcode ("rlc", "a");
7196 emitcode ("mov", "ov,c");
7197 /* if it is only one byte then */
7200 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7202 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7203 emitcode ("", "%05d$:", tlbl->key + 100);
7204 emitcode ("mov", "c,ov");
7205 emitcode ("rrc", "a");
7206 emitcode ("", "%05d$:", tlbl1->key + 100);
7207 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7208 aopPut (AOP (result), "a", 0);
7212 reAdjustPreg (AOP (result));
7213 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7214 emitcode ("", "%05d$:", tlbl->key + 100);
7215 emitcode ("mov", "c,ov");
7216 _startLazyDPSEvaluation ();
7219 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7221 emitcode ("rrc", "a");
7222 aopPut (AOP (result), "a", offset--);
7224 _endLazyDPSEvaluation ();
7225 reAdjustPreg (AOP (result));
7226 emitcode ("", "%05d$:", tlbl1->key + 100);
7227 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7230 freeAsmop (left, NULL, ic, TRUE);
7231 freeAsmop (result, NULL, ic, TRUE);
7234 /*-----------------------------------------------------------------*/
7235 /* genRightShift - generate code for right shifting */
7236 /*-----------------------------------------------------------------*/
7238 genRightShift (iCode * ic)
7240 operand *right, *left, *result;
7244 symbol *tlbl, *tlbl1;
7246 D (emitcode (";", "genRightShift ");
7249 /* if signed then we do it the hard way preserve the
7250 sign bit moving it inwards */
7251 retype = getSpec (operandType (IC_RESULT (ic)));
7253 if (!SPEC_USIGN (retype))
7255 genSignedRightShift (ic);
7259 /* signed & unsigned types are treated the same : i.e. the
7260 signed is NOT propagated inwards : quoting from the
7261 ANSI - standard : "for E1 >> E2, is equivalent to division
7262 by 2**E2 if unsigned or if it has a non-negative value,
7263 otherwise the result is implementation defined ", MY definition
7264 is that the sign does not get propagated */
7266 right = IC_RIGHT (ic);
7267 left = IC_LEFT (ic);
7268 result = IC_RESULT (ic);
7270 aopOp (right, ic, FALSE, FALSE);
7273 /* if the shift count is known then do it
7274 as efficiently as possible */
7275 if (AOP_TYPE (right) == AOP_LIT)
7277 genRightShiftLiteral (left, right, result, ic, 0);
7282 /* shift count is unknown then we have to form
7283 a loop get the loop count in B : Note: we take
7284 only the lower order byte since shifting
7285 more that 32 bits make no sense anyway, ( the
7286 largest size of an object can be only 32 bits ) */
7288 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7289 emitcode ("inc", "b");
7290 freeAsmop (right, NULL, ic, TRUE);
7291 aopOp (left, ic, FALSE, FALSE);
7292 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7294 /* now move the left to the result if they are not the
7296 if (!sameRegs (AOP (left), AOP (result)) &&
7297 AOP_SIZE (result) > 1)
7300 size = AOP_SIZE (result);
7302 _startLazyDPSEvaluation ();
7305 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7306 if (*l == '@' && IS_AOP_PREG (result))
7309 emitcode ("mov", "a,%s", l);
7310 aopPut (AOP (result), "a", offset);
7313 aopPut (AOP (result), l, offset);
7316 _endLazyDPSEvaluation ();
7319 tlbl = newiTempLabel (NULL);
7320 tlbl1 = newiTempLabel (NULL);
7321 size = AOP_SIZE (result);
7324 /* if it is only one byte then */
7327 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7329 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7330 emitcode ("", "%05d$:", tlbl->key + 100);
7332 emitcode ("rrc", "a");
7333 emitcode ("", "%05d$:", tlbl1->key + 100);
7334 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7335 aopPut (AOP (result), "a", 0);
7339 reAdjustPreg (AOP (result));
7340 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7341 emitcode ("", "%05d$:", tlbl->key + 100);
7343 _startLazyDPSEvaluation ();
7346 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7348 emitcode ("rrc", "a");
7349 aopPut (AOP (result), "a", offset--);
7351 _endLazyDPSEvaluation ();
7352 reAdjustPreg (AOP (result));
7354 emitcode ("", "%05d$:", tlbl1->key + 100);
7355 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7358 freeAsmop (left, NULL, ic, TRUE);
7359 freeAsmop (result, NULL, ic, TRUE);
7362 /*-----------------------------------------------------------------*/
7363 /* genUnpackBits - generates code for unpacking bits */
7364 /*-----------------------------------------------------------------*/
7366 genUnpackBits (operand * result, char *rname, int ptype)
7373 D (emitcode (";", "genUnpackBits ");
7376 etype = getSpec (operandType (result));
7378 /* read the first byte */
7384 emitcode ("mov", "a,@%s", rname);
7388 emitcode ("movx", "a,@%s", rname);
7392 emitcode ("movx", "a,@dptr");
7396 emitcode ("clr", "a");
7397 emitcode ("movc", "a", "@a+dptr");
7401 emitcode ("lcall", "__gptrget");
7405 /* if we have bitdisplacement then it fits */
7406 /* into this byte completely or if length is */
7407 /* less than a byte */
7408 if ((shCnt = SPEC_BSTR (etype)) ||
7409 (SPEC_BLEN (etype) <= 8))
7412 /* shift right acc */
7415 emitcode ("anl", "a,#0x%02x",
7416 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7417 aopPut (AOP (result), "a", offset);
7421 /* bit field did not fit in a byte */
7422 rlen = SPEC_BLEN (etype) - 8;
7423 aopPut (AOP (result), "a", offset++);
7432 emitcode ("inc", "%s", rname);
7433 emitcode ("mov", "a,@%s", rname);
7437 emitcode ("inc", "%s", rname);
7438 emitcode ("movx", "a,@%s", rname);
7442 emitcode ("inc", "dptr");
7443 emitcode ("movx", "a,@dptr");
7447 emitcode ("clr", "a");
7448 emitcode ("inc", "dptr");
7449 emitcode ("movc", "a", "@a+dptr");
7453 emitcode ("inc", "dptr");
7454 emitcode ("lcall", "__gptrget");
7459 /* if we are done */
7463 aopPut (AOP (result), "a", offset++);
7469 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7470 aopPut (AOP (result), "a", offset);
7477 /*-----------------------------------------------------------------*/
7478 /* genDataPointerGet - generates code when ptr offset is known */
7479 /*-----------------------------------------------------------------*/
7481 genDataPointerGet (operand * left,
7487 int size, offset = 0;
7488 aopOp (result, ic, TRUE, FALSE);
7490 /* get the string representation of the name */
7491 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7492 size = AOP_SIZE (result);
7493 _startLazyDPSEvaluation ();
7497 sprintf (buffer, "(%s + %d)", l + 1, offset);
7499 sprintf (buffer, "%s", l + 1);
7500 aopPut (AOP (result), buffer, offset++);
7502 _endLazyDPSEvaluation ();
7504 freeAsmop (left, NULL, ic, TRUE);
7505 freeAsmop (result, NULL, ic, TRUE);
7508 /*-----------------------------------------------------------------*/
7509 /* genNearPointerGet - emitcode for near pointer fetch */
7510 /*-----------------------------------------------------------------*/
7512 genNearPointerGet (operand * left,
7519 sym_link *rtype, *retype, *letype;
7520 sym_link *ltype = operandType (left);
7523 rtype = operandType (result);
7524 retype = getSpec (rtype);
7525 letype = getSpec (ltype);
7527 aopOp (left, ic, FALSE, FALSE);
7529 /* if left is rematerialisable and
7530 result is not bit variable type and
7531 the left is pointer to data space i.e
7532 lower 128 bytes of space */
7533 if (AOP_TYPE (left) == AOP_IMMD &&
7534 !IS_BITVAR (retype) &&
7535 !IS_BITVAR (letype) &&
7536 DCL_TYPE (ltype) == POINTER)
7538 genDataPointerGet (left, result, ic);
7542 /* if the value is already in a pointer register
7543 then don't need anything more */
7544 if (!AOP_INPREG (AOP (left)))
7546 /* otherwise get a free pointer register */
7548 preg = getFreePtr (ic, &aop, FALSE);
7549 emitcode ("mov", "%s,%s",
7551 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7555 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7557 freeAsmop (left, NULL, ic, TRUE);
7558 aopOp (result, ic, FALSE, FALSE);
7560 /* if bitfield then unpack the bits */
7561 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7562 genUnpackBits (result, rname, POINTER);
7565 /* we have can just get the values */
7566 int size = AOP_SIZE (result);
7571 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7574 emitcode ("mov", "a,@%s", rname);
7575 aopPut (AOP (result), "a", offset);
7579 sprintf (buffer, "@%s", rname);
7580 aopPut (AOP (result), buffer, offset);
7584 emitcode ("inc", "%s", rname);
7588 /* now some housekeeping stuff */
7591 /* we had to allocate for this iCode */
7592 freeAsmop (NULL, aop, ic, TRUE);
7596 /* we did not allocate which means left
7597 already in a pointer register, then
7598 if size > 0 && this could be used again
7599 we have to point it back to where it
7601 if (AOP_SIZE (result) > 1 &&
7602 !OP_SYMBOL (left)->remat &&
7603 (OP_SYMBOL (left)->liveTo > ic->seq ||
7606 int size = AOP_SIZE (result) - 1;
7608 emitcode ("dec", "%s", rname);
7613 freeAsmop (result, NULL, ic, TRUE);
7617 /*-----------------------------------------------------------------*/
7618 /* genPagedPointerGet - emitcode for paged pointer fetch */
7619 /*-----------------------------------------------------------------*/
7621 genPagedPointerGet (operand * left,
7628 sym_link *rtype, *retype, *letype;
7630 rtype = operandType (result);
7631 retype = getSpec (rtype);
7632 letype = getSpec (operandType (left));
7633 aopOp (left, ic, FALSE, FALSE);
7635 /* if the value is already in a pointer register
7636 then don't need anything more */
7637 if (!AOP_INPREG (AOP (left)))
7639 /* otherwise get a free pointer register */
7641 preg = getFreePtr (ic, &aop, FALSE);
7642 emitcode ("mov", "%s,%s",
7644 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7648 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7650 freeAsmop (left, NULL, ic, TRUE);
7651 aopOp (result, ic, FALSE, FALSE);
7653 /* if bitfield then unpack the bits */
7654 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7655 genUnpackBits (result, rname, PPOINTER);
7658 /* we have can just get the values */
7659 int size = AOP_SIZE (result);
7665 emitcode ("movx", "a,@%s", rname);
7666 aopPut (AOP (result), "a", offset);
7671 emitcode ("inc", "%s", rname);
7675 /* now some housekeeping stuff */
7678 /* we had to allocate for this iCode */
7679 freeAsmop (NULL, aop, ic, TRUE);
7683 /* we did not allocate which means left
7684 already in a pointer register, then
7685 if size > 0 && this could be used again
7686 we have to point it back to where it
7688 if (AOP_SIZE (result) > 1 &&
7689 !OP_SYMBOL (left)->remat &&
7690 (OP_SYMBOL (left)->liveTo > ic->seq ||
7693 int size = AOP_SIZE (result) - 1;
7695 emitcode ("dec", "%s", rname);
7700 freeAsmop (result, NULL, ic, TRUE);
7705 /*-----------------------------------------------------------------*/
7706 /* genFarPointerGet - gget value from far space */
7707 /*-----------------------------------------------------------------*/
7709 genFarPointerGet (operand * left,
7710 operand * result, iCode * ic)
7713 sym_link *retype = getSpec (operandType (result));
7714 sym_link *letype = getSpec (operandType (left));
7715 D (emitcode (";", "genFarPointerGet");
7718 aopOp (left, ic, FALSE, FALSE);
7720 /* if the operand is already in dptr
7721 then we do nothing else we move the value to dptr */
7722 if (AOP_TYPE (left) != AOP_STR)
7724 /* if this is remateriazable */
7725 if (AOP_TYPE (left) == AOP_IMMD)
7727 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7731 /* we need to get it byte by byte */
7732 _startLazyDPSEvaluation ();
7733 if (AOP_TYPE (left) != AOP_DPTR)
7735 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7736 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7737 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7741 /* We need to generate a load to DPTR indirect through DPTR. */
7742 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7744 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7745 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7746 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7747 emitcode ("pop", "dph");
7748 emitcode ("pop", "dpl");
7750 _endLazyDPSEvaluation ();
7753 /* so dptr know contains the address */
7754 freeAsmop (left, NULL, ic, TRUE);
7755 aopOp (result, ic, FALSE, TRUE);
7757 /* if bit then unpack */
7758 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7759 genUnpackBits (result, "dptr", FPOINTER);
7762 size = AOP_SIZE (result);
7765 _startLazyDPSEvaluation ();
7772 emitcode ("movx", "a,@dptr");
7774 emitcode ("inc", "dptr");
7776 aopPut (AOP (result), "a", offset++);
7778 _endLazyDPSEvaluation ();
7781 freeAsmop (result, NULL, ic, TRUE);
7784 /*-----------------------------------------------------------------*/
7785 /* emitcodePointerGet - gget value from code space */
7786 /*-----------------------------------------------------------------*/
7788 emitcodePointerGet (operand * left,
7789 operand * result, iCode * ic)
7792 sym_link *retype = getSpec (operandType (result));
7794 aopOp (left, ic, FALSE, FALSE);
7796 /* if the operand is already in dptr
7797 then we do nothing else we move the value to dptr */
7798 if (AOP_TYPE (left) != AOP_STR)
7800 /* if this is remateriazable */
7801 if (AOP_TYPE (left) == AOP_IMMD)
7803 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7806 { /* we need to get it byte by byte */
7807 _startLazyDPSEvaluation ();
7808 if (AOP_TYPE (left) != AOP_DPTR)
7810 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7811 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7812 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7816 /* We need to generate a load to DPTR indirect through DPTR. */
7817 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7819 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7820 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7821 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7822 emitcode ("pop", "dph");
7823 emitcode ("pop", "dpl");
7825 _endLazyDPSEvaluation ();
7828 /* so dptr know contains the address */
7829 freeAsmop (left, NULL, ic, TRUE);
7830 aopOp (result, ic, FALSE, TRUE);
7832 /* if bit then unpack */
7833 if (IS_BITVAR (retype))
7834 genUnpackBits (result, "dptr", CPOINTER);
7837 size = AOP_SIZE (result);
7840 _startLazyDPSEvaluation ();
7846 emitcode ("clr", "a");
7847 emitcode ("movc", "a,@a+dptr");
7849 emitcode ("inc", "dptr");
7850 aopPut (AOP (result), "a", offset++);
7852 _endLazyDPSEvaluation ();
7855 freeAsmop (result, NULL, ic, TRUE);
7858 /*-----------------------------------------------------------------*/
7859 /* genGenPointerGet - gget value from generic pointer space */
7860 /*-----------------------------------------------------------------*/
7862 genGenPointerGet (operand * left,
7863 operand * result, iCode * ic)
7866 sym_link *retype = getSpec (operandType (result));
7867 sym_link *letype = getSpec (operandType (left));
7869 D (emitcode (";", "genGenPointerGet "); );
7871 aopOp (left, ic, FALSE, TRUE);
7873 /* if the operand is already in dptr
7874 then we do nothing else we move the value to dptr */
7875 if (AOP_TYPE (left) != AOP_STR)
7877 /* if this is remateriazable */
7878 if (AOP_TYPE (left) == AOP_IMMD)
7880 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7881 emitcode ("mov", "b,#%d", pointerCode (retype));
7884 { /* we need to get it byte by byte */
7885 _startLazyDPSEvaluation ();
7886 if (AOP(left)->type==AOP_DPTR2) {
7888 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7891 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7892 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7895 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7896 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7899 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7900 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7902 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7903 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7904 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7905 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7907 _endLazyDPSEvaluation ();
7910 /* so dptr know contains the address */
7911 freeAsmop (left, NULL, ic, TRUE);
7912 aopOp (result, ic, FALSE, TRUE);
7914 /* if bit then unpack */
7915 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7916 genUnpackBits (result, "dptr", GPOINTER);
7919 size = AOP_SIZE (result);
7924 emitcode ("lcall", "__gptrget");
7925 aopPut (AOP (result), "a", offset++);
7927 emitcode ("inc", "dptr");
7931 freeAsmop (result, NULL, ic, TRUE);
7934 /*-----------------------------------------------------------------*/
7935 /* genPointerGet - generate code for pointer get */
7936 /*-----------------------------------------------------------------*/
7938 genPointerGet (iCode * ic)
7940 operand *left, *result;
7941 sym_link *type, *etype;
7944 D (emitcode (";", "genPointerGet ");
7947 left = IC_LEFT (ic);
7948 result = IC_RESULT (ic);
7950 /* depending on the type of pointer we need to
7951 move it to the correct pointer register */
7952 type = operandType (left);
7953 etype = getSpec (type);
7954 /* if left is of type of pointer then it is simple */
7955 if (IS_PTR (type) && !IS_FUNC (type->next))
7956 p_type = DCL_TYPE (type);
7959 /* we have to go by the storage class */
7960 p_type = PTR_TYPE (SPEC_OCLS (etype));
7963 /* now that we have the pointer type we assign
7964 the pointer values */
7970 genNearPointerGet (left, result, ic);
7974 genPagedPointerGet (left, result, ic);
7978 genFarPointerGet (left, result, ic);
7982 emitcodePointerGet (left, result, ic);
7986 genGenPointerGet (left, result, ic);
7992 /*-----------------------------------------------------------------*/
7993 /* genPackBits - generates code for packed bit storage */
7994 /*-----------------------------------------------------------------*/
7996 genPackBits (sym_link * etype,
7998 char *rname, int p_type)
8006 blen = SPEC_BLEN (etype);
8007 bstr = SPEC_BSTR (etype);
8009 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8012 /* if the bit lenth is less than or */
8013 /* it exactly fits a byte then */
8014 if (SPEC_BLEN (etype) <= 8)
8016 shCount = SPEC_BSTR (etype);
8018 /* shift left acc */
8021 if (SPEC_BLEN (etype) < 8)
8022 { /* if smaller than a byte */
8028 emitcode ("mov", "b,a");
8029 emitcode ("mov", "a,@%s", rname);
8033 emitcode ("mov", "b,a");
8034 emitcode ("movx", "a,@dptr");
8038 emitcode ("push", "b");
8039 emitcode ("push", "acc");
8040 emitcode ("lcall", "__gptrget");
8041 emitcode ("pop", "b");
8045 emitcode ("anl", "a,#0x%02x", (unsigned char)
8046 ((unsigned char) (0xFF << (blen + bstr)) |
8047 (unsigned char) (0xFF >> (8 - bstr))));
8048 emitcode ("orl", "a,b");
8049 if (p_type == GPOINTER)
8050 emitcode ("pop", "b");
8057 emitcode ("mov", "@%s,a", rname);
8061 emitcode ("movx", "@dptr,a");
8065 emitcode ("lcall", "__gptrput");
8070 if (SPEC_BLEN (etype) <= 8)
8073 emitcode ("inc", "%s", rname);
8074 rLen = SPEC_BLEN (etype);
8076 /* now generate for lengths greater than one byte */
8080 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8092 emitcode ("mov", "@%s,a", rname);
8095 emitcode ("mov", "@%s,%s", rname, l);
8100 emitcode ("movx", "@dptr,a");
8105 emitcode ("lcall", "__gptrput");
8108 emitcode ("inc", "%s", rname);
8113 /* last last was not complete */
8116 /* save the byte & read byte */
8120 emitcode ("mov", "b,a");
8121 emitcode ("mov", "a,@%s", rname);
8125 emitcode ("mov", "b,a");
8126 emitcode ("movx", "a,@dptr");
8130 emitcode ("push", "b");
8131 emitcode ("push", "acc");
8132 emitcode ("lcall", "__gptrget");
8133 emitcode ("pop", "b");
8137 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8138 emitcode ("orl", "a,b");
8141 if (p_type == GPOINTER)
8142 emitcode ("pop", "b");
8148 emitcode ("mov", "@%s,a", rname);
8152 emitcode ("movx", "@dptr,a");
8156 emitcode ("lcall", "__gptrput");
8160 /*-----------------------------------------------------------------*/
8161 /* genDataPointerSet - remat pointer to data space */
8162 /*-----------------------------------------------------------------*/
8164 genDataPointerSet (operand * right,
8168 int size, offset = 0;
8169 char *l, buffer[256];
8171 aopOp (right, ic, FALSE, FALSE);
8173 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8174 size = AOP_SIZE (right);
8178 sprintf (buffer, "(%s + %d)", l + 1, offset);
8180 sprintf (buffer, "%s", l + 1);
8181 emitcode ("mov", "%s,%s", buffer,
8182 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8185 freeAsmop (right, NULL, ic, TRUE);
8186 freeAsmop (result, NULL, ic, TRUE);
8189 /*-----------------------------------------------------------------*/
8190 /* genNearPointerSet - emitcode for near pointer put */
8191 /*-----------------------------------------------------------------*/
8193 genNearPointerSet (operand * right,
8200 sym_link *retype, *letype;
8201 sym_link *ptype = operandType (result);
8203 retype = getSpec (operandType (right));
8204 letype = getSpec (ptype);
8206 aopOp (result, ic, FALSE, FALSE);
8208 /* if the result is rematerializable &
8209 in data space & not a bit variable */
8210 if (AOP_TYPE (result) == AOP_IMMD &&
8211 DCL_TYPE (ptype) == POINTER &&
8212 !IS_BITVAR (retype) &&
8213 !IS_BITVAR (letype))
8215 genDataPointerSet (right, result, ic);
8219 /* if the value is already in a pointer register
8220 then don't need anything more */
8221 if (!AOP_INPREG (AOP (result)))
8223 /* otherwise get a free pointer register */
8225 preg = getFreePtr (ic, &aop, FALSE);
8226 emitcode ("mov", "%s,%s",
8228 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8232 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8234 freeAsmop (result, NULL, ic, TRUE);
8235 aopOp (right, ic, FALSE, FALSE);
8237 /* if bitfield then unpack the bits */
8238 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8239 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8242 /* we have can just get the values */
8243 int size = AOP_SIZE (right);
8248 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8252 emitcode ("mov", "@%s,a", rname);
8255 emitcode ("mov", "@%s,%s", rname, l);
8257 emitcode ("inc", "%s", rname);
8262 /* now some housekeeping stuff */
8265 /* we had to allocate for this iCode */
8266 freeAsmop (NULL, aop, ic, TRUE);
8270 /* we did not allocate which means left
8271 already in a pointer register, then
8272 if size > 0 && this could be used again
8273 we have to point it back to where it
8275 if (AOP_SIZE (right) > 1 &&
8276 !OP_SYMBOL (result)->remat &&
8277 (OP_SYMBOL (result)->liveTo > ic->seq ||
8280 int size = AOP_SIZE (right) - 1;
8282 emitcode ("dec", "%s", rname);
8287 freeAsmop (right, NULL, ic, TRUE);
8292 /*-----------------------------------------------------------------*/
8293 /* genPagedPointerSet - emitcode for Paged pointer put */
8294 /*-----------------------------------------------------------------*/
8296 genPagedPointerSet (operand * right,
8303 sym_link *retype, *letype;
8305 retype = getSpec (operandType (right));
8306 letype = getSpec (operandType (result));
8308 aopOp (result, ic, FALSE, FALSE);
8310 /* if the value is already in a pointer register
8311 then don't need anything more */
8312 if (!AOP_INPREG (AOP (result)))
8314 /* otherwise get a free pointer register */
8316 preg = getFreePtr (ic, &aop, FALSE);
8317 emitcode ("mov", "%s,%s",
8319 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8323 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8325 freeAsmop (result, NULL, ic, TRUE);
8326 aopOp (right, ic, FALSE, FALSE);
8328 /* if bitfield then unpack the bits */
8329 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8330 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8333 /* we have can just get the values */
8334 int size = AOP_SIZE (right);
8339 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8342 emitcode ("movx", "@%s,a", rname);
8345 emitcode ("inc", "%s", rname);
8351 /* now some housekeeping stuff */
8354 /* we had to allocate for this iCode */
8355 freeAsmop (NULL, aop, ic, TRUE);
8359 /* we did not allocate which means left
8360 already in a pointer register, then
8361 if size > 0 && this could be used again
8362 we have to point it back to where it
8364 if (AOP_SIZE (right) > 1 &&
8365 !OP_SYMBOL (result)->remat &&
8366 (OP_SYMBOL (result)->liveTo > ic->seq ||
8369 int size = AOP_SIZE (right) - 1;
8371 emitcode ("dec", "%s", rname);
8376 freeAsmop (right, NULL, ic, TRUE);
8381 /*-----------------------------------------------------------------*/
8382 /* genFarPointerSet - set value from far space */
8383 /*-----------------------------------------------------------------*/
8385 genFarPointerSet (operand * right,
8386 operand * result, iCode * ic)
8389 sym_link *retype = getSpec (operandType (right));
8390 sym_link *letype = getSpec (operandType (result));
8392 aopOp (result, ic, FALSE, FALSE);
8394 /* if the operand is already in dptr
8395 then we do nothing else we move the value to dptr */
8396 if (AOP_TYPE (result) != AOP_STR)
8398 /* if this is remateriazable */
8399 if (AOP_TYPE (result) == AOP_IMMD)
8400 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8403 /* we need to get it byte by byte */
8404 _startLazyDPSEvaluation ();
8405 if (AOP_TYPE (result) != AOP_DPTR)
8407 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8408 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8409 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8413 /* We need to generate a load to DPTR indirect through DPTR. */
8414 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8416 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8417 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8418 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8419 emitcode ("pop", "dph");
8420 emitcode ("pop", "dpl");
8422 _endLazyDPSEvaluation ();
8425 /* so dptr know contains the address */
8426 freeAsmop (result, NULL, ic, TRUE);
8427 aopOp (right, ic, FALSE, TRUE);
8429 /* if bit then unpack */
8430 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8431 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8434 size = AOP_SIZE (right);
8437 _startLazyDPSEvaluation ();
8440 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8446 emitcode ("movx", "@dptr,a");
8448 emitcode ("inc", "dptr");
8450 _endLazyDPSEvaluation ();
8453 freeAsmop (right, NULL, ic, TRUE);
8456 /*-----------------------------------------------------------------*/
8457 /* genGenPointerSet - set value from generic pointer space */
8458 /*-----------------------------------------------------------------*/
8460 genGenPointerSet (operand * right,
8461 operand * result, iCode * ic)
8464 sym_link *retype = getSpec (operandType (right));
8465 sym_link *letype = getSpec (operandType (result));
8467 aopOp (result, ic, FALSE, TRUE);
8469 /* if the operand is already in dptr
8470 then we do nothing else we move the value to dptr */
8471 if (AOP_TYPE (result) != AOP_STR)
8473 _startLazyDPSEvaluation ();
8474 /* if this is remateriazable */
8475 if (AOP_TYPE (result) == AOP_IMMD)
8477 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8478 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8481 { /* we need to get it byte by byte */
8482 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8483 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8484 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8485 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8487 _endLazyDPSEvaluation ();
8489 /* so dptr know contains the address */
8490 freeAsmop (result, NULL, ic, TRUE);
8491 aopOp (right, ic, FALSE, TRUE);
8493 /* if bit then unpack */
8494 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8495 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8498 size = AOP_SIZE (right);
8501 _startLazyDPSEvaluation ();
8504 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8510 emitcode ("lcall", "__gptrput");
8512 emitcode ("inc", "dptr");
8514 _endLazyDPSEvaluation ();
8517 freeAsmop (right, NULL, ic, TRUE);
8520 /*-----------------------------------------------------------------*/
8521 /* genPointerSet - stores the value into a pointer location */
8522 /*-----------------------------------------------------------------*/
8524 genPointerSet (iCode * ic)
8526 operand *right, *result;
8527 sym_link *type, *etype;
8530 D (emitcode (";", "genPointerSet ");
8533 right = IC_RIGHT (ic);
8534 result = IC_RESULT (ic);
8536 /* depending on the type of pointer we need to
8537 move it to the correct pointer register */
8538 type = operandType (result);
8539 etype = getSpec (type);
8540 /* if left is of type of pointer then it is simple */
8541 if (IS_PTR (type) && !IS_FUNC (type->next))
8543 p_type = DCL_TYPE (type);
8547 /* we have to go by the storage class */
8548 p_type = PTR_TYPE (SPEC_OCLS (etype));
8551 /* now that we have the pointer type we assign
8552 the pointer values */
8558 genNearPointerSet (right, result, ic);
8562 genPagedPointerSet (right, result, ic);
8566 genFarPointerSet (right, result, ic);
8570 genGenPointerSet (right, result, ic);
8576 /*-----------------------------------------------------------------*/
8577 /* genIfx - generate code for Ifx statement */
8578 /*-----------------------------------------------------------------*/
8580 genIfx (iCode * ic, iCode * popIc)
8582 operand *cond = IC_COND (ic);
8585 D (emitcode (";", "genIfx ");
8588 aopOp (cond, ic, FALSE, FALSE);
8590 /* get the value into acc */
8591 if (AOP_TYPE (cond) != AOP_CRY)
8595 /* the result is now in the accumulator */
8596 freeAsmop (cond, NULL, ic, TRUE);
8598 /* if there was something to be popped then do it */
8602 /* if the condition is a bit variable */
8603 if (isbit && IS_ITEMP (cond) &&
8605 genIfxJump (ic, SPIL_LOC (cond)->rname);
8606 else if (isbit && !IS_ITEMP (cond))
8607 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8609 genIfxJump (ic, "a");
8614 /*-----------------------------------------------------------------*/
8615 /* genAddrOf - generates code for address of */
8616 /*-----------------------------------------------------------------*/
8618 genAddrOf (iCode * ic)
8620 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8623 D (emitcode (";", "genAddrOf ");
8626 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8628 /* if the operand is on the stack then we
8629 need to get the stack offset of this
8633 /* if it has an offset then we need to compute
8637 emitcode ("mov", "a,_bp");
8638 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8639 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8643 /* we can just move _bp */
8644 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8646 /* fill the result with zero */
8647 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8650 if (options.stack10bit && size < (FPTRSIZE - 1))
8653 "*** warning: pointer to stack var truncated.\n");
8660 if (options.stack10bit && offset == 2)
8662 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8666 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8673 /* object not on stack then we need the name */
8674 size = AOP_SIZE (IC_RESULT (ic));
8679 char s[SDCC_NAME_MAX];
8681 sprintf (s, "#(%s >> %d)",
8685 sprintf (s, "#%s", sym->rname);
8686 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8690 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8694 /*-----------------------------------------------------------------*/
8695 /* genFarFarAssign - assignment when both are in far space */
8696 /*-----------------------------------------------------------------*/
8698 genFarFarAssign (operand * result, operand * right, iCode * ic)
8700 int size = AOP_SIZE (right);
8706 /* This is a net loss for size == 1, but a big gain
8709 D (emitcode (";", "genFarFarAssign (improved)");
8712 aopOp (result, ic, TRUE, TRUE);
8714 _startLazyDPSEvaluation ();
8717 aopPut (AOP (result),
8718 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8721 _endLazyDPSEvaluation ();
8722 freeAsmop (result, NULL, ic, FALSE);
8723 freeAsmop (right, NULL, ic, FALSE);
8727 D (emitcode (";", "genFarFarAssign ");
8730 /* first push the right side on to the stack */
8731 _startLazyDPSEvaluation ();
8734 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8736 emitcode ("push", "acc");
8739 freeAsmop (right, NULL, ic, FALSE);
8740 /* now assign DPTR to result */
8741 aopOp (result, ic, FALSE, FALSE);
8742 size = AOP_SIZE (result);
8745 emitcode ("pop", "acc");
8746 aopPut (AOP (result), "a", --offset);
8748 freeAsmop (result, NULL, ic, FALSE);
8749 _endLazyDPSEvaluation ();
8753 /*-----------------------------------------------------------------*/
8754 /* genAssign - generate code for assignment */
8755 /*-----------------------------------------------------------------*/
8757 genAssign (iCode * ic)
8759 operand *result, *right;
8761 unsigned long lit = 0L;
8763 D (emitcode (";", "genAssign ");
8766 result = IC_RESULT (ic);
8767 right = IC_RIGHT (ic);
8769 /* if they are the same */
8770 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8773 aopOp (right, ic, FALSE, FALSE);
8775 emitcode (";", "genAssign: resultIsFar = %s",
8776 isOperandInFarSpace (result) ?
8779 /* special case both in far space */
8780 if ((AOP_TYPE (right) == AOP_DPTR ||
8781 AOP_TYPE (right) == AOP_DPTR2) &&
8782 /* IS_TRUE_SYMOP(result) && */
8783 isOperandInFarSpace (result))
8785 genFarFarAssign (result, right, ic);
8789 aopOp (result, ic, TRUE, FALSE);
8791 /* if they are the same registers */
8792 if (sameRegs (AOP (right), AOP (result)))
8795 /* if the result is a bit */
8796 if (AOP_TYPE (result) == AOP_CRY)
8799 /* if the right size is a literal then
8800 we know what the value is */
8801 if (AOP_TYPE (right) == AOP_LIT)
8803 if (((int) operandLitValue (right)))
8804 aopPut (AOP (result), one, 0);
8806 aopPut (AOP (result), zero, 0);
8810 /* the right is also a bit variable */
8811 if (AOP_TYPE (right) == AOP_CRY)
8813 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8814 aopPut (AOP (result), "c", 0);
8820 aopPut (AOP (result), "a", 0);
8824 /* bit variables done */
8826 size = AOP_SIZE (result);
8828 if (AOP_TYPE (right) == AOP_LIT)
8829 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8832 (AOP_TYPE (result) != AOP_REG) &&
8833 (AOP_TYPE (right) == AOP_LIT) &&
8834 !IS_FLOAT (operandType (right)))
8836 D (emitcode (";", "Kevin's better literal load code");
8838 _startLazyDPSEvaluation ();
8839 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8841 aopPut (AOP (result),
8842 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8847 /* And now fill the rest with zeros. */
8850 emitcode ("clr", "a");
8854 aopPut (AOP (result), "a", offset++);
8856 _endLazyDPSEvaluation ();
8860 _startLazyDPSEvaluation ();
8863 aopPut (AOP (result),
8864 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8868 _endLazyDPSEvaluation ();
8872 freeAsmop (right, NULL, ic, FALSE);
8873 freeAsmop (result, NULL, ic, TRUE);
8876 /*-----------------------------------------------------------------*/
8877 /* genJumpTab - generates code for jump table */
8878 /*-----------------------------------------------------------------*/
8880 genJumpTab (iCode * ic)
8885 D (emitcode (";", "genJumpTab ");
8888 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8889 /* get the condition into accumulator */
8890 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8892 /* multiply by four! */
8893 emitcode ("add", "a,acc");
8894 emitcode ("add", "a,acc");
8895 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8897 jtab = newiTempLabel (NULL);
8898 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8899 emitcode ("jmp", "@a+dptr");
8900 emitcode ("", "%05d$:", jtab->key + 100);
8901 /* now generate the jump labels */
8902 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8903 jtab = setNextItem (IC_JTLABELS (ic)))
8904 emitcode ("ljmp", "%05d$", jtab->key + 100);
8908 /*-----------------------------------------------------------------*/
8909 /* genCast - gen code for casting */
8910 /*-----------------------------------------------------------------*/
8912 genCast (iCode * ic)
8914 operand *result = IC_RESULT (ic);
8915 sym_link *ctype = operandType (IC_LEFT (ic));
8916 sym_link *rtype = operandType (IC_RIGHT (ic));
8917 operand *right = IC_RIGHT (ic);
8920 D (emitcode (";", "genCast ");
8923 /* if they are equivalent then do nothing */
8924 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8927 aopOp (right, ic, FALSE, FALSE);
8928 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8930 /* if the result is a bit */
8931 if (AOP_TYPE (result) == AOP_CRY)
8933 /* if the right size is a literal then
8934 we know what the value is */
8935 if (AOP_TYPE (right) == AOP_LIT)
8937 if (((int) operandLitValue (right)))
8938 aopPut (AOP (result), one, 0);
8940 aopPut (AOP (result), zero, 0);
8945 /* the right is also a bit variable */
8946 if (AOP_TYPE (right) == AOP_CRY)
8948 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8949 aopPut (AOP (result), "c", 0);
8955 aopPut (AOP (result), "a", 0);
8959 /* if they are the same size : or less */
8960 if (AOP_SIZE (result) <= AOP_SIZE (right))
8963 /* if they are in the same place */
8964 if (sameRegs (AOP (right), AOP (result)))
8967 /* if they in different places then copy */
8968 size = AOP_SIZE (result);
8970 _startLazyDPSEvaluation ();
8973 aopPut (AOP (result),
8974 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8978 _endLazyDPSEvaluation ();
8983 /* if the result is of type pointer */
8988 sym_link *type = operandType (right);
8990 /* pointer to generic pointer */
8991 if (IS_GENPTR (ctype))
8997 p_type = DCL_TYPE (type);
9001 #if OLD_CAST_BEHAVIOR
9002 /* KV: we are converting a non-pointer type to
9003 * a generic pointer. This (ifdef'd out) code
9004 * says that the resulting generic pointer
9005 * should have the same class as the storage
9006 * location of the non-pointer variable.
9008 * For example, converting an int (which happens
9009 * to be stored in DATA space) to a pointer results
9010 * in a DATA generic pointer; if the original int
9011 * in XDATA space, so will be the resulting pointer.
9013 * I don't like that behavior, and thus this change:
9014 * all such conversions will be forced to XDATA and
9015 * throw a warning. If you want some non-XDATA
9016 * type, or you want to suppress the warning, you
9017 * must go through an intermediate cast, like so:
9019 * char _generic *gp = (char _xdata *)(intVar);
9021 sym_link *etype = getSpec (type);
9023 /* we have to go by the storage class */
9024 if (SPEC_OCLS (etype) != generic)
9026 p_type = PTR_TYPE (SPEC_OCLS (etype));
9031 /* Converting unknown class (i.e. register variable)
9032 * to generic pointer. This is not good, but
9033 * we'll make a guess (and throw a warning).
9036 werror (W_INT_TO_GEN_PTR_CAST);
9040 /* the first two bytes are known */
9041 size = GPTRSIZE - 1;
9043 _startLazyDPSEvaluation ();
9046 aopPut (AOP (result),
9047 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9051 _endLazyDPSEvaluation ();
9053 /* the last byte depending on type */
9071 /* this should never happen */
9072 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9073 "got unknown pointer type");
9076 aopPut (AOP (result), l, GPTRSIZE - 1);
9080 /* just copy the pointers */
9081 size = AOP_SIZE (result);
9083 _startLazyDPSEvaluation ();
9086 aopPut (AOP (result),
9087 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9091 _endLazyDPSEvaluation ();
9095 /* so we now know that the size of destination is greater
9096 than the size of the source */
9097 /* we move to result for the size of source */
9098 size = AOP_SIZE (right);
9100 _startLazyDPSEvaluation ();
9103 aopPut (AOP (result),
9104 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9108 _endLazyDPSEvaluation ();
9110 /* now depending on the sign of the source && destination */
9111 size = AOP_SIZE (result) - AOP_SIZE (right);
9112 /* if unsigned or not an integral type */
9113 /* also, if the source is a bit, we don't need to sign extend, because
9114 * it can't possibly have set the sign bit.
9116 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9120 aopPut (AOP (result), zero, offset++);
9125 /* we need to extend the sign :{ */
9126 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9127 FALSE, FALSE, TRUE);
9129 emitcode ("rlc", "a");
9130 emitcode ("subb", "a,acc");
9132 aopPut (AOP (result), "a", offset++);
9135 /* we are done hurray !!!! */
9138 freeAsmop (right, NULL, ic, TRUE);
9139 freeAsmop (result, NULL, ic, TRUE);
9143 /*-----------------------------------------------------------------*/
9144 /* genDjnz - generate decrement & jump if not zero instrucion */
9145 /*-----------------------------------------------------------------*/
9147 genDjnz (iCode * ic, iCode * ifx)
9153 /* if the if condition has a false label
9154 then we cannot save */
9158 /* if the minus is not of the form
9160 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9161 !IS_OP_LITERAL (IC_RIGHT (ic)))
9164 if (operandLitValue (IC_RIGHT (ic)) != 1)
9167 /* if the size of this greater than one then no
9169 if (getSize (operandType (IC_RESULT (ic))) > 1)
9172 /* otherwise we can save BIG */
9173 lbl = newiTempLabel (NULL);
9174 lbl1 = newiTempLabel (NULL);
9176 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9178 if (IS_AOP_PREG (IC_RESULT (ic)))
9180 emitcode ("dec", "%s",
9181 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9182 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9183 emitcode ("jnz", "%05d$", lbl->key + 100);
9187 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9190 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9191 emitcode ("", "%05d$:", lbl->key + 100);
9192 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9193 emitcode ("", "%05d$:", lbl1->key + 100);
9195 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9200 /*-----------------------------------------------------------------*/
9201 /* genReceive - generate code for a receive iCode */
9202 /*-----------------------------------------------------------------*/
9204 genReceive (iCode * ic)
9207 D (emitcode (";", "genReceive ");
9210 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9211 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9212 IS_TRUE_SYMOP (IC_RESULT (ic))))
9214 int size = getSize (operandType (IC_RESULT (ic)));
9215 int offset = fReturnSizeDS390 - size;
9218 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9219 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9222 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9223 size = AOP_SIZE (IC_RESULT (ic));
9227 emitcode ("pop", "acc");
9228 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9235 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9237 assignResultValue (IC_RESULT (ic));
9240 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9243 /*-----------------------------------------------------------------*/
9244 /* gen390Code - generate code for Dallas 390 based controllers */
9245 /*-----------------------------------------------------------------*/
9247 gen390Code (iCode * lic)
9252 lineHead = lineCurr = NULL;
9256 /* print the allocation information */
9258 printAllocInfo (currFunc, codeOutFile);
9260 /* if debug information required */
9261 if (options.debug && currFunc)
9263 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9265 if (IS_STATIC (currFunc->etype))
9266 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9268 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9271 /* stack pointer name */
9272 if (options.useXstack)
9278 for (ic = lic; ic; ic = ic->next)
9281 if (cln != ic->lineno)
9286 emitcode ("", "C$%s$%d$%d$%d ==.",
9287 FileBaseName (ic->filename), ic->lineno,
9288 ic->level, ic->block);
9291 emitcode (";", "%s %d", ic->filename, ic->lineno);
9294 /* if the result is marked as
9295 spilt and rematerializable or code for
9296 this has already been generated then
9298 if (resultRemat (ic) || ic->generated)
9301 /* depending on the operation */
9321 /* IPOP happens only when trying to restore a
9322 spilt live range, if there is an ifx statement
9323 following this pop then the if statement might
9324 be using some of the registers being popped which
9325 would destory the contents of the register so
9326 we need to check for this condition and handle it */
9328 ic->next->op == IFX &&
9329 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9330 genIfx (ic->next, ic);
9348 genEndFunction (ic);
9368 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9385 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9389 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9396 /* note these two are xlated by algebraic equivalence
9397 during parsing SDCC.y */
9398 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9399 "got '>=' or '<=' shouldn't have come here");
9403 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9415 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9419 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9423 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9450 case GET_VALUE_AT_ADDRESS:
9455 if (POINTER_SET (ic))
9482 addSet (&_G.sendSet, ic);
9487 /* piCode(ic,stdout); */
9493 /* now we are ready to call the
9494 peep hole optimizer */
9495 if (!options.nopeep)
9496 peepHole (&lineHead);
9498 /* now do the actual printing */
9499 printLine (lineHead, codeOutFile);