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=16 bit multiplication */
3688 /*-----------------------------------------------------------------*/
3690 emitcode(";catch","me");
3694 genMultOneByte (operand * left,
3698 sym_link *opetype = operandType (result);
3701 if (AOP_SIZE (result)!=2) {
3702 // this should never happen
3703 fprintf (stderr, "size!=2 in geniCodeMultOneByte\n");
3706 if (SPEC_USIGN(opetype) ||
3707 // ignore the sign of left and right, what else can we do?
3708 (SPEC_USIGN(operandType(left)) &&
3709 SPEC_USIGN(operandType(right)))) {
3710 // just an unsigned 8*8=16 multiply
3711 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3712 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3713 emitcode ("mul", "ab");
3714 aopPut (AOP (result), "a", 0);
3715 aopPut (AOP (result), "b", 1);
3719 // we have to do a signed multiply
3722 // literals ignored for now
3724 /* (if two literals: the value is computed before) */
3725 /* if one literal, literal on the right */
3726 if (AOP_TYPE (left) == AOP_LIT)
3734 emitcode ("mov", "ap,#0"); // can't we use some flag bit here?
3735 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3736 lbl=newiTempLabel(NULL);
3737 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3738 // right side is negative, should test for litteral too
3739 emitcode ("inc", "ap"); // opRight is negative
3740 emitcode ("cpl", "a"); // 8-bit two's complement, this fails for -128
3741 emitcode ("inc", "a");
3742 emitcode ("", "%05d$:", lbl->key+100);
3743 emitcode ("mov", "b,a");
3745 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3746 lbl=newiTempLabel(NULL);
3747 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3748 // left side is negative
3749 emitcode ("inc", "ap"); // opLeft is negative
3750 emitcode ("cpl", "a"); // 8-bit two's complement, this fails for -128
3751 emitcode ("inc", "a");
3752 emitcode ("", "%05d$:", lbl->key+100);
3753 emitcode ("mul", "ab");
3755 lbl=newiTempLabel(NULL);
3756 emitcode ("xch", "a,ap");
3757 emitcode ("rrc", "a");
3758 emitcode ("xch", "a,ap");
3759 emitcode ("jnc", "%05d$", lbl->key+100);
3760 // only ONE op was negative, we have to do a 16-bit two's complement
3761 emitcode ("setb", "c");
3762 emitcode ("cpl", "a");
3763 emitcode ("addc", "a,#0");
3764 emitcode ("push", "acc"); // lsb
3765 emitcode ("mov", "a,b");
3766 emitcode ("cpl", "a");
3767 emitcode ("addc", "a,#0");
3768 emitcode ("mov", "b,a"); // msb
3769 emitcode ("pop", "acc"); // lsb
3771 emitcode ("", "%05d$:", lbl->key+100);
3772 aopPut (AOP (result), "a", 0);
3773 aopPut (AOP (result), "b", 1);
3776 /*-----------------------------------------------------------------*/
3777 /* genMult - generates code for multiplication */
3778 /*-----------------------------------------------------------------*/
3780 genMult (iCode * ic)
3782 operand *left = IC_LEFT (ic);
3783 operand *right = IC_RIGHT (ic);
3784 operand *result = IC_RESULT (ic);
3786 D (emitcode (";", "genMult ");
3789 /* assign the amsops */
3792 /* special cases first */
3794 if (AOP_TYPE (left) == AOP_CRY &&
3795 AOP_TYPE (right) == AOP_CRY)
3797 genMultbits (left, right, result);
3801 /* if both are of size == 1 */
3802 if (AOP_SIZE (left) == 1 &&
3803 AOP_SIZE (right) == 1)
3805 genMultOneByte (left, right, result);
3809 /* should have been converted to function call */
3813 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3814 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3815 freeAsmop (result, NULL, ic, TRUE);
3818 /*-----------------------------------------------------------------*/
3819 /* genDivbits :- division of bits */
3820 /*-----------------------------------------------------------------*/
3822 genDivbits (operand * left,
3829 /* the result must be bit */
3830 LOAD_AB_FOR_DIV (left, right, l);
3831 emitcode ("div", "ab");
3832 emitcode ("rrc", "a");
3833 aopPut (AOP (result), "c", 0);
3836 /*-----------------------------------------------------------------*/
3837 /* genDivOneByte : 8 bit division */
3838 /*-----------------------------------------------------------------*/
3840 genDivOneByte (operand * left,
3844 sym_link *opetype = operandType (result);
3849 size = AOP_SIZE (result) - 1;
3851 /* signed or unsigned */
3852 if (SPEC_USIGN (opetype))
3854 /* unsigned is easy */
3855 LOAD_AB_FOR_DIV (left, right, l);
3856 emitcode ("div", "ab");
3857 aopPut (AOP (result), "a", 0);
3859 aopPut (AOP (result), zero, offset++);
3863 /* signed is a little bit more difficult */
3865 /* save the signs of the operands */
3866 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3868 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3869 emitcode ("push", "acc"); /* save it on the stack */
3871 /* now sign adjust for both left & right */
3872 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3874 lbl = newiTempLabel (NULL);
3875 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3876 emitcode ("cpl", "a");
3877 emitcode ("inc", "a");
3878 emitcode ("", "%05d$:", (lbl->key + 100));
3879 emitcode ("mov", "b,a");
3881 /* sign adjust left side */
3882 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3885 lbl = newiTempLabel (NULL);
3886 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3887 emitcode ("cpl", "a");
3888 emitcode ("inc", "a");
3889 emitcode ("", "%05d$:", (lbl->key + 100));
3891 /* now the division */
3892 emitcode ("nop", "; workaround for DS80C390 div bug.");
3893 emitcode ("div", "ab");
3894 /* we are interested in the lower order
3896 emitcode ("mov", "b,a");
3897 lbl = newiTempLabel (NULL);
3898 emitcode ("pop", "acc");
3899 /* if there was an over flow we don't
3900 adjust the sign of the result */
3901 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3902 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3904 emitcode ("clr", "a");
3905 emitcode ("subb", "a,b");
3906 emitcode ("mov", "b,a");
3907 emitcode ("", "%05d$:", (lbl->key + 100));
3909 /* now we are done */
3910 aopPut (AOP (result), "b", 0);
3913 emitcode ("mov", "c,b.7");
3914 emitcode ("subb", "a,acc");
3917 aopPut (AOP (result), "a", offset++);
3921 /*-----------------------------------------------------------------*/
3922 /* genDiv - generates code for division */
3923 /*-----------------------------------------------------------------*/
3927 operand *left = IC_LEFT (ic);
3928 operand *right = IC_RIGHT (ic);
3929 operand *result = IC_RESULT (ic);
3931 D (emitcode (";", "genDiv ");
3934 /* assign the amsops */
3937 /* special cases first */
3939 if (AOP_TYPE (left) == AOP_CRY &&
3940 AOP_TYPE (right) == AOP_CRY)
3942 genDivbits (left, right, result);
3946 /* if both are of size == 1 */
3947 if (AOP_SIZE (left) == 1 &&
3948 AOP_SIZE (right) == 1)
3950 genDivOneByte (left, right, result);
3954 /* should have been converted to function call */
3957 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3958 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3959 freeAsmop (result, NULL, ic, TRUE);
3962 /*-----------------------------------------------------------------*/
3963 /* genModbits :- modulus of bits */
3964 /*-----------------------------------------------------------------*/
3966 genModbits (operand * left,
3973 /* the result must be bit */
3974 LOAD_AB_FOR_DIV (left, right, l);
3975 emitcode ("div", "ab");
3976 emitcode ("mov", "a,b");
3977 emitcode ("rrc", "a");
3978 aopPut (AOP (result), "c", 0);
3981 /*-----------------------------------------------------------------*/
3982 /* genModOneByte : 8 bit modulus */
3983 /*-----------------------------------------------------------------*/
3985 genModOneByte (operand * left,
3989 sym_link *opetype = operandType (result);
3993 /* signed or unsigned */
3994 if (SPEC_USIGN (opetype))
3996 /* unsigned is easy */
3997 LOAD_AB_FOR_DIV (left, right, l);
3998 emitcode ("div", "ab");
3999 aopPut (AOP (result), "b", 0);
4003 /* signed is a little bit more difficult */
4005 /* save the signs of the operands */
4006 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4009 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4010 emitcode ("push", "acc"); /* save it on the stack */
4012 /* now sign adjust for both left & right */
4013 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4016 lbl = newiTempLabel (NULL);
4017 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4018 emitcode ("cpl", "a");
4019 emitcode ("inc", "a");
4020 emitcode ("", "%05d$:", (lbl->key + 100));
4021 emitcode ("mov", "b,a");
4023 /* sign adjust left side */
4024 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4027 lbl = newiTempLabel (NULL);
4028 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4029 emitcode ("cpl", "a");
4030 emitcode ("inc", "a");
4031 emitcode ("", "%05d$:", (lbl->key + 100));
4033 /* now the multiplication */
4034 emitcode ("nop", "; workaround for DS80C390 div bug.");
4035 emitcode ("div", "ab");
4036 /* we are interested in the lower order
4038 lbl = newiTempLabel (NULL);
4039 emitcode ("pop", "acc");
4040 /* if there was an over flow we don't
4041 adjust the sign of the result */
4042 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4043 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4045 emitcode ("clr", "a");
4046 emitcode ("subb", "a,b");
4047 emitcode ("mov", "b,a");
4048 emitcode ("", "%05d$:", (lbl->key + 100));
4050 /* now we are done */
4051 aopPut (AOP (result), "b", 0);
4055 /*-----------------------------------------------------------------*/
4056 /* genMod - generates code for division */
4057 /*-----------------------------------------------------------------*/
4061 operand *left = IC_LEFT (ic);
4062 operand *right = IC_RIGHT (ic);
4063 operand *result = IC_RESULT (ic);
4065 D (emitcode (";", "genMod ");
4068 /* assign the amsops */
4071 /* special cases first */
4073 if (AOP_TYPE (left) == AOP_CRY &&
4074 AOP_TYPE (right) == AOP_CRY)
4076 genModbits (left, right, result);
4080 /* if both are of size == 1 */
4081 if (AOP_SIZE (left) == 1 &&
4082 AOP_SIZE (right) == 1)
4084 genModOneByte (left, right, result);
4088 /* should have been converted to function call */
4092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4094 freeAsmop (result, NULL, ic, TRUE);
4097 /*-----------------------------------------------------------------*/
4098 /* genIfxJump :- will create a jump depending on the ifx */
4099 /*-----------------------------------------------------------------*/
4101 genIfxJump (iCode * ic, char *jval)
4104 symbol *tlbl = newiTempLabel (NULL);
4107 D (emitcode (";", "genIfxJump ");
4110 /* if true label then we jump if condition
4114 jlbl = IC_TRUE (ic);
4115 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4116 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4120 /* false label is present */
4121 jlbl = IC_FALSE (ic);
4122 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4123 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4125 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4126 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4128 emitcode (inst, "%05d$", tlbl->key + 100);
4129 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4130 emitcode ("", "%05d$:", tlbl->key + 100);
4132 /* mark the icode as generated */
4136 /*-----------------------------------------------------------------*/
4137 /* genCmp :- greater or less than comparison */
4138 /*-----------------------------------------------------------------*/
4140 genCmp (operand * left, operand * right,
4141 iCode * ic, iCode * ifx, int sign)
4143 int size, offset = 0;
4144 unsigned long lit = 0L;
4147 D (emitcode (";", "genCmp");
4150 result = IC_RESULT (ic);
4152 /* if left & right are bit variables */
4153 if (AOP_TYPE (left) == AOP_CRY &&
4154 AOP_TYPE (right) == AOP_CRY)
4156 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4157 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4161 /* subtract right from left if at the
4162 end the carry flag is set then we know that
4163 left is greater than right */
4164 size = max (AOP_SIZE (left), AOP_SIZE (right));
4166 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4167 if ((size == 1) && !sign &&
4168 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4170 symbol *lbl = newiTempLabel (NULL);
4171 emitcode ("cjne", "%s,%s,%05d$",
4172 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4173 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4175 emitcode ("", "%05d$:", lbl->key + 100);
4179 if (AOP_TYPE (right) == AOP_LIT)
4181 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4182 /* optimize if(x < 0) or if(x >= 0) */
4191 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4193 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4194 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4196 aopOp (result, ic, FALSE, FALSE);
4198 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4200 freeAsmop (result, NULL, ic, TRUE);
4201 genIfxJump (ifx, "acc.7");
4206 emitcode ("rlc", "a");
4208 goto release_freedLR;
4216 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4217 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4218 emitcode (";", "genCmp #2");
4219 if (sign && (size == 0))
4221 emitcode (";", "genCmp #3");
4222 emitcode ("xrl", "a,#0x80");
4223 if (AOP_TYPE (right) == AOP_LIT)
4225 unsigned long lit = (unsigned long)
4226 floatFromVal (AOP (right)->aopu.aop_lit);
4227 emitcode (";", "genCmp #3.1");
4228 emitcode ("subb", "a,#0x%02x",
4229 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4233 emitcode (";", "genCmp #3.2");
4234 if (AOP_NEEDSACC (right))
4236 emitcode ("push", "acc");
4238 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4239 FALSE, FALSE, FALSE));
4240 emitcode ("xrl", "b,#0x80");
4241 if (AOP_NEEDSACC (right))
4243 emitcode ("pop", "acc");
4245 emitcode ("subb", "a,b");
4252 emitcode (";", "genCmp #4");
4253 if (AOP_NEEDSACC (right))
4256 emitcode (";", "genCmp #4.1");
4257 emitcode ("xch", "a, b");
4258 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4259 emitcode ("xch", "a, b");
4264 emitcode (";", "genCmp #4.2");
4265 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4268 emitcode ("subb", "a,%s", s);
4275 /* Don't need the left & right operands any more; do need the result. */
4276 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4277 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4279 aopOp (result, ic, FALSE, FALSE);
4283 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4289 /* if the result is used in the next
4290 ifx conditional branch then generate
4291 code a little differently */
4294 genIfxJump (ifx, "c");
4300 /* leave the result in acc */
4302 freeAsmop (result, NULL, ic, TRUE);
4305 /*-----------------------------------------------------------------*/
4306 /* genCmpGt :- greater than comparison */
4307 /*-----------------------------------------------------------------*/
4309 genCmpGt (iCode * ic, iCode * ifx)
4311 operand *left, *right;
4312 sym_link *letype, *retype;
4315 D (emitcode (";", "genCmpGt ");
4318 left = IC_LEFT (ic);
4319 right = IC_RIGHT (ic);
4321 letype = getSpec (operandType (left));
4322 retype = getSpec (operandType (right));
4323 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4325 /* assign the left & right amsops */
4328 genCmp (right, left, ic, ifx, sign);
4331 /*-----------------------------------------------------------------*/
4332 /* genCmpLt - less than comparisons */
4333 /*-----------------------------------------------------------------*/
4335 genCmpLt (iCode * ic, iCode * ifx)
4337 operand *left, *right;
4338 sym_link *letype, *retype;
4341 D (emitcode (";", "genCmpLt ");
4344 left = IC_LEFT (ic);
4345 right = IC_RIGHT (ic);
4347 letype = getSpec (operandType (left));
4348 retype = getSpec (operandType (right));
4349 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4351 /* assign the left & right amsops */
4354 genCmp (left, right, ic, ifx, sign);
4357 /*-----------------------------------------------------------------*/
4358 /* gencjneshort - compare and jump if not equal */
4359 /*-----------------------------------------------------------------*/
4361 gencjneshort (operand * left, operand * right, symbol * lbl)
4363 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4365 unsigned long lit = 0L;
4367 D (emitcode (";", "gencjneshort");
4370 /* if the left side is a literal or
4371 if the right is in a pointer register and left
4373 if ((AOP_TYPE (left) == AOP_LIT) ||
4374 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4381 if (AOP_TYPE (right) == AOP_LIT)
4382 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4384 if (opIsGptr (left) || opIsGptr (right))
4386 /* We are comparing a generic pointer to something.
4387 * Exclude the generic type byte from the comparison.
4390 D (emitcode (";", "cjneshort: generic ptr special case.");
4395 /* if the right side is a literal then anything goes */
4396 if (AOP_TYPE (right) == AOP_LIT &&
4397 AOP_TYPE (left) != AOP_DIR)
4401 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4403 emitcode ("cjne", "a,%s,%05d$",
4404 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4410 /* if the right side is in a register or in direct space or
4411 if the left is a pointer register & right is not */
4412 else if (AOP_TYPE (right) == AOP_REG ||
4413 AOP_TYPE (right) == AOP_DIR ||
4414 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4415 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4419 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4420 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4421 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4422 emitcode ("jnz", "%05d$", lbl->key + 100);
4424 emitcode ("cjne", "a,%s,%05d$",
4425 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4432 /* right is a pointer reg need both a & b */
4435 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4436 if (strcmp (l, "b"))
4437 emitcode ("mov", "b,%s", l);
4438 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4439 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4445 /*-----------------------------------------------------------------*/
4446 /* gencjne - compare and jump if not equal */
4447 /*-----------------------------------------------------------------*/
4449 gencjne (operand * left, operand * right, symbol * lbl)
4451 symbol *tlbl = newiTempLabel (NULL);
4453 D (emitcode (";", "gencjne");
4456 gencjneshort (left, right, lbl);
4458 emitcode ("mov", "a,%s", one);
4459 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4460 emitcode ("", "%05d$:", lbl->key + 100);
4461 emitcode ("clr", "a");
4462 emitcode ("", "%05d$:", tlbl->key + 100);
4465 /*-----------------------------------------------------------------*/
4466 /* genCmpEq - generates code for equal to */
4467 /*-----------------------------------------------------------------*/
4469 genCmpEq (iCode * ic, iCode * ifx)
4471 operand *left, *right, *result;
4473 D (emitcode (";", "genCmpEq ");
4477 AOP_SET_LOCALS (ic);
4479 /* if literal, literal on the right or
4480 if the right is in a pointer register and left
4482 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4483 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4485 operand *t = IC_RIGHT (ic);
4486 IC_RIGHT (ic) = IC_LEFT (ic);
4490 if (ifx && /* !AOP_SIZE(result) */
4491 OP_SYMBOL (result) &&
4492 OP_SYMBOL (result)->regType == REG_CND)
4495 /* if they are both bit variables */
4496 if (AOP_TYPE (left) == AOP_CRY &&
4497 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4499 if (AOP_TYPE (right) == AOP_LIT)
4501 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4504 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4505 emitcode ("cpl", "c");
4509 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513 emitcode ("clr", "c");
4515 /* AOP_TYPE(right) == AOP_CRY */
4519 symbol *lbl = newiTempLabel (NULL);
4520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4521 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4522 emitcode ("cpl", "c");
4523 emitcode ("", "%05d$:", (lbl->key + 100));
4525 /* if true label then we jump if condition
4527 tlbl = newiTempLabel (NULL);
4530 emitcode ("jnc", "%05d$", tlbl->key + 100);
4531 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4535 emitcode ("jc", "%05d$", tlbl->key + 100);
4536 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4538 emitcode ("", "%05d$:", tlbl->key + 100);
4542 tlbl = newiTempLabel (NULL);
4543 gencjneshort (left, right, tlbl);
4546 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4547 emitcode ("", "%05d$:", tlbl->key + 100);
4551 symbol *lbl = newiTempLabel (NULL);
4552 emitcode ("sjmp", "%05d$", lbl->key + 100);
4553 emitcode ("", "%05d$:", tlbl->key + 100);
4554 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4555 emitcode ("", "%05d$:", lbl->key + 100);
4558 /* mark the icode as generated */
4561 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4562 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4566 /* if they are both bit variables */
4567 if (AOP_TYPE (left) == AOP_CRY &&
4568 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4570 if (AOP_TYPE (right) == AOP_LIT)
4572 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4575 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4576 emitcode ("cpl", "c");
4580 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4584 emitcode ("clr", "c");
4586 /* AOP_TYPE(right) == AOP_CRY */
4590 symbol *lbl = newiTempLabel (NULL);
4591 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4592 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4593 emitcode ("cpl", "c");
4594 emitcode ("", "%05d$:", (lbl->key + 100));
4597 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4600 aopOp (result, ic, TRUE, FALSE);
4603 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4610 genIfxJump (ifx, "c");
4613 /* if the result is used in an arithmetic operation
4614 then put the result in place */
4619 gencjne (left, right, newiTempLabel (NULL));
4621 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4622 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4624 aopOp (result, ic, TRUE, FALSE);
4626 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4628 aopPut (AOP (result), "a", 0);
4633 genIfxJump (ifx, "a");
4636 /* if the result is used in an arithmetic operation
4637 then put the result in place */
4638 if (AOP_TYPE (result) != AOP_CRY)
4640 /* leave the result in acc */
4644 freeAsmop (result, NULL, ic, TRUE);
4647 /*-----------------------------------------------------------------*/
4648 /* ifxForOp - returns the icode containing the ifx for operand */
4649 /*-----------------------------------------------------------------*/
4651 ifxForOp (operand * op, iCode * ic)
4653 /* if true symbol then needs to be assigned */
4654 if (IS_TRUE_SYMOP (op))
4657 /* if this has register type condition and
4658 the next instruction is ifx with the same operand
4659 and live to of the operand is upto the ifx only then */
4661 ic->next->op == IFX &&
4662 IC_COND (ic->next)->key == op->key &&
4663 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4668 /*-----------------------------------------------------------------*/
4669 /* genAndOp - for && operation */
4670 /*-----------------------------------------------------------------*/
4672 genAndOp (iCode * ic)
4674 operand *left, *right, *result;
4677 D (emitcode (";", "genAndOp ");
4680 /* note here that && operations that are in an
4681 if statement are taken away by backPatchLabels
4682 only those used in arthmetic operations remain */
4684 AOP_SET_LOCALS (ic);
4686 /* if both are bit variables */
4687 if (AOP_TYPE (left) == AOP_CRY &&
4688 AOP_TYPE (right) == AOP_CRY)
4690 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4691 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4696 tlbl = newiTempLabel (NULL);
4698 emitcode ("jz", "%05d$", tlbl->key + 100);
4700 emitcode ("", "%05d$:", tlbl->key + 100);
4704 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706 freeAsmop (result, NULL, ic, TRUE);
4710 /*-----------------------------------------------------------------*/
4711 /* genOrOp - for || operation */
4712 /*-----------------------------------------------------------------*/
4714 genOrOp (iCode * ic)
4716 operand *left, *right, *result;
4719 D (emitcode (";", "genOrOp ");
4722 /* note here that || operations that are in an
4723 if statement are taken away by backPatchLabels
4724 only those used in arthmetic operations remain */
4726 AOP_SET_LOCALS (ic);
4728 /* if both are bit variables */
4729 if (AOP_TYPE (left) == AOP_CRY &&
4730 AOP_TYPE (right) == AOP_CRY)
4732 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4733 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4738 tlbl = newiTempLabel (NULL);
4740 emitcode ("jnz", "%05d$", tlbl->key + 100);
4742 emitcode ("", "%05d$:", tlbl->key + 100);
4746 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4747 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748 freeAsmop (result, NULL, ic, TRUE);
4751 /*-----------------------------------------------------------------*/
4752 /* isLiteralBit - test if lit == 2^n */
4753 /*-----------------------------------------------------------------*/
4755 isLiteralBit (unsigned long lit)
4757 unsigned long pw[32] =
4758 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4759 0x100L, 0x200L, 0x400L, 0x800L,
4760 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4761 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4762 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4763 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4764 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4767 for (idx = 0; idx < 32; idx++)
4773 /*-----------------------------------------------------------------*/
4774 /* continueIfTrue - */
4775 /*-----------------------------------------------------------------*/
4777 continueIfTrue (iCode * ic)
4780 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4784 /*-----------------------------------------------------------------*/
4786 /*-----------------------------------------------------------------*/
4788 jumpIfTrue (iCode * ic)
4791 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4795 /*-----------------------------------------------------------------*/
4796 /* jmpTrueOrFalse - */
4797 /*-----------------------------------------------------------------*/
4799 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4801 // ugly but optimized by peephole
4804 symbol *nlbl = newiTempLabel (NULL);
4805 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4806 emitcode ("", "%05d$:", tlbl->key + 100);
4807 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4808 emitcode ("", "%05d$:", nlbl->key + 100);
4812 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4813 emitcode ("", "%05d$:", tlbl->key + 100);
4818 /*-----------------------------------------------------------------*/
4819 /* genAnd - code for and */
4820 /*-----------------------------------------------------------------*/
4822 genAnd (iCode * ic, iCode * ifx)
4824 operand *left, *right, *result;
4825 int size, offset = 0;
4826 unsigned long lit = 0L;
4830 D (emitcode (";", "genAnd ");
4834 AOP_SET_LOCALS (ic);
4837 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4839 AOP_TYPE (left), AOP_TYPE (right));
4840 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4842 AOP_SIZE (left), AOP_SIZE (right));
4845 /* if left is a literal & right is not then exchange them */
4846 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4847 AOP_NEEDSACC (left))
4849 operand *tmp = right;
4854 /* if result = right then exchange them */
4855 if (sameRegs (AOP (result), AOP (right)))
4857 operand *tmp = right;
4862 /* if right is bit then exchange them */
4863 if (AOP_TYPE (right) == AOP_CRY &&
4864 AOP_TYPE (left) != AOP_CRY)
4866 operand *tmp = right;
4870 if (AOP_TYPE (right) == AOP_LIT)
4871 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4873 size = AOP_SIZE (result);
4876 // result = bit & yy;
4877 if (AOP_TYPE (left) == AOP_CRY)
4879 // c = bit & literal;
4880 if (AOP_TYPE (right) == AOP_LIT)
4884 if (size && sameRegs (AOP (result), AOP (left)))
4887 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4892 if (size && (AOP_TYPE (result) == AOP_CRY))
4894 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4897 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4902 emitcode ("clr", "c");
4907 if (AOP_TYPE (right) == AOP_CRY)
4910 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4911 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4916 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4918 emitcode ("rrc", "a");
4919 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4927 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4928 genIfxJump (ifx, "c");
4932 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4933 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4934 if ((AOP_TYPE (right) == AOP_LIT) &&
4935 (AOP_TYPE (result) == AOP_CRY) &&
4936 (AOP_TYPE (left) != AOP_CRY))
4938 int posbit = isLiteralBit (lit);
4943 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4946 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4952 sprintf (buffer, "acc.%d", posbit & 0x07);
4953 genIfxJump (ifx, buffer);
4960 symbol *tlbl = newiTempLabel (NULL);
4961 int sizel = AOP_SIZE (left);
4963 emitcode ("setb", "c");
4966 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4968 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4970 if ((posbit = isLiteralBit (bytelit)) != 0)
4971 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4974 if (bytelit != 0x0FFL)
4975 emitcode ("anl", "a,%s",
4976 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4977 emitcode ("jnz", "%05d$", tlbl->key + 100);
4982 // bit = left & literal
4985 emitcode ("clr", "c");
4986 emitcode ("", "%05d$:", tlbl->key + 100);
4988 // if(left & literal)
4992 jmpTrueOrFalse (ifx, tlbl);
5000 /* if left is same as result */
5001 if (sameRegs (AOP (result), AOP (left)))
5003 for (; size--; offset++)
5005 if (AOP_TYPE (right) == AOP_LIT)
5007 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5009 else if (bytelit == 0)
5010 aopPut (AOP (result), zero, offset);
5011 else if (IS_AOP_PREG (result))
5013 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5014 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5015 aopPut (AOP (result), "a", offset);
5018 emitcode ("anl", "%s,%s",
5019 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5020 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5024 if (AOP_TYPE (left) == AOP_ACC)
5025 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5028 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5029 if (IS_AOP_PREG (result))
5031 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5032 aopPut (AOP (result), "a", offset);
5036 emitcode ("anl", "%s,a",
5037 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5044 // left & result in different registers
5045 if (AOP_TYPE (result) == AOP_CRY)
5048 // if(size), result in bit
5049 // if(!size && ifx), conditional oper: if(left & right)
5050 symbol *tlbl = newiTempLabel (NULL);
5051 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5053 emitcode ("setb", "c");
5056 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5057 emitcode ("anl", "a,%s",
5058 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5059 emitcode ("jnz", "%05d$", tlbl->key + 100);
5065 emitcode ("", "%05d$:", tlbl->key + 100);
5069 jmpTrueOrFalse (ifx, tlbl);
5073 for (; (size--); offset++)
5076 // result = left & right
5077 if (AOP_TYPE (right) == AOP_LIT)
5079 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5081 aopPut (AOP (result),
5082 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5086 else if (bytelit == 0)
5088 aopPut (AOP (result), zero, offset);
5091 D (emitcode (";", "better literal AND.");
5093 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5094 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5095 FALSE, FALSE, FALSE));
5100 // faster than result <- left, anl result,right
5101 // and better if result is SFR
5102 if (AOP_TYPE (left) == AOP_ACC)
5104 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5105 FALSE, FALSE, FALSE));
5109 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5110 emitcode ("anl", "a,%s",
5111 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5114 aopPut (AOP (result), "a", offset);
5120 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5121 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122 freeAsmop (result, NULL, ic, TRUE);
5125 /*-----------------------------------------------------------------*/
5126 /* genOr - code for or */
5127 /*-----------------------------------------------------------------*/
5129 genOr (iCode * ic, iCode * ifx)
5131 operand *left, *right, *result;
5132 int size, offset = 0;
5133 unsigned long lit = 0L;
5135 D (emitcode (";", "genOr ");
5139 AOP_SET_LOCALS (ic);
5142 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5144 AOP_TYPE (left), AOP_TYPE (right));
5145 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5147 AOP_SIZE (left), AOP_SIZE (right));
5150 /* if left is a literal & right is not then exchange them */
5151 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5152 AOP_NEEDSACC (left))
5154 operand *tmp = right;
5159 /* if result = right then exchange them */
5160 if (sameRegs (AOP (result), AOP (right)))
5162 operand *tmp = right;
5167 /* if right is bit then exchange them */
5168 if (AOP_TYPE (right) == AOP_CRY &&
5169 AOP_TYPE (left) != AOP_CRY)
5171 operand *tmp = right;
5175 if (AOP_TYPE (right) == AOP_LIT)
5176 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5178 size = AOP_SIZE (result);
5182 if (AOP_TYPE (left) == AOP_CRY)
5184 if (AOP_TYPE (right) == AOP_LIT)
5186 // c = bit & literal;
5189 // lit != 0 => result = 1
5190 if (AOP_TYPE (result) == AOP_CRY)
5193 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5195 continueIfTrue (ifx);
5198 emitcode ("setb", "c");
5202 // lit == 0 => result = left
5203 if (size && sameRegs (AOP (result), AOP (left)))
5205 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5210 if (AOP_TYPE (right) == AOP_CRY)
5213 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5214 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5219 symbol *tlbl = newiTempLabel (NULL);
5220 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5221 emitcode ("setb", "c");
5222 emitcode ("jb", "%s,%05d$",
5223 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5225 emitcode ("jnz", "%05d$", tlbl->key + 100);
5226 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5228 jmpTrueOrFalse (ifx, tlbl);
5234 emitcode ("", "%05d$:", tlbl->key + 100);
5243 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5244 genIfxJump (ifx, "c");
5248 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5249 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5250 if ((AOP_TYPE (right) == AOP_LIT) &&
5251 (AOP_TYPE (result) == AOP_CRY) &&
5252 (AOP_TYPE (left) != AOP_CRY))
5258 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5260 continueIfTrue (ifx);
5265 // lit = 0, result = boolean(left)
5267 emitcode ("setb", "c");
5271 symbol *tlbl = newiTempLabel (NULL);
5272 emitcode ("jnz", "%05d$", tlbl->key + 100);
5274 emitcode ("", "%05d$:", tlbl->key + 100);
5278 genIfxJump (ifx, "a");
5286 /* if left is same as result */
5287 if (sameRegs (AOP (result), AOP (left)))
5289 for (; size--; offset++)
5291 if (AOP_TYPE (right) == AOP_LIT)
5293 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5299 if (IS_AOP_PREG (left))
5301 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5302 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5303 aopPut (AOP (result), "a", offset);
5307 emitcode ("orl", "%s,%s",
5308 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5309 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5315 if (AOP_TYPE (left) == AOP_ACC)
5317 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5321 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5322 if (IS_AOP_PREG (left))
5324 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5325 aopPut (AOP (result), "a", offset);
5329 emitcode ("orl", "%s,a",
5330 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5338 // left & result in different registers
5339 if (AOP_TYPE (result) == AOP_CRY)
5342 // if(size), result in bit
5343 // if(!size && ifx), conditional oper: if(left | right)
5344 symbol *tlbl = newiTempLabel (NULL);
5345 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5347 emitcode ("setb", "c");
5350 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5351 emitcode ("orl", "a,%s",
5352 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5353 emitcode ("jnz", "%05d$", tlbl->key + 100);
5359 emitcode ("", "%05d$:", tlbl->key + 100);
5363 jmpTrueOrFalse (ifx, tlbl);
5367 for (; (size--); offset++)
5370 // result = left & right
5371 if (AOP_TYPE (right) == AOP_LIT)
5373 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5375 aopPut (AOP (result),
5376 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5380 D (emitcode (";", "better literal OR.");
5382 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5383 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5384 FALSE, FALSE, FALSE));
5389 // faster than result <- left, anl result,right
5390 // and better if result is SFR
5391 if (AOP_TYPE (left) == AOP_ACC)
5393 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5394 FALSE, FALSE, FALSE));
5398 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5399 emitcode ("orl", "a,%s",
5400 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5403 aopPut (AOP (result), "a", offset);
5409 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5410 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5411 freeAsmop (result, NULL, ic, TRUE);
5414 /*-----------------------------------------------------------------*/
5415 /* genXor - code for xclusive or */
5416 /*-----------------------------------------------------------------*/
5418 genXor (iCode * ic, iCode * ifx)
5420 operand *left, *right, *result;
5421 int size, offset = 0;
5422 unsigned long lit = 0L;
5424 D (emitcode (";", "genXor ");
5428 AOP_SET_LOCALS (ic);
5431 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5433 AOP_TYPE (left), AOP_TYPE (right));
5434 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5436 AOP_SIZE (left), AOP_SIZE (right));
5439 /* if left is a literal & right is not ||
5440 if left needs acc & right does not */
5441 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5442 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5444 operand *tmp = right;
5449 /* if result = right then exchange them */
5450 if (sameRegs (AOP (result), AOP (right)))
5452 operand *tmp = right;
5457 /* if right is bit then exchange them */
5458 if (AOP_TYPE (right) == AOP_CRY &&
5459 AOP_TYPE (left) != AOP_CRY)
5461 operand *tmp = right;
5465 if (AOP_TYPE (right) == AOP_LIT)
5466 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5468 size = AOP_SIZE (result);
5472 if (AOP_TYPE (left) == AOP_CRY)
5474 if (AOP_TYPE (right) == AOP_LIT)
5476 // c = bit & literal;
5479 // lit>>1 != 0 => result = 1
5480 if (AOP_TYPE (result) == AOP_CRY)
5483 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5485 continueIfTrue (ifx);
5488 emitcode ("setb", "c");
5495 // lit == 0, result = left
5496 if (size && sameRegs (AOP (result), AOP (left)))
5498 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5502 // lit == 1, result = not(left)
5503 if (size && sameRegs (AOP (result), AOP (left)))
5505 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5510 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5511 emitcode ("cpl", "c");
5520 symbol *tlbl = newiTempLabel (NULL);
5521 if (AOP_TYPE (right) == AOP_CRY)
5524 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5528 int sizer = AOP_SIZE (right);
5530 // if val>>1 != 0, result = 1
5531 emitcode ("setb", "c");
5534 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5536 // test the msb of the lsb
5537 emitcode ("anl", "a,#0xfe");
5538 emitcode ("jnz", "%05d$", tlbl->key + 100);
5542 emitcode ("rrc", "a");
5544 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5545 emitcode ("cpl", "c");
5546 emitcode ("", "%05d$:", (tlbl->key + 100));
5553 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5554 genIfxJump (ifx, "c");
5558 if (sameRegs (AOP (result), AOP (left)))
5560 /* if left is same as result */
5561 for (; size--; offset++)
5563 if (AOP_TYPE (right) == AOP_LIT)
5565 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5567 else if (IS_AOP_PREG (left))
5569 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5570 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5571 aopPut (AOP (result), "a", offset);
5574 emitcode ("xrl", "%s,%s",
5575 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5576 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5580 if (AOP_TYPE (left) == AOP_ACC)
5581 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5584 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5585 if (IS_AOP_PREG (left))
5587 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5588 aopPut (AOP (result), "a", offset);
5591 emitcode ("xrl", "%s,a",
5592 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5599 // left & result in different registers
5600 if (AOP_TYPE (result) == AOP_CRY)
5603 // if(size), result in bit
5604 // if(!size && ifx), conditional oper: if(left ^ right)
5605 symbol *tlbl = newiTempLabel (NULL);
5606 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5608 emitcode ("setb", "c");
5611 if ((AOP_TYPE (right) == AOP_LIT) &&
5612 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5614 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5618 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5619 emitcode ("xrl", "a,%s",
5620 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5622 emitcode ("jnz", "%05d$", tlbl->key + 100);
5628 emitcode ("", "%05d$:", tlbl->key + 100);
5632 jmpTrueOrFalse (ifx, tlbl);
5635 for (; (size--); offset++)
5638 // result = left & right
5639 if (AOP_TYPE (right) == AOP_LIT)
5641 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5643 aopPut (AOP (result),
5644 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5648 D (emitcode (";", "better literal XOR.");
5650 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5651 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5652 FALSE, FALSE, FALSE));
5656 // faster than result <- left, anl result,right
5657 // and better if result is SFR
5658 if (AOP_TYPE (left) == AOP_ACC)
5660 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5661 FALSE, FALSE, FALSE));
5665 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5666 emitcode ("xrl", "a,%s",
5667 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5670 aopPut (AOP (result), "a", offset);
5675 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5676 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5677 freeAsmop (result, NULL, ic, TRUE);
5680 /*-----------------------------------------------------------------*/
5681 /* genInline - write the inline code out */
5682 /*-----------------------------------------------------------------*/
5684 genInline (iCode * ic)
5686 char buffer[MAX_INLINEASM];
5690 D (emitcode (";", "genInline ");
5693 _G.inLine += (!options.asmpeep);
5694 strcpy (buffer, IC_INLINE (ic));
5696 /* emit each line as a code */
5721 /* emitcode("",buffer); */
5722 _G.inLine -= (!options.asmpeep);
5725 /*-----------------------------------------------------------------*/
5726 /* genRRC - rotate right with carry */
5727 /*-----------------------------------------------------------------*/
5731 operand *left, *result;
5732 int size, offset = 0;
5735 D (emitcode (";", "genRRC ");
5738 /* rotate right with carry */
5739 left = IC_LEFT (ic);
5740 result = IC_RESULT (ic);
5741 aopOp (left, ic, FALSE, FALSE);
5742 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5744 /* move it to the result */
5745 size = AOP_SIZE (result);
5749 _startLazyDPSEvaluation ();
5752 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5754 emitcode ("rrc", "a");
5755 if (AOP_SIZE (result) > 1)
5756 aopPut (AOP (result), "a", offset--);
5758 _endLazyDPSEvaluation ();
5760 /* now we need to put the carry into the
5761 highest order byte of the result */
5762 if (AOP_SIZE (result) > 1)
5764 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5767 emitcode ("mov", "acc.7,c");
5768 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5769 freeAsmop (left, NULL, ic, TRUE);
5770 freeAsmop (result, NULL, ic, TRUE);
5773 /*-----------------------------------------------------------------*/
5774 /* genRLC - generate code for rotate left with carry */
5775 /*-----------------------------------------------------------------*/
5779 operand *left, *result;
5780 int size, offset = 0;
5783 D (emitcode (";", "genRLC ");
5786 /* rotate right with carry */
5787 left = IC_LEFT (ic);
5788 result = IC_RESULT (ic);
5789 aopOp (left, ic, FALSE, FALSE);
5790 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5792 /* move it to the result */
5793 size = AOP_SIZE (result);
5797 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5799 emitcode ("add", "a,acc");
5800 if (AOP_SIZE (result) > 1)
5802 aopPut (AOP (result), "a", offset++);
5805 _startLazyDPSEvaluation ();
5808 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5810 emitcode ("rlc", "a");
5811 if (AOP_SIZE (result) > 1)
5812 aopPut (AOP (result), "a", offset++);
5814 _endLazyDPSEvaluation ();
5816 /* now we need to put the carry into the
5817 highest order byte of the result */
5818 if (AOP_SIZE (result) > 1)
5820 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5823 emitcode ("mov", "acc.0,c");
5824 aopPut (AOP (result), "a", 0);
5825 freeAsmop (left, NULL, ic, TRUE);
5826 freeAsmop (result, NULL, ic, TRUE);
5829 /*-----------------------------------------------------------------*/
5830 /* genGetHbit - generates code get highest order bit */
5831 /*-----------------------------------------------------------------*/
5833 genGetHbit (iCode * ic)
5835 operand *left, *result;
5836 left = IC_LEFT (ic);
5837 result = IC_RESULT (ic);
5838 aopOp (left, ic, FALSE, FALSE);
5839 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5841 D (emitcode (";", "genGetHbit ");
5844 /* get the highest order byte into a */
5845 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5846 if (AOP_TYPE (result) == AOP_CRY)
5848 emitcode ("rlc", "a");
5853 emitcode ("rl", "a");
5854 emitcode ("anl", "a,#0x01");
5859 freeAsmop (left, NULL, ic, TRUE);
5860 freeAsmop (result, NULL, ic, TRUE);
5863 /*-----------------------------------------------------------------*/
5864 /* AccRol - rotate left accumulator by known count */
5865 /*-----------------------------------------------------------------*/
5867 AccRol (int shCount)
5869 shCount &= 0x0007; // shCount : 0..7
5876 emitcode ("rl", "a");
5879 emitcode ("rl", "a");
5880 emitcode ("rl", "a");
5883 emitcode ("swap", "a");
5884 emitcode ("rr", "a");
5887 emitcode ("swap", "a");
5890 emitcode ("swap", "a");
5891 emitcode ("rl", "a");
5894 emitcode ("rr", "a");
5895 emitcode ("rr", "a");
5898 emitcode ("rr", "a");
5903 /*-----------------------------------------------------------------*/
5904 /* AccLsh - left shift accumulator by known count */
5905 /*-----------------------------------------------------------------*/
5907 AccLsh (int shCount)
5912 emitcode ("add", "a,acc");
5913 else if (shCount == 2)
5915 emitcode ("add", "a,acc");
5916 emitcode ("add", "a,acc");
5920 /* rotate left accumulator */
5922 /* and kill the lower order bits */
5923 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5928 /*-----------------------------------------------------------------*/
5929 /* AccRsh - right shift accumulator by known count */
5930 /*-----------------------------------------------------------------*/
5932 AccRsh (int shCount)
5939 emitcode ("rrc", "a");
5943 /* rotate right accumulator */
5944 AccRol (8 - shCount);
5945 /* and kill the higher order bits */
5946 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5953 /*-----------------------------------------------------------------*/
5954 /* AccSRsh - signed right shift accumulator by known count */
5955 /*-----------------------------------------------------------------*/
5957 AccSRsh (int shCount)
5964 emitcode ("mov", "c,acc.7");
5965 emitcode ("rrc", "a");
5967 else if (shCount == 2)
5969 emitcode ("mov", "c,acc.7");
5970 emitcode ("rrc", "a");
5971 emitcode ("mov", "c,acc.7");
5972 emitcode ("rrc", "a");
5976 tlbl = newiTempLabel (NULL);
5977 /* rotate right accumulator */
5978 AccRol (8 - shCount);
5979 /* and kill the higher order bits */
5980 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5981 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5982 emitcode ("orl", "a,#0x%02x",
5983 (unsigned char) ~SRMask[shCount]);
5984 emitcode ("", "%05d$:", tlbl->key + 100);
5992 /*-----------------------------------------------------------------*/
5993 /* shiftR1Left2Result - shift right one byte from left to result */
5994 /*-----------------------------------------------------------------*/
5996 shiftR1Left2Result (operand * left, int offl,
5997 operand * result, int offr,
5998 int shCount, int sign)
6000 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6001 /* shift right accumulator */
6006 aopPut (AOP (result), "a", offr);
6012 /*-----------------------------------------------------------------*/
6013 /* shiftL1Left2Result - shift left one byte from left to result */
6014 /*-----------------------------------------------------------------*/
6016 shiftL1Left2Result (operand * left, int offl,
6017 operand * result, int offr, int shCount)
6020 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6022 /* shift left accumulator */
6024 aopPut (AOP (result), "a", offr);
6030 /*-----------------------------------------------------------------*/
6031 /* movLeft2Result - move byte from left to result */
6032 /*-----------------------------------------------------------------*/
6034 movLeft2Result (operand * left, int offl,
6035 operand * result, int offr, int sign)
6038 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6040 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6042 if (*l == '@' && (IS_AOP_PREG (result)))
6044 emitcode ("mov", "a,%s", l);
6045 aopPut (AOP (result), "a", offr);
6050 aopPut (AOP (result), l, offr);
6053 /* MSB sign in acc.7 ! */
6054 if (getDataSize (left) == offl + 1)
6056 emitcode ("mov", "a,%s", l);
6057 aopPut (AOP (result), "a", offr);
6067 /*-----------------------------------------------------------------*/
6068 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6069 /*-----------------------------------------------------------------*/
6073 emitcode ("rrc", "a");
6074 emitcode ("xch", "a,%s", x);
6075 emitcode ("rrc", "a");
6076 emitcode ("xch", "a,%s", x);
6082 /*-----------------------------------------------------------------*/
6083 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6084 /*-----------------------------------------------------------------*/
6088 emitcode ("xch", "a,%s", x);
6089 emitcode ("rlc", "a");
6090 emitcode ("xch", "a,%s", x);
6091 emitcode ("rlc", "a");
6097 /*-----------------------------------------------------------------*/
6098 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6099 /*-----------------------------------------------------------------*/
6103 emitcode ("xch", "a,%s", x);
6104 emitcode ("add", "a,acc");
6105 emitcode ("xch", "a,%s", x);
6106 emitcode ("rlc", "a");
6112 /*-----------------------------------------------------------------*/
6113 /* AccAXLsh - left shift a:x by known count (0..7) */
6114 /*-----------------------------------------------------------------*/
6116 AccAXLsh (char *x, int shCount)
6131 case 5: // AAAAABBB:CCCCCDDD
6133 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6135 emitcode ("anl", "a,#0x%02x",
6136 SLMask[shCount]); // BBB00000:CCCCCDDD
6138 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6140 AccRol (shCount); // DDDCCCCC:BBB00000
6142 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6144 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6146 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6148 emitcode ("anl", "a,#0x%02x",
6149 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6151 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6153 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6156 case 6: // AAAAAABB:CCCCCCDD
6158 emitcode ("anl", "a,#0x%02x",
6159 SRMask[shCount]); // 000000BB:CCCCCCDD
6161 emitcode ("mov", "c,acc.0"); // c = B
6163 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6165 AccAXRrl1 (x); // BCCCCCCD:D000000B
6167 AccAXRrl1 (x); // BBCCCCCC:DD000000
6170 case 7: // a:x <<= 7
6172 emitcode ("anl", "a,#0x%02x",
6173 SRMask[shCount]); // 0000000B:CCCCCCCD
6175 emitcode ("mov", "c,acc.0"); // c = B
6177 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6179 AccAXRrl1 (x); // BCCCCCCC:D0000000
6190 /*-----------------------------------------------------------------*/
6191 /* AccAXRsh - right shift a:x known count (0..7) */
6192 /*-----------------------------------------------------------------*/
6194 AccAXRsh (char *x, int shCount)
6202 AccAXRrl1 (x); // 0->a:x
6207 AccAXRrl1 (x); // 0->a:x
6210 AccAXRrl1 (x); // 0->a:x
6215 case 5: // AAAAABBB:CCCCCDDD = a:x
6217 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6219 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6221 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6223 emitcode ("anl", "a,#0x%02x",
6224 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6226 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6228 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6230 emitcode ("anl", "a,#0x%02x",
6231 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6233 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6235 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6237 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6240 case 6: // AABBBBBB:CCDDDDDD
6242 emitcode ("mov", "c,acc.7");
6243 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6245 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6247 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6249 emitcode ("anl", "a,#0x%02x",
6250 SRMask[shCount]); // 000000AA:BBBBBBCC
6253 case 7: // ABBBBBBB:CDDDDDDD
6255 emitcode ("mov", "c,acc.7"); // c = A
6257 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6259 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6261 emitcode ("anl", "a,#0x%02x",
6262 SRMask[shCount]); // 0000000A:BBBBBBBC
6273 /*-----------------------------------------------------------------*/
6274 /* AccAXRshS - right shift signed a:x known count (0..7) */
6275 /*-----------------------------------------------------------------*/
6277 AccAXRshS (char *x, int shCount)
6285 emitcode ("mov", "c,acc.7");
6286 AccAXRrl1 (x); // s->a:x
6290 emitcode ("mov", "c,acc.7");
6291 AccAXRrl1 (x); // s->a:x
6293 emitcode ("mov", "c,acc.7");
6294 AccAXRrl1 (x); // s->a:x
6299 case 5: // AAAAABBB:CCCCCDDD = a:x
6301 tlbl = newiTempLabel (NULL);
6302 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6304 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6306 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6308 emitcode ("anl", "a,#0x%02x",
6309 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6311 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6313 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6315 emitcode ("anl", "a,#0x%02x",
6316 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6318 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6320 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6322 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6324 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6325 emitcode ("orl", "a,#0x%02x",
6326 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6328 emitcode ("", "%05d$:", tlbl->key + 100);
6329 break; // SSSSAAAA:BBBCCCCC
6331 case 6: // AABBBBBB:CCDDDDDD
6333 tlbl = newiTempLabel (NULL);
6334 emitcode ("mov", "c,acc.7");
6335 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6337 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6339 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6341 emitcode ("anl", "a,#0x%02x",
6342 SRMask[shCount]); // 000000AA:BBBBBBCC
6344 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6345 emitcode ("orl", "a,#0x%02x",
6346 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6348 emitcode ("", "%05d$:", tlbl->key + 100);
6350 case 7: // ABBBBBBB:CDDDDDDD
6352 tlbl = newiTempLabel (NULL);
6353 emitcode ("mov", "c,acc.7"); // c = A
6355 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6357 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6359 emitcode ("anl", "a,#0x%02x",
6360 SRMask[shCount]); // 0000000A:BBBBBBBC
6362 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6363 emitcode ("orl", "a,#0x%02x",
6364 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6366 emitcode ("", "%05d$:", tlbl->key + 100);
6376 /*-----------------------------------------------------------------*/
6377 /* shiftL2Left2Result - shift left two bytes from left to result */
6378 /*-----------------------------------------------------------------*/
6380 shiftL2Left2Result (operand * left, int offl,
6381 operand * result, int offr, int shCount)
6383 if (sameRegs (AOP (result), AOP (left)) &&
6384 ((offl + MSB16) == offr))
6386 /* don't crash result[offr] */
6387 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6388 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6392 movLeft2Result (left, offl, result, offr, 0);
6393 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6395 /* ax << shCount (x = lsb(result)) */
6396 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6397 aopPut (AOP (result), "a", offr + MSB16);
6403 /*-----------------------------------------------------------------*/
6404 /* shiftR2Left2Result - shift right two bytes from left to result */
6405 /*-----------------------------------------------------------------*/
6407 shiftR2Left2Result (operand * left, int offl,
6408 operand * result, int offr,
6409 int shCount, int sign)
6411 if (sameRegs (AOP (result), AOP (left)) &&
6412 ((offl + MSB16) == offr))
6414 /* don't crash result[offr] */
6415 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6416 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6420 movLeft2Result (left, offl, result, offr, 0);
6421 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6423 /* a:x >> shCount (x = lsb(result)) */
6425 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6427 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6428 if (getDataSize (result) > 1)
6429 aopPut (AOP (result), "a", offr + MSB16);
6435 /*-----------------------------------------------------------------*/
6436 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6437 /*-----------------------------------------------------------------*/
6439 shiftLLeftOrResult (operand * left, int offl,
6440 operand * result, int offr, int shCount)
6442 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6443 /* shift left accumulator */
6445 /* or with result */
6446 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6447 /* back to result */
6448 aopPut (AOP (result), "a", offr);
6454 /*-----------------------------------------------------------------*/
6455 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6456 /*-----------------------------------------------------------------*/
6458 shiftRLeftOrResult (operand * left, int offl,
6459 operand * result, int offr, int shCount)
6461 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6462 /* shift right 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 /* genlshOne - left shift a one byte quantity by known count */
6475 /*-----------------------------------------------------------------*/
6477 genlshOne (operand * result, operand * left, int shCount)
6479 D (emitcode (";", "genlshOne ");
6481 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6487 /*-----------------------------------------------------------------*/
6488 /* genlshTwo - left shift two bytes by known amount != 0 */
6489 /*-----------------------------------------------------------------*/
6491 genlshTwo (operand * result, operand * left, int shCount)
6495 D (emitcode (";", "genlshTwo ");
6498 size = getDataSize (result);
6500 /* if shCount >= 8 */
6508 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6510 movLeft2Result (left, LSB, result, MSB16, 0);
6512 aopPut (AOP (result), zero, LSB);
6515 /* 1 <= shCount <= 7 */
6519 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6521 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6528 /*-----------------------------------------------------------------*/
6529 /* shiftLLong - shift left one long from left to result */
6530 /* offl = LSB or MSB16 */
6531 /*-----------------------------------------------------------------*/
6533 shiftLLong (operand * left, operand * result, int offr)
6536 int size = AOP_SIZE (result);
6538 if (size >= LSB + offr)
6540 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6542 emitcode ("add", "a,acc");
6543 if (sameRegs (AOP (left), AOP (result)) &&
6544 size >= MSB16 + offr && offr != LSB)
6545 emitcode ("xch", "a,%s",
6546 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6548 aopPut (AOP (result), "a", LSB + offr);
6551 if (size >= MSB16 + offr)
6553 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6555 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6558 emitcode ("rlc", "a");
6559 if (sameRegs (AOP (left), AOP (result)) &&
6560 size >= MSB24 + offr && offr != LSB)
6561 emitcode ("xch", "a,%s",
6562 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6564 aopPut (AOP (result), "a", MSB16 + offr);
6567 if (size >= MSB24 + offr)
6569 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6571 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6574 emitcode ("rlc", "a");
6575 if (sameRegs (AOP (left), AOP (result)) &&
6576 size >= MSB32 + offr && offr != LSB)
6577 emitcode ("xch", "a,%s",
6578 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6580 aopPut (AOP (result), "a", MSB24 + offr);
6583 if (size > MSB32 + offr)
6585 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6587 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6590 emitcode ("rlc", "a");
6591 aopPut (AOP (result), "a", MSB32 + offr);
6594 aopPut (AOP (result), zero, LSB);
6600 /*-----------------------------------------------------------------*/
6601 /* genlshFour - shift four byte by a known amount != 0 */
6602 /*-----------------------------------------------------------------*/
6604 genlshFour (operand * result, operand * left, int shCount)
6608 D (emitcode (";", "genlshFour ");
6611 size = AOP_SIZE (result);
6613 /* if shifting more that 3 bytes */
6618 /* lowest order of left goes to the highest
6619 order of the destination */
6620 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6622 movLeft2Result (left, LSB, result, MSB32, 0);
6623 aopPut (AOP (result), zero, LSB);
6624 aopPut (AOP (result), zero, MSB16);
6625 aopPut (AOP (result), zero, MSB32);
6629 /* more than two bytes */
6630 else if (shCount >= 16)
6632 /* lower order two bytes goes to higher order two bytes */
6634 /* if some more remaining */
6636 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6639 movLeft2Result (left, MSB16, result, MSB32, 0);
6640 movLeft2Result (left, LSB, result, MSB24, 0);
6642 aopPut (AOP (result), zero, MSB16);
6643 aopPut (AOP (result), zero, LSB);
6647 /* if more than 1 byte */
6648 else if (shCount >= 8)
6650 /* lower order three bytes goes to higher order three bytes */
6655 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6657 movLeft2Result (left, LSB, result, MSB16, 0);
6663 movLeft2Result (left, MSB24, result, MSB32, 0);
6664 movLeft2Result (left, MSB16, result, MSB24, 0);
6665 movLeft2Result (left, LSB, result, MSB16, 0);
6666 aopPut (AOP (result), zero, LSB);
6668 else if (shCount == 1)
6669 shiftLLong (left, result, MSB16);
6672 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6673 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6674 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6675 aopPut (AOP (result), zero, LSB);
6680 /* 1 <= shCount <= 7 */
6681 else if (shCount <= 2)
6683 shiftLLong (left, result, LSB);
6685 shiftLLong (result, result, LSB);
6687 /* 3 <= shCount <= 7, optimize */
6690 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6691 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6692 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6699 /*-----------------------------------------------------------------*/
6700 /* genLeftShiftLiteral - left shifting by known count */
6701 /*-----------------------------------------------------------------*/
6703 genLeftShiftLiteral (operand * left,
6708 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6711 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6714 freeAsmop (right, NULL, ic, TRUE);
6716 aopOp (left, ic, FALSE, FALSE);
6717 aopOp (result, ic, FALSE, TRUE);
6719 size = getSize (operandType (result));
6722 emitcode ("; shift left ", "result %d, left %d", size,
6726 /* I suppose that the left size >= result size */
6731 movLeft2Result (left, size, result, size, 0);
6735 else if (shCount >= (size * 8))
6737 aopPut (AOP (result), zero, size);
6743 genlshOne (result, left, shCount);
6747 case 3: /* bug: this is for generic pointers, I bet. */
6748 genlshTwo (result, left, shCount);
6752 genlshFour (result, left, shCount);
6756 freeAsmop (left, NULL, ic, TRUE);
6757 freeAsmop (result, NULL, ic, TRUE);
6761 /*-----------------------------------------------------------------*/
6762 /* genLeftShift - generates code for left shifting */
6763 /*-----------------------------------------------------------------*/
6765 genLeftShift (iCode * ic)
6767 operand *left, *right, *result;
6770 symbol *tlbl, *tlbl1;
6772 D (emitcode (";", "genLeftShift ");
6775 right = IC_RIGHT (ic);
6776 left = IC_LEFT (ic);
6777 result = IC_RESULT (ic);
6779 aopOp (right, ic, FALSE, FALSE);
6782 /* if the shift count is known then do it
6783 as efficiently as possible */
6784 if (AOP_TYPE (right) == AOP_LIT)
6786 genLeftShiftLiteral (left, right, result, ic);
6791 /* shift count is unknown then we have to form
6792 a loop get the loop count in B : Note: we take
6793 only the lower order byte since shifting
6794 more that 32 bits make no sense anyway, ( the
6795 largest size of an object can be only 32 bits ) */
6797 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6798 emitcode ("inc", "b");
6799 freeAsmop (right, NULL, ic, TRUE);
6800 aopOp (left, ic, FALSE, FALSE);
6801 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6803 /* now move the left to the result if they are not the
6805 if (!sameRegs (AOP (left), AOP (result)) &&
6806 AOP_SIZE (result) > 1)
6809 size = AOP_SIZE (result);
6811 _startLazyDPSEvaluation ();
6814 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6815 if (*l == '@' && (IS_AOP_PREG (result)))
6818 emitcode ("mov", "a,%s", l);
6819 aopPut (AOP (result), "a", offset);
6822 aopPut (AOP (result), l, offset);
6825 _endLazyDPSEvaluation ();
6828 tlbl = newiTempLabel (NULL);
6829 size = AOP_SIZE (result);
6831 tlbl1 = newiTempLabel (NULL);
6833 /* if it is only one byte then */
6836 symbol *tlbl1 = newiTempLabel (NULL);
6838 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6840 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6841 emitcode ("", "%05d$:", tlbl->key + 100);
6842 emitcode ("add", "a,acc");
6843 emitcode ("", "%05d$:", tlbl1->key + 100);
6844 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6845 aopPut (AOP (result), "a", 0);
6849 reAdjustPreg (AOP (result));
6851 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6852 emitcode ("", "%05d$:", tlbl->key + 100);
6853 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6855 emitcode ("add", "a,acc");
6856 aopPut (AOP (result), "a", offset++);
6857 _startLazyDPSEvaluation ();
6860 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6862 emitcode ("rlc", "a");
6863 aopPut (AOP (result), "a", offset++);
6865 _endLazyDPSEvaluation ();
6866 reAdjustPreg (AOP (result));
6868 emitcode ("", "%05d$:", tlbl1->key + 100);
6869 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6871 freeAsmop (left, NULL, ic, TRUE);
6872 freeAsmop (result, NULL, ic, TRUE);
6877 /*-----------------------------------------------------------------*/
6878 /* genrshOne - right shift a one byte quantity by known count */
6879 /*-----------------------------------------------------------------*/
6881 genrshOne (operand * result, operand * left,
6882 int shCount, int sign)
6884 D (emitcode (";", "genrshOne");
6886 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6892 /*-----------------------------------------------------------------*/
6893 /* genrshTwo - right shift two bytes by known amount != 0 */
6894 /*-----------------------------------------------------------------*/
6896 genrshTwo (operand * result, operand * left,
6897 int shCount, int sign)
6899 D (emitcode (";", "genrshTwo");
6902 /* if shCount >= 8 */
6907 shiftR1Left2Result (left, MSB16, result, LSB,
6910 movLeft2Result (left, MSB16, result, LSB, sign);
6911 addSign (result, MSB16, sign);
6914 /* 1 <= shCount <= 7 */
6916 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6922 /*-----------------------------------------------------------------*/
6923 /* shiftRLong - shift right one long from left to result */
6924 /* offl = LSB or MSB16 */
6925 /*-----------------------------------------------------------------*/
6927 shiftRLong (operand * left, int offl,
6928 operand * result, int sign)
6931 emitcode ("clr", "c");
6932 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6934 emitcode ("mov", "c,acc.7");
6935 emitcode ("rrc", "a");
6936 aopPut (AOP (result), "a", MSB32 - offl);
6938 /* add sign of "a" */
6939 addSign (result, MSB32, sign);
6941 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6942 emitcode ("rrc", "a");
6943 aopPut (AOP (result), "a", MSB24 - offl);
6945 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6946 emitcode ("rrc", "a");
6947 aopPut (AOP (result), "a", MSB16 - offl);
6951 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6952 emitcode ("rrc", "a");
6953 aopPut (AOP (result), "a", LSB);
6960 /*-----------------------------------------------------------------*/
6961 /* genrshFour - shift four byte by a known amount != 0 */
6962 /*-----------------------------------------------------------------*/
6964 genrshFour (operand * result, operand * left,
6965 int shCount, int sign)
6967 D (emitcode (";", "genrshFour");
6970 /* if shifting more that 3 bytes */
6975 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6977 movLeft2Result (left, MSB32, result, LSB, sign);
6978 addSign (result, MSB16, sign);
6980 else if (shCount >= 16)
6984 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6987 movLeft2Result (left, MSB24, result, LSB, 0);
6988 movLeft2Result (left, MSB32, result, MSB16, sign);
6990 addSign (result, MSB24, sign);
6992 else if (shCount >= 8)
6996 shiftRLong (left, MSB16, result, sign);
6997 else if (shCount == 0)
6999 movLeft2Result (left, MSB16, result, LSB, 0);
7000 movLeft2Result (left, MSB24, result, MSB16, 0);
7001 movLeft2Result (left, MSB32, result, MSB24, sign);
7002 addSign (result, MSB32, sign);
7006 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7007 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7008 /* the last shift is signed */
7009 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7010 addSign (result, MSB32, sign);
7014 { /* 1 <= shCount <= 7 */
7017 shiftRLong (left, LSB, result, sign);
7019 shiftRLong (result, LSB, result, sign);
7023 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7024 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7025 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7033 /*-----------------------------------------------------------------*/
7034 /* genRightShiftLiteral - right shifting by known count */
7035 /*-----------------------------------------------------------------*/
7037 genRightShiftLiteral (operand * left,
7043 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7046 D (emitcode (";", "genRightShiftLiteral");
7049 freeAsmop (right, NULL, ic, TRUE);
7051 aopOp (left, ic, FALSE, FALSE);
7052 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7055 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7059 size = getDataSize (left);
7060 /* test the LEFT size !!! */
7062 /* I suppose that the left size >= result size */
7065 size = getDataSize (result);
7067 movLeft2Result (left, size, result, size, 0);
7070 else if (shCount >= (size * 8))
7073 /* get sign in acc.7 */
7074 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7075 addSign (result, LSB, sign);
7082 genrshOne (result, left, shCount, sign);
7086 genrshTwo (result, left, shCount, sign);
7090 genrshFour (result, left, shCount, sign);
7096 freeAsmop (left, NULL, ic, TRUE);
7097 freeAsmop (result, NULL, ic, TRUE);
7102 /*-----------------------------------------------------------------*/
7103 /* genSignedRightShift - right shift of signed number */
7104 /*-----------------------------------------------------------------*/
7106 genSignedRightShift (iCode * ic)
7108 operand *right, *left, *result;
7111 symbol *tlbl, *tlbl1;
7113 D (emitcode (";", "genSignedRightShift ");
7116 /* we do it the hard way put the shift count in b
7117 and loop thru preserving the sign */
7119 right = IC_RIGHT (ic);
7120 left = IC_LEFT (ic);
7121 result = IC_RESULT (ic);
7123 aopOp (right, ic, FALSE, FALSE);
7126 if (AOP_TYPE (right) == AOP_LIT)
7128 genRightShiftLiteral (left, right, result, ic, 1);
7132 /* shift count is unknown then we have to form
7133 a loop get the loop count in B : Note: we take
7134 only the lower order byte since shifting
7135 more that 32 bits make no sense anyway, ( the
7136 largest size of an object can be only 32 bits ) */
7138 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7139 emitcode ("inc", "b");
7140 freeAsmop (right, NULL, ic, TRUE);
7141 aopOp (left, ic, FALSE, FALSE);
7142 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7144 /* now move the left to the result if they are not the
7146 if (!sameRegs (AOP (left), AOP (result)) &&
7147 AOP_SIZE (result) > 1)
7150 size = AOP_SIZE (result);
7152 _startLazyDPSEvaluation ();
7155 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7156 if (*l == '@' && IS_AOP_PREG (result))
7159 emitcode ("mov", "a,%s", l);
7160 aopPut (AOP (result), "a", offset);
7163 aopPut (AOP (result), l, offset);
7166 _endLazyDPSEvaluation ();
7169 /* mov the highest order bit to OVR */
7170 tlbl = newiTempLabel (NULL);
7171 tlbl1 = newiTempLabel (NULL);
7173 size = AOP_SIZE (result);
7175 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7176 emitcode ("rlc", "a");
7177 emitcode ("mov", "ov,c");
7178 /* if it is only one byte then */
7181 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7183 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7184 emitcode ("", "%05d$:", tlbl->key + 100);
7185 emitcode ("mov", "c,ov");
7186 emitcode ("rrc", "a");
7187 emitcode ("", "%05d$:", tlbl1->key + 100);
7188 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7189 aopPut (AOP (result), "a", 0);
7193 reAdjustPreg (AOP (result));
7194 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7195 emitcode ("", "%05d$:", tlbl->key + 100);
7196 emitcode ("mov", "c,ov");
7197 _startLazyDPSEvaluation ();
7200 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7202 emitcode ("rrc", "a");
7203 aopPut (AOP (result), "a", offset--);
7205 _endLazyDPSEvaluation ();
7206 reAdjustPreg (AOP (result));
7207 emitcode ("", "%05d$:", tlbl1->key + 100);
7208 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7211 freeAsmop (left, NULL, ic, TRUE);
7212 freeAsmop (result, NULL, ic, TRUE);
7215 /*-----------------------------------------------------------------*/
7216 /* genRightShift - generate code for right shifting */
7217 /*-----------------------------------------------------------------*/
7219 genRightShift (iCode * ic)
7221 operand *right, *left, *result;
7225 symbol *tlbl, *tlbl1;
7227 D (emitcode (";", "genRightShift ");
7230 /* if signed then we do it the hard way preserve the
7231 sign bit moving it inwards */
7232 retype = getSpec (operandType (IC_RESULT (ic)));
7234 if (!SPEC_USIGN (retype))
7236 genSignedRightShift (ic);
7240 /* signed & unsigned types are treated the same : i.e. the
7241 signed is NOT propagated inwards : quoting from the
7242 ANSI - standard : "for E1 >> E2, is equivalent to division
7243 by 2**E2 if unsigned or if it has a non-negative value,
7244 otherwise the result is implementation defined ", MY definition
7245 is that the sign does not get propagated */
7247 right = IC_RIGHT (ic);
7248 left = IC_LEFT (ic);
7249 result = IC_RESULT (ic);
7251 aopOp (right, ic, FALSE, FALSE);
7254 /* if the shift count is known then do it
7255 as efficiently as possible */
7256 if (AOP_TYPE (right) == AOP_LIT)
7258 genRightShiftLiteral (left, right, result, ic, 0);
7263 /* shift count is unknown then we have to form
7264 a loop get the loop count in B : Note: we take
7265 only the lower order byte since shifting
7266 more that 32 bits make no sense anyway, ( the
7267 largest size of an object can be only 32 bits ) */
7269 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7270 emitcode ("inc", "b");
7271 freeAsmop (right, NULL, ic, TRUE);
7272 aopOp (left, ic, FALSE, FALSE);
7273 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7275 /* now move the left to the result if they are not the
7277 if (!sameRegs (AOP (left), AOP (result)) &&
7278 AOP_SIZE (result) > 1)
7281 size = AOP_SIZE (result);
7283 _startLazyDPSEvaluation ();
7286 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7287 if (*l == '@' && IS_AOP_PREG (result))
7290 emitcode ("mov", "a,%s", l);
7291 aopPut (AOP (result), "a", offset);
7294 aopPut (AOP (result), l, offset);
7297 _endLazyDPSEvaluation ();
7300 tlbl = newiTempLabel (NULL);
7301 tlbl1 = newiTempLabel (NULL);
7302 size = AOP_SIZE (result);
7305 /* if it is only one byte then */
7308 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7310 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7311 emitcode ("", "%05d$:", tlbl->key + 100);
7313 emitcode ("rrc", "a");
7314 emitcode ("", "%05d$:", tlbl1->key + 100);
7315 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7316 aopPut (AOP (result), "a", 0);
7320 reAdjustPreg (AOP (result));
7321 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7322 emitcode ("", "%05d$:", tlbl->key + 100);
7324 _startLazyDPSEvaluation ();
7327 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7329 emitcode ("rrc", "a");
7330 aopPut (AOP (result), "a", offset--);
7332 _endLazyDPSEvaluation ();
7333 reAdjustPreg (AOP (result));
7335 emitcode ("", "%05d$:", tlbl1->key + 100);
7336 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7339 freeAsmop (left, NULL, ic, TRUE);
7340 freeAsmop (result, NULL, ic, TRUE);
7343 /*-----------------------------------------------------------------*/
7344 /* genUnpackBits - generates code for unpacking bits */
7345 /*-----------------------------------------------------------------*/
7347 genUnpackBits (operand * result, char *rname, int ptype)
7354 D (emitcode (";", "genUnpackBits ");
7357 etype = getSpec (operandType (result));
7359 /* read the first byte */
7365 emitcode ("mov", "a,@%s", rname);
7369 emitcode ("movx", "a,@%s", rname);
7373 emitcode ("movx", "a,@dptr");
7377 emitcode ("clr", "a");
7378 emitcode ("movc", "a", "@a+dptr");
7382 emitcode ("lcall", "__gptrget");
7386 /* if we have bitdisplacement then it fits */
7387 /* into this byte completely or if length is */
7388 /* less than a byte */
7389 if ((shCnt = SPEC_BSTR (etype)) ||
7390 (SPEC_BLEN (etype) <= 8))
7393 /* shift right acc */
7396 emitcode ("anl", "a,#0x%02x",
7397 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7398 aopPut (AOP (result), "a", offset);
7402 /* bit field did not fit in a byte */
7403 rlen = SPEC_BLEN (etype) - 8;
7404 aopPut (AOP (result), "a", offset++);
7413 emitcode ("inc", "%s", rname);
7414 emitcode ("mov", "a,@%s", rname);
7418 emitcode ("inc", "%s", rname);
7419 emitcode ("movx", "a,@%s", rname);
7423 emitcode ("inc", "dptr");
7424 emitcode ("movx", "a,@dptr");
7428 emitcode ("clr", "a");
7429 emitcode ("inc", "dptr");
7430 emitcode ("movc", "a", "@a+dptr");
7434 emitcode ("inc", "dptr");
7435 emitcode ("lcall", "__gptrget");
7440 /* if we are done */
7444 aopPut (AOP (result), "a", offset++);
7450 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7451 aopPut (AOP (result), "a", offset);
7458 /*-----------------------------------------------------------------*/
7459 /* genDataPointerGet - generates code when ptr offset is known */
7460 /*-----------------------------------------------------------------*/
7462 genDataPointerGet (operand * left,
7468 int size, offset = 0;
7469 aopOp (result, ic, TRUE, FALSE);
7471 /* get the string representation of the name */
7472 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7473 size = AOP_SIZE (result);
7474 _startLazyDPSEvaluation ();
7478 sprintf (buffer, "(%s + %d)", l + 1, offset);
7480 sprintf (buffer, "%s", l + 1);
7481 aopPut (AOP (result), buffer, offset++);
7483 _endLazyDPSEvaluation ();
7485 freeAsmop (left, NULL, ic, TRUE);
7486 freeAsmop (result, NULL, ic, TRUE);
7489 /*-----------------------------------------------------------------*/
7490 /* genNearPointerGet - emitcode for near pointer fetch */
7491 /*-----------------------------------------------------------------*/
7493 genNearPointerGet (operand * left,
7500 sym_link *rtype, *retype, *letype;
7501 sym_link *ltype = operandType (left);
7504 rtype = operandType (result);
7505 retype = getSpec (rtype);
7506 letype = getSpec (ltype);
7508 aopOp (left, ic, FALSE, FALSE);
7510 /* if left is rematerialisable and
7511 result is not bit variable type and
7512 the left is pointer to data space i.e
7513 lower 128 bytes of space */
7514 if (AOP_TYPE (left) == AOP_IMMD &&
7515 !IS_BITVAR (retype) &&
7516 !IS_BITVAR (letype) &&
7517 DCL_TYPE (ltype) == POINTER)
7519 genDataPointerGet (left, result, ic);
7523 /* if the value is already in a pointer register
7524 then don't need anything more */
7525 if (!AOP_INPREG (AOP (left)))
7527 /* otherwise get a free pointer register */
7529 preg = getFreePtr (ic, &aop, FALSE);
7530 emitcode ("mov", "%s,%s",
7532 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7536 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7538 freeAsmop (left, NULL, ic, TRUE);
7539 aopOp (result, ic, FALSE, FALSE);
7541 /* if bitfield then unpack the bits */
7542 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7543 genUnpackBits (result, rname, POINTER);
7546 /* we have can just get the values */
7547 int size = AOP_SIZE (result);
7552 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7555 emitcode ("mov", "a,@%s", rname);
7556 aopPut (AOP (result), "a", offset);
7560 sprintf (buffer, "@%s", rname);
7561 aopPut (AOP (result), buffer, offset);
7565 emitcode ("inc", "%s", rname);
7569 /* now some housekeeping stuff */
7572 /* we had to allocate for this iCode */
7573 freeAsmop (NULL, aop, ic, TRUE);
7577 /* we did not allocate which means left
7578 already in a pointer register, then
7579 if size > 0 && this could be used again
7580 we have to point it back to where it
7582 if (AOP_SIZE (result) > 1 &&
7583 !OP_SYMBOL (left)->remat &&
7584 (OP_SYMBOL (left)->liveTo > ic->seq ||
7587 int size = AOP_SIZE (result) - 1;
7589 emitcode ("dec", "%s", rname);
7594 freeAsmop (result, NULL, ic, TRUE);
7598 /*-----------------------------------------------------------------*/
7599 /* genPagedPointerGet - emitcode for paged pointer fetch */
7600 /*-----------------------------------------------------------------*/
7602 genPagedPointerGet (operand * left,
7609 sym_link *rtype, *retype, *letype;
7611 rtype = operandType (result);
7612 retype = getSpec (rtype);
7613 letype = getSpec (operandType (left));
7614 aopOp (left, ic, FALSE, FALSE);
7616 /* if the value is already in a pointer register
7617 then don't need anything more */
7618 if (!AOP_INPREG (AOP (left)))
7620 /* otherwise get a free pointer register */
7622 preg = getFreePtr (ic, &aop, FALSE);
7623 emitcode ("mov", "%s,%s",
7625 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7629 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7631 freeAsmop (left, NULL, ic, TRUE);
7632 aopOp (result, ic, FALSE, FALSE);
7634 /* if bitfield then unpack the bits */
7635 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7636 genUnpackBits (result, rname, PPOINTER);
7639 /* we have can just get the values */
7640 int size = AOP_SIZE (result);
7646 emitcode ("movx", "a,@%s", rname);
7647 aopPut (AOP (result), "a", offset);
7652 emitcode ("inc", "%s", rname);
7656 /* now some housekeeping stuff */
7659 /* we had to allocate for this iCode */
7660 freeAsmop (NULL, aop, ic, TRUE);
7664 /* we did not allocate which means left
7665 already in a pointer register, then
7666 if size > 0 && this could be used again
7667 we have to point it back to where it
7669 if (AOP_SIZE (result) > 1 &&
7670 !OP_SYMBOL (left)->remat &&
7671 (OP_SYMBOL (left)->liveTo > ic->seq ||
7674 int size = AOP_SIZE (result) - 1;
7676 emitcode ("dec", "%s", rname);
7681 freeAsmop (result, NULL, ic, TRUE);
7686 /*-----------------------------------------------------------------*/
7687 /* genFarPointerGet - gget value from far space */
7688 /*-----------------------------------------------------------------*/
7690 genFarPointerGet (operand * left,
7691 operand * result, iCode * ic)
7694 sym_link *retype = getSpec (operandType (result));
7695 sym_link *letype = getSpec (operandType (left));
7696 D (emitcode (";", "genFarPointerGet");
7699 aopOp (left, ic, FALSE, FALSE);
7701 /* if the operand is already in dptr
7702 then we do nothing else we move the value to dptr */
7703 if (AOP_TYPE (left) != AOP_STR)
7705 /* if this is remateriazable */
7706 if (AOP_TYPE (left) == AOP_IMMD)
7708 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7712 /* we need to get it byte by byte */
7713 _startLazyDPSEvaluation ();
7714 if (AOP_TYPE (left) != AOP_DPTR)
7716 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7717 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7718 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7722 /* We need to generate a load to DPTR indirect through DPTR. */
7723 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7725 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7726 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7727 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7728 emitcode ("pop", "dph");
7729 emitcode ("pop", "dpl");
7731 _endLazyDPSEvaluation ();
7734 /* so dptr know contains the address */
7735 freeAsmop (left, NULL, ic, TRUE);
7736 aopOp (result, ic, FALSE, TRUE);
7738 /* if bit then unpack */
7739 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7740 genUnpackBits (result, "dptr", FPOINTER);
7743 size = AOP_SIZE (result);
7746 _startLazyDPSEvaluation ();
7753 emitcode ("movx", "a,@dptr");
7755 emitcode ("inc", "dptr");
7757 aopPut (AOP (result), "a", offset++);
7759 _endLazyDPSEvaluation ();
7762 freeAsmop (result, NULL, ic, TRUE);
7765 /*-----------------------------------------------------------------*/
7766 /* emitcodePointerGet - gget value from code space */
7767 /*-----------------------------------------------------------------*/
7769 emitcodePointerGet (operand * left,
7770 operand * result, iCode * ic)
7773 sym_link *retype = getSpec (operandType (result));
7775 aopOp (left, ic, FALSE, FALSE);
7777 /* if the operand is already in dptr
7778 then we do nothing else we move the value to dptr */
7779 if (AOP_TYPE (left) != AOP_STR)
7781 /* if this is remateriazable */
7782 if (AOP_TYPE (left) == AOP_IMMD)
7784 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7787 { /* we need to get it byte by byte */
7788 _startLazyDPSEvaluation ();
7789 if (AOP_TYPE (left) != AOP_DPTR)
7791 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7792 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7793 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7797 /* We need to generate a load to DPTR indirect through DPTR. */
7798 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7800 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7801 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7802 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7803 emitcode ("pop", "dph");
7804 emitcode ("pop", "dpl");
7806 _endLazyDPSEvaluation ();
7809 /* so dptr know contains the address */
7810 freeAsmop (left, NULL, ic, TRUE);
7811 aopOp (result, ic, FALSE, TRUE);
7813 /* if bit then unpack */
7814 if (IS_BITVAR (retype))
7815 genUnpackBits (result, "dptr", CPOINTER);
7818 size = AOP_SIZE (result);
7821 _startLazyDPSEvaluation ();
7827 emitcode ("clr", "a");
7828 emitcode ("movc", "a,@a+dptr");
7830 emitcode ("inc", "dptr");
7831 aopPut (AOP (result), "a", offset++);
7833 _endLazyDPSEvaluation ();
7836 freeAsmop (result, NULL, ic, TRUE);
7839 /*-----------------------------------------------------------------*/
7840 /* genGenPointerGet - gget value from generic pointer space */
7841 /*-----------------------------------------------------------------*/
7843 genGenPointerGet (operand * left,
7844 operand * result, iCode * ic)
7847 sym_link *retype = getSpec (operandType (result));
7848 sym_link *letype = getSpec (operandType (left));
7850 D (emitcode (";", "genGenPointerGet "); );
7852 aopOp (left, ic, FALSE, TRUE);
7854 /* if the operand is already in dptr
7855 then we do nothing else we move the value to dptr */
7856 if (AOP_TYPE (left) != AOP_STR)
7858 /* if this is remateriazable */
7859 if (AOP_TYPE (left) == AOP_IMMD)
7861 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7862 emitcode ("mov", "b,#%d", pointerCode (retype));
7865 { /* we need to get it byte by byte */
7866 _startLazyDPSEvaluation ();
7867 if (AOP(left)->type==AOP_DPTR2) {
7869 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7872 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7873 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7876 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7877 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7880 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7881 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7883 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7884 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7885 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7886 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7888 _endLazyDPSEvaluation ();
7891 /* so dptr know contains the address */
7892 freeAsmop (left, NULL, ic, TRUE);
7893 aopOp (result, ic, FALSE, TRUE);
7895 /* if bit then unpack */
7896 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7897 genUnpackBits (result, "dptr", GPOINTER);
7900 size = AOP_SIZE (result);
7905 emitcode ("lcall", "__gptrget");
7906 aopPut (AOP (result), "a", offset++);
7908 emitcode ("inc", "dptr");
7912 freeAsmop (result, NULL, ic, TRUE);
7915 /*-----------------------------------------------------------------*/
7916 /* genPointerGet - generate code for pointer get */
7917 /*-----------------------------------------------------------------*/
7919 genPointerGet (iCode * ic)
7921 operand *left, *result;
7922 sym_link *type, *etype;
7925 D (emitcode (";", "genPointerGet ");
7928 left = IC_LEFT (ic);
7929 result = IC_RESULT (ic);
7931 /* depending on the type of pointer we need to
7932 move it to the correct pointer register */
7933 type = operandType (left);
7934 etype = getSpec (type);
7935 /* if left is of type of pointer then it is simple */
7936 if (IS_PTR (type) && !IS_FUNC (type->next))
7937 p_type = DCL_TYPE (type);
7940 /* we have to go by the storage class */
7941 p_type = PTR_TYPE (SPEC_OCLS (etype));
7944 /* now that we have the pointer type we assign
7945 the pointer values */
7951 genNearPointerGet (left, result, ic);
7955 genPagedPointerGet (left, result, ic);
7959 genFarPointerGet (left, result, ic);
7963 emitcodePointerGet (left, result, ic);
7967 genGenPointerGet (left, result, ic);
7973 /*-----------------------------------------------------------------*/
7974 /* genPackBits - generates code for packed bit storage */
7975 /*-----------------------------------------------------------------*/
7977 genPackBits (sym_link * etype,
7979 char *rname, int p_type)
7987 blen = SPEC_BLEN (etype);
7988 bstr = SPEC_BSTR (etype);
7990 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
7993 /* if the bit lenth is less than or */
7994 /* it exactly fits a byte then */
7995 if (SPEC_BLEN (etype) <= 8)
7997 shCount = SPEC_BSTR (etype);
7999 /* shift left acc */
8002 if (SPEC_BLEN (etype) < 8)
8003 { /* if smaller than a byte */
8009 emitcode ("mov", "b,a");
8010 emitcode ("mov", "a,@%s", rname);
8014 emitcode ("mov", "b,a");
8015 emitcode ("movx", "a,@dptr");
8019 emitcode ("push", "b");
8020 emitcode ("push", "acc");
8021 emitcode ("lcall", "__gptrget");
8022 emitcode ("pop", "b");
8026 emitcode ("anl", "a,#0x%02x", (unsigned char)
8027 ((unsigned char) (0xFF << (blen + bstr)) |
8028 (unsigned char) (0xFF >> (8 - bstr))));
8029 emitcode ("orl", "a,b");
8030 if (p_type == GPOINTER)
8031 emitcode ("pop", "b");
8038 emitcode ("mov", "@%s,a", rname);
8042 emitcode ("movx", "@dptr,a");
8046 emitcode ("lcall", "__gptrput");
8051 if (SPEC_BLEN (etype) <= 8)
8054 emitcode ("inc", "%s", rname);
8055 rLen = SPEC_BLEN (etype);
8057 /* now generate for lengths greater than one byte */
8061 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8073 emitcode ("mov", "@%s,a", rname);
8076 emitcode ("mov", "@%s,%s", rname, l);
8081 emitcode ("movx", "@dptr,a");
8086 emitcode ("lcall", "__gptrput");
8089 emitcode ("inc", "%s", rname);
8094 /* last last was not complete */
8097 /* save the byte & read byte */
8101 emitcode ("mov", "b,a");
8102 emitcode ("mov", "a,@%s", rname);
8106 emitcode ("mov", "b,a");
8107 emitcode ("movx", "a,@dptr");
8111 emitcode ("push", "b");
8112 emitcode ("push", "acc");
8113 emitcode ("lcall", "__gptrget");
8114 emitcode ("pop", "b");
8118 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8119 emitcode ("orl", "a,b");
8122 if (p_type == GPOINTER)
8123 emitcode ("pop", "b");
8129 emitcode ("mov", "@%s,a", rname);
8133 emitcode ("movx", "@dptr,a");
8137 emitcode ("lcall", "__gptrput");
8141 /*-----------------------------------------------------------------*/
8142 /* genDataPointerSet - remat pointer to data space */
8143 /*-----------------------------------------------------------------*/
8145 genDataPointerSet (operand * right,
8149 int size, offset = 0;
8150 char *l, buffer[256];
8152 aopOp (right, ic, FALSE, FALSE);
8154 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8155 size = AOP_SIZE (right);
8159 sprintf (buffer, "(%s + %d)", l + 1, offset);
8161 sprintf (buffer, "%s", l + 1);
8162 emitcode ("mov", "%s,%s", buffer,
8163 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8166 freeAsmop (right, NULL, ic, TRUE);
8167 freeAsmop (result, NULL, ic, TRUE);
8170 /*-----------------------------------------------------------------*/
8171 /* genNearPointerSet - emitcode for near pointer put */
8172 /*-----------------------------------------------------------------*/
8174 genNearPointerSet (operand * right,
8181 sym_link *retype, *letype;
8182 sym_link *ptype = operandType (result);
8184 retype = getSpec (operandType (right));
8185 letype = getSpec (ptype);
8187 aopOp (result, ic, FALSE, FALSE);
8189 /* if the result is rematerializable &
8190 in data space & not a bit variable */
8191 if (AOP_TYPE (result) == AOP_IMMD &&
8192 DCL_TYPE (ptype) == POINTER &&
8193 !IS_BITVAR (retype) &&
8194 !IS_BITVAR (letype))
8196 genDataPointerSet (right, result, ic);
8200 /* if the value is already in a pointer register
8201 then don't need anything more */
8202 if (!AOP_INPREG (AOP (result)))
8204 /* otherwise get a free pointer register */
8206 preg = getFreePtr (ic, &aop, FALSE);
8207 emitcode ("mov", "%s,%s",
8209 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8213 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8215 freeAsmop (result, NULL, ic, TRUE);
8216 aopOp (right, ic, FALSE, FALSE);
8218 /* if bitfield then unpack the bits */
8219 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8220 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8223 /* we have can just get the values */
8224 int size = AOP_SIZE (right);
8229 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8233 emitcode ("mov", "@%s,a", rname);
8236 emitcode ("mov", "@%s,%s", rname, l);
8238 emitcode ("inc", "%s", rname);
8243 /* now some housekeeping stuff */
8246 /* we had to allocate for this iCode */
8247 freeAsmop (NULL, aop, ic, TRUE);
8251 /* we did not allocate which means left
8252 already in a pointer register, then
8253 if size > 0 && this could be used again
8254 we have to point it back to where it
8256 if (AOP_SIZE (right) > 1 &&
8257 !OP_SYMBOL (result)->remat &&
8258 (OP_SYMBOL (result)->liveTo > ic->seq ||
8261 int size = AOP_SIZE (right) - 1;
8263 emitcode ("dec", "%s", rname);
8268 freeAsmop (right, NULL, ic, TRUE);
8273 /*-----------------------------------------------------------------*/
8274 /* genPagedPointerSet - emitcode for Paged pointer put */
8275 /*-----------------------------------------------------------------*/
8277 genPagedPointerSet (operand * right,
8284 sym_link *retype, *letype;
8286 retype = getSpec (operandType (right));
8287 letype = getSpec (operandType (result));
8289 aopOp (result, ic, FALSE, FALSE);
8291 /* if the value is already in a pointer register
8292 then don't need anything more */
8293 if (!AOP_INPREG (AOP (result)))
8295 /* otherwise get a free pointer register */
8297 preg = getFreePtr (ic, &aop, FALSE);
8298 emitcode ("mov", "%s,%s",
8300 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8304 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8306 freeAsmop (result, NULL, ic, TRUE);
8307 aopOp (right, ic, FALSE, FALSE);
8309 /* if bitfield then unpack the bits */
8310 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8311 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8314 /* we have can just get the values */
8315 int size = AOP_SIZE (right);
8320 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8323 emitcode ("movx", "@%s,a", rname);
8326 emitcode ("inc", "%s", rname);
8332 /* now some housekeeping stuff */
8335 /* we had to allocate for this iCode */
8336 freeAsmop (NULL, aop, ic, TRUE);
8340 /* we did not allocate which means left
8341 already in a pointer register, then
8342 if size > 0 && this could be used again
8343 we have to point it back to where it
8345 if (AOP_SIZE (right) > 1 &&
8346 !OP_SYMBOL (result)->remat &&
8347 (OP_SYMBOL (result)->liveTo > ic->seq ||
8350 int size = AOP_SIZE (right) - 1;
8352 emitcode ("dec", "%s", rname);
8357 freeAsmop (right, NULL, ic, TRUE);
8362 /*-----------------------------------------------------------------*/
8363 /* genFarPointerSet - set value from far space */
8364 /*-----------------------------------------------------------------*/
8366 genFarPointerSet (operand * right,
8367 operand * result, iCode * ic)
8370 sym_link *retype = getSpec (operandType (right));
8371 sym_link *letype = getSpec (operandType (result));
8373 aopOp (result, ic, FALSE, FALSE);
8375 /* if the operand is already in dptr
8376 then we do nothing else we move the value to dptr */
8377 if (AOP_TYPE (result) != AOP_STR)
8379 /* if this is remateriazable */
8380 if (AOP_TYPE (result) == AOP_IMMD)
8381 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8384 /* we need to get it byte by byte */
8385 _startLazyDPSEvaluation ();
8386 if (AOP_TYPE (result) != AOP_DPTR)
8388 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8389 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8390 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8394 /* We need to generate a load to DPTR indirect through DPTR. */
8395 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8397 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8398 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8399 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8400 emitcode ("pop", "dph");
8401 emitcode ("pop", "dpl");
8403 _endLazyDPSEvaluation ();
8406 /* so dptr know contains the address */
8407 freeAsmop (result, NULL, ic, TRUE);
8408 aopOp (right, ic, FALSE, TRUE);
8410 /* if bit then unpack */
8411 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8412 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8415 size = AOP_SIZE (right);
8418 _startLazyDPSEvaluation ();
8421 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8427 emitcode ("movx", "@dptr,a");
8429 emitcode ("inc", "dptr");
8431 _endLazyDPSEvaluation ();
8434 freeAsmop (right, NULL, ic, TRUE);
8437 /*-----------------------------------------------------------------*/
8438 /* genGenPointerSet - set value from generic pointer space */
8439 /*-----------------------------------------------------------------*/
8441 genGenPointerSet (operand * right,
8442 operand * result, iCode * ic)
8445 sym_link *retype = getSpec (operandType (right));
8446 sym_link *letype = getSpec (operandType (result));
8448 aopOp (result, ic, FALSE, TRUE);
8450 /* if the operand is already in dptr
8451 then we do nothing else we move the value to dptr */
8452 if (AOP_TYPE (result) != AOP_STR)
8454 _startLazyDPSEvaluation ();
8455 /* if this is remateriazable */
8456 if (AOP_TYPE (result) == AOP_IMMD)
8458 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8459 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8462 { /* we need to get it byte by byte */
8463 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8464 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8465 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8466 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8468 _endLazyDPSEvaluation ();
8470 /* so dptr know contains the address */
8471 freeAsmop (result, NULL, ic, TRUE);
8472 aopOp (right, ic, FALSE, TRUE);
8474 /* if bit then unpack */
8475 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8476 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8479 size = AOP_SIZE (right);
8482 _startLazyDPSEvaluation ();
8485 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8491 emitcode ("lcall", "__gptrput");
8493 emitcode ("inc", "dptr");
8495 _endLazyDPSEvaluation ();
8498 freeAsmop (right, NULL, ic, TRUE);
8501 /*-----------------------------------------------------------------*/
8502 /* genPointerSet - stores the value into a pointer location */
8503 /*-----------------------------------------------------------------*/
8505 genPointerSet (iCode * ic)
8507 operand *right, *result;
8508 sym_link *type, *etype;
8511 D (emitcode (";", "genPointerSet ");
8514 right = IC_RIGHT (ic);
8515 result = IC_RESULT (ic);
8517 /* depending on the type of pointer we need to
8518 move it to the correct pointer register */
8519 type = operandType (result);
8520 etype = getSpec (type);
8521 /* if left is of type of pointer then it is simple */
8522 if (IS_PTR (type) && !IS_FUNC (type->next))
8524 p_type = DCL_TYPE (type);
8528 /* we have to go by the storage class */
8529 p_type = PTR_TYPE (SPEC_OCLS (etype));
8532 /* now that we have the pointer type we assign
8533 the pointer values */
8539 genNearPointerSet (right, result, ic);
8543 genPagedPointerSet (right, result, ic);
8547 genFarPointerSet (right, result, ic);
8551 genGenPointerSet (right, result, ic);
8557 /*-----------------------------------------------------------------*/
8558 /* genIfx - generate code for Ifx statement */
8559 /*-----------------------------------------------------------------*/
8561 genIfx (iCode * ic, iCode * popIc)
8563 operand *cond = IC_COND (ic);
8566 D (emitcode (";", "genIfx ");
8569 aopOp (cond, ic, FALSE, FALSE);
8571 /* get the value into acc */
8572 if (AOP_TYPE (cond) != AOP_CRY)
8576 /* the result is now in the accumulator */
8577 freeAsmop (cond, NULL, ic, TRUE);
8579 /* if there was something to be popped then do it */
8583 /* if the condition is a bit variable */
8584 if (isbit && IS_ITEMP (cond) &&
8586 genIfxJump (ic, SPIL_LOC (cond)->rname);
8587 else if (isbit && !IS_ITEMP (cond))
8588 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8590 genIfxJump (ic, "a");
8595 /*-----------------------------------------------------------------*/
8596 /* genAddrOf - generates code for address of */
8597 /*-----------------------------------------------------------------*/
8599 genAddrOf (iCode * ic)
8601 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8604 D (emitcode (";", "genAddrOf ");
8607 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8609 /* if the operand is on the stack then we
8610 need to get the stack offset of this
8614 /* if it has an offset then we need to compute
8618 emitcode ("mov", "a,_bp");
8619 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8620 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8624 /* we can just move _bp */
8625 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8627 /* fill the result with zero */
8628 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8631 if (options.stack10bit && size < (FPTRSIZE - 1))
8634 "*** warning: pointer to stack var truncated.\n");
8641 if (options.stack10bit && offset == 2)
8643 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8647 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8654 /* object not on stack then we need the name */
8655 size = AOP_SIZE (IC_RESULT (ic));
8660 char s[SDCC_NAME_MAX];
8662 sprintf (s, "#(%s >> %d)",
8666 sprintf (s, "#%s", sym->rname);
8667 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8671 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8675 /*-----------------------------------------------------------------*/
8676 /* genFarFarAssign - assignment when both are in far space */
8677 /*-----------------------------------------------------------------*/
8679 genFarFarAssign (operand * result, operand * right, iCode * ic)
8681 int size = AOP_SIZE (right);
8687 /* This is a net loss for size == 1, but a big gain
8690 D (emitcode (";", "genFarFarAssign (improved)");
8693 aopOp (result, ic, TRUE, TRUE);
8695 _startLazyDPSEvaluation ();
8698 aopPut (AOP (result),
8699 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8702 _endLazyDPSEvaluation ();
8703 freeAsmop (result, NULL, ic, FALSE);
8704 freeAsmop (right, NULL, ic, FALSE);
8708 D (emitcode (";", "genFarFarAssign ");
8711 /* first push the right side on to the stack */
8712 _startLazyDPSEvaluation ();
8715 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8717 emitcode ("push", "acc");
8720 freeAsmop (right, NULL, ic, FALSE);
8721 /* now assign DPTR to result */
8722 aopOp (result, ic, FALSE, FALSE);
8723 size = AOP_SIZE (result);
8726 emitcode ("pop", "acc");
8727 aopPut (AOP (result), "a", --offset);
8729 freeAsmop (result, NULL, ic, FALSE);
8730 _endLazyDPSEvaluation ();
8734 /*-----------------------------------------------------------------*/
8735 /* genAssign - generate code for assignment */
8736 /*-----------------------------------------------------------------*/
8738 genAssign (iCode * ic)
8740 operand *result, *right;
8742 unsigned long lit = 0L;
8744 D (emitcode (";", "genAssign ");
8747 result = IC_RESULT (ic);
8748 right = IC_RIGHT (ic);
8750 /* if they are the same */
8751 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8754 aopOp (right, ic, FALSE, FALSE);
8756 emitcode (";", "genAssign: resultIsFar = %s",
8757 isOperandInFarSpace (result) ?
8760 /* special case both in far space */
8761 if ((AOP_TYPE (right) == AOP_DPTR ||
8762 AOP_TYPE (right) == AOP_DPTR2) &&
8763 /* IS_TRUE_SYMOP(result) && */
8764 isOperandInFarSpace (result))
8766 genFarFarAssign (result, right, ic);
8770 aopOp (result, ic, TRUE, FALSE);
8772 /* if they are the same registers */
8773 if (sameRegs (AOP (right), AOP (result)))
8776 /* if the result is a bit */
8777 if (AOP_TYPE (result) == AOP_CRY)
8780 /* if the right size is a literal then
8781 we know what the value is */
8782 if (AOP_TYPE (right) == AOP_LIT)
8784 if (((int) operandLitValue (right)))
8785 aopPut (AOP (result), one, 0);
8787 aopPut (AOP (result), zero, 0);
8791 /* the right is also a bit variable */
8792 if (AOP_TYPE (right) == AOP_CRY)
8794 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8795 aopPut (AOP (result), "c", 0);
8801 aopPut (AOP (result), "a", 0);
8805 /* bit variables done */
8807 size = AOP_SIZE (result);
8809 if (AOP_TYPE (right) == AOP_LIT)
8810 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8813 (AOP_TYPE (result) != AOP_REG) &&
8814 (AOP_TYPE (right) == AOP_LIT) &&
8815 !IS_FLOAT (operandType (right)))
8817 D (emitcode (";", "Kevin's better literal load code");
8819 _startLazyDPSEvaluation ();
8820 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8822 aopPut (AOP (result),
8823 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8828 /* And now fill the rest with zeros. */
8831 emitcode ("clr", "a");
8835 aopPut (AOP (result), "a", offset++);
8837 _endLazyDPSEvaluation ();
8841 _startLazyDPSEvaluation ();
8844 aopPut (AOP (result),
8845 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8849 _endLazyDPSEvaluation ();
8853 freeAsmop (right, NULL, ic, FALSE);
8854 freeAsmop (result, NULL, ic, TRUE);
8857 /*-----------------------------------------------------------------*/
8858 /* genJumpTab - generates code for jump table */
8859 /*-----------------------------------------------------------------*/
8861 genJumpTab (iCode * ic)
8866 D (emitcode (";", "genJumpTab ");
8869 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8870 /* get the condition into accumulator */
8871 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8873 /* multiply by four! */
8874 emitcode ("add", "a,acc");
8875 emitcode ("add", "a,acc");
8876 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8878 jtab = newiTempLabel (NULL);
8879 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8880 emitcode ("jmp", "@a+dptr");
8881 emitcode ("", "%05d$:", jtab->key + 100);
8882 /* now generate the jump labels */
8883 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8884 jtab = setNextItem (IC_JTLABELS (ic)))
8885 emitcode ("ljmp", "%05d$", jtab->key + 100);
8889 /*-----------------------------------------------------------------*/
8890 /* genCast - gen code for casting */
8891 /*-----------------------------------------------------------------*/
8893 genCast (iCode * ic)
8895 operand *result = IC_RESULT (ic);
8896 sym_link *ctype = operandType (IC_LEFT (ic));
8897 sym_link *rtype = operandType (IC_RIGHT (ic));
8898 operand *right = IC_RIGHT (ic);
8901 D (emitcode (";", "genCast ");
8904 /* if they are equivalent then do nothing */
8905 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8908 aopOp (right, ic, FALSE, FALSE);
8909 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8911 /* if the result is a bit */
8912 if (AOP_TYPE (result) == AOP_CRY)
8914 /* if the right size is a literal then
8915 we know what the value is */
8916 if (AOP_TYPE (right) == AOP_LIT)
8918 if (((int) operandLitValue (right)))
8919 aopPut (AOP (result), one, 0);
8921 aopPut (AOP (result), zero, 0);
8926 /* the right is also a bit variable */
8927 if (AOP_TYPE (right) == AOP_CRY)
8929 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8930 aopPut (AOP (result), "c", 0);
8936 aopPut (AOP (result), "a", 0);
8940 /* if they are the same size : or less */
8941 if (AOP_SIZE (result) <= AOP_SIZE (right))
8944 /* if they are in the same place */
8945 if (sameRegs (AOP (right), AOP (result)))
8948 /* if they in different places then copy */
8949 size = AOP_SIZE (result);
8951 _startLazyDPSEvaluation ();
8954 aopPut (AOP (result),
8955 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8959 _endLazyDPSEvaluation ();
8964 /* if the result is of type pointer */
8969 sym_link *type = operandType (right);
8971 /* pointer to generic pointer */
8972 if (IS_GENPTR (ctype))
8978 p_type = DCL_TYPE (type);
8982 #if OLD_CAST_BEHAVIOR
8983 /* KV: we are converting a non-pointer type to
8984 * a generic pointer. This (ifdef'd out) code
8985 * says that the resulting generic pointer
8986 * should have the same class as the storage
8987 * location of the non-pointer variable.
8989 * For example, converting an int (which happens
8990 * to be stored in DATA space) to a pointer results
8991 * in a DATA generic pointer; if the original int
8992 * in XDATA space, so will be the resulting pointer.
8994 * I don't like that behavior, and thus this change:
8995 * all such conversions will be forced to XDATA and
8996 * throw a warning. If you want some non-XDATA
8997 * type, or you want to suppress the warning, you
8998 * must go through an intermediate cast, like so:
9000 * char _generic *gp = (char _xdata *)(intVar);
9002 sym_link *etype = getSpec (type);
9004 /* we have to go by the storage class */
9005 if (SPEC_OCLS (etype) != generic)
9007 p_type = PTR_TYPE (SPEC_OCLS (etype));
9012 /* Converting unknown class (i.e. register variable)
9013 * to generic pointer. This is not good, but
9014 * we'll make a guess (and throw a warning).
9017 werror (W_INT_TO_GEN_PTR_CAST);
9021 /* the first two bytes are known */
9022 size = GPTRSIZE - 1;
9024 _startLazyDPSEvaluation ();
9027 aopPut (AOP (result),
9028 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9032 _endLazyDPSEvaluation ();
9034 /* the last byte depending on type */
9052 /* this should never happen */
9053 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9054 "got unknown pointer type");
9057 aopPut (AOP (result), l, GPTRSIZE - 1);
9061 /* just copy the pointers */
9062 size = AOP_SIZE (result);
9064 _startLazyDPSEvaluation ();
9067 aopPut (AOP (result),
9068 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9072 _endLazyDPSEvaluation ();
9076 /* so we now know that the size of destination is greater
9077 than the size of the source */
9078 /* we move to result for the size of source */
9079 size = AOP_SIZE (right);
9081 _startLazyDPSEvaluation ();
9084 aopPut (AOP (result),
9085 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9089 _endLazyDPSEvaluation ();
9091 /* now depending on the sign of the source && destination */
9092 size = AOP_SIZE (result) - AOP_SIZE (right);
9093 /* if unsigned or not an integral type */
9094 /* also, if the source is a bit, we don't need to sign extend, because
9095 * it can't possibly have set the sign bit.
9097 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9101 aopPut (AOP (result), zero, offset++);
9106 /* we need to extend the sign :{ */
9107 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9108 FALSE, FALSE, TRUE);
9110 emitcode ("rlc", "a");
9111 emitcode ("subb", "a,acc");
9113 aopPut (AOP (result), "a", offset++);
9116 /* we are done hurray !!!! */
9119 freeAsmop (right, NULL, ic, TRUE);
9120 freeAsmop (result, NULL, ic, TRUE);
9124 /*-----------------------------------------------------------------*/
9125 /* genDjnz - generate decrement & jump if not zero instrucion */
9126 /*-----------------------------------------------------------------*/
9128 genDjnz (iCode * ic, iCode * ifx)
9134 /* if the if condition has a false label
9135 then we cannot save */
9139 /* if the minus is not of the form
9141 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9142 !IS_OP_LITERAL (IC_RIGHT (ic)))
9145 if (operandLitValue (IC_RIGHT (ic)) != 1)
9148 /* if the size of this greater than one then no
9150 if (getSize (operandType (IC_RESULT (ic))) > 1)
9153 /* otherwise we can save BIG */
9154 lbl = newiTempLabel (NULL);
9155 lbl1 = newiTempLabel (NULL);
9157 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9159 if (IS_AOP_PREG (IC_RESULT (ic)))
9161 emitcode ("dec", "%s",
9162 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9163 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9164 emitcode ("jnz", "%05d$", lbl->key + 100);
9168 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9171 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9172 emitcode ("", "%05d$:", lbl->key + 100);
9173 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9174 emitcode ("", "%05d$:", lbl1->key + 100);
9176 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9181 /*-----------------------------------------------------------------*/
9182 /* genReceive - generate code for a receive iCode */
9183 /*-----------------------------------------------------------------*/
9185 genReceive (iCode * ic)
9188 D (emitcode (";", "genReceive ");
9191 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9192 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9193 IS_TRUE_SYMOP (IC_RESULT (ic))))
9195 int size = getSize (operandType (IC_RESULT (ic)));
9196 int offset = fReturnSizeDS390 - size;
9199 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9200 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9203 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9204 size = AOP_SIZE (IC_RESULT (ic));
9208 emitcode ("pop", "acc");
9209 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9216 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9218 assignResultValue (IC_RESULT (ic));
9221 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9224 /*-----------------------------------------------------------------*/
9225 /* gen390Code - generate code for Dallas 390 based controllers */
9226 /*-----------------------------------------------------------------*/
9228 gen390Code (iCode * lic)
9233 lineHead = lineCurr = NULL;
9237 /* print the allocation information */
9239 printAllocInfo (currFunc, codeOutFile);
9241 /* if debug information required */
9242 if (options.debug && currFunc)
9244 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9246 if (IS_STATIC (currFunc->etype))
9247 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9249 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9252 /* stack pointer name */
9253 if (options.useXstack)
9259 for (ic = lic; ic; ic = ic->next)
9262 if (cln != ic->lineno)
9267 emitcode ("", "C$%s$%d$%d$%d ==.",
9268 FileBaseName (ic->filename), ic->lineno,
9269 ic->level, ic->block);
9272 emitcode (";", "%s %d", ic->filename, ic->lineno);
9275 /* if the result is marked as
9276 spilt and rematerializable or code for
9277 this has already been generated then
9279 if (resultRemat (ic) || ic->generated)
9282 /* depending on the operation */
9302 /* IPOP happens only when trying to restore a
9303 spilt live range, if there is an ifx statement
9304 following this pop then the if statement might
9305 be using some of the registers being popped which
9306 would destory the contents of the register so
9307 we need to check for this condition and handle it */
9309 ic->next->op == IFX &&
9310 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9311 genIfx (ic->next, ic);
9329 genEndFunction (ic);
9349 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9366 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9370 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9377 /* note these two are xlated by algebraic equivalence
9378 during parsing SDCC.y */
9379 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9380 "got '>=' or '<=' shouldn't have come here");
9384 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9396 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9400 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9404 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9431 case GET_VALUE_AT_ADDRESS:
9436 if (POINTER_SET (ic))
9463 addSet (&_G.sendSet, ic);
9468 /* piCode(ic,stdout); */
9474 /* now we are ready to call the
9475 peep hole optimizer */
9476 if (!options.nopeep)
9477 peepHole (&lineHead);
9479 /* now do the actual printing */
9480 printLine (lineHead, codeOutFile);