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
6157 emitcode ("anl", "a,#0x%02x",
6158 SRMask[shCount]); // 000000BB:CCCCCCDD
6159 emitcode ("mov", "c,acc.0"); // c = B
6160 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6162 AccAXRrl1 (x); // BCCCCCCD:D000000B
6163 AccAXRrl1 (x); // BBCCCCCC:DD000000
6165 emitcode("rrc","a");
6166 emitcode("xch","a,%s", x);
6167 emitcode("rrc","a");
6168 emitcode("mov","c,acc.0"); //<< get correct bit
6169 emitcode("xch","a,%s", x);
6171 emitcode("rrc","a");
6172 emitcode("xch","a,%s", x);
6173 emitcode("rrc","a");
6174 emitcode("xch","a,%s", x);
6177 case 7: // a:x <<= 7
6179 emitcode ("anl", "a,#0x%02x",
6180 SRMask[shCount]); // 0000000B:CCCCCCCD
6182 emitcode ("mov", "c,acc.0"); // c = B
6184 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6186 AccAXRrl1 (x); // BCCCCCCC:D0000000
6197 /*-----------------------------------------------------------------*/
6198 /* AccAXRsh - right shift a:x known count (0..7) */
6199 /*-----------------------------------------------------------------*/
6201 AccAXRsh (char *x, int shCount)
6209 AccAXRrl1 (x); // 0->a:x
6214 AccAXRrl1 (x); // 0->a:x
6217 AccAXRrl1 (x); // 0->a:x
6222 case 5: // AAAAABBB:CCCCCDDD = a:x
6224 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6226 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6228 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6230 emitcode ("anl", "a,#0x%02x",
6231 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6233 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6235 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6237 emitcode ("anl", "a,#0x%02x",
6238 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6240 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6242 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6244 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6247 case 6: // AABBBBBB:CCDDDDDD
6249 emitcode ("mov", "c,acc.7");
6250 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6252 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6254 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6256 emitcode ("anl", "a,#0x%02x",
6257 SRMask[shCount]); // 000000AA:BBBBBBCC
6260 case 7: // ABBBBBBB:CDDDDDDD
6262 emitcode ("mov", "c,acc.7"); // c = A
6264 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6266 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6268 emitcode ("anl", "a,#0x%02x",
6269 SRMask[shCount]); // 0000000A:BBBBBBBC
6280 /*-----------------------------------------------------------------*/
6281 /* AccAXRshS - right shift signed a:x known count (0..7) */
6282 /*-----------------------------------------------------------------*/
6284 AccAXRshS (char *x, int shCount)
6292 emitcode ("mov", "c,acc.7");
6293 AccAXRrl1 (x); // s->a:x
6297 emitcode ("mov", "c,acc.7");
6298 AccAXRrl1 (x); // s->a:x
6300 emitcode ("mov", "c,acc.7");
6301 AccAXRrl1 (x); // s->a:x
6306 case 5: // AAAAABBB:CCCCCDDD = a:x
6308 tlbl = newiTempLabel (NULL);
6309 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6311 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6313 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6315 emitcode ("anl", "a,#0x%02x",
6316 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6318 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6320 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6322 emitcode ("anl", "a,#0x%02x",
6323 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6325 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6327 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6329 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6331 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6332 emitcode ("orl", "a,#0x%02x",
6333 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6335 emitcode ("", "%05d$:", tlbl->key + 100);
6336 break; // SSSSAAAA:BBBCCCCC
6338 case 6: // AABBBBBB:CCDDDDDD
6340 tlbl = newiTempLabel (NULL);
6341 emitcode ("mov", "c,acc.7");
6342 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6344 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6346 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6348 emitcode ("anl", "a,#0x%02x",
6349 SRMask[shCount]); // 000000AA:BBBBBBCC
6351 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6352 emitcode ("orl", "a,#0x%02x",
6353 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6355 emitcode ("", "%05d$:", tlbl->key + 100);
6357 case 7: // ABBBBBBB:CDDDDDDD
6359 tlbl = newiTempLabel (NULL);
6360 emitcode ("mov", "c,acc.7"); // c = A
6362 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6364 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6366 emitcode ("anl", "a,#0x%02x",
6367 SRMask[shCount]); // 0000000A:BBBBBBBC
6369 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6370 emitcode ("orl", "a,#0x%02x",
6371 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6373 emitcode ("", "%05d$:", tlbl->key + 100);
6383 /*-----------------------------------------------------------------*/
6384 /* shiftL2Left2Result - shift left two bytes from left to result */
6385 /*-----------------------------------------------------------------*/
6387 shiftL2Left2Result (operand * left, int offl,
6388 operand * result, int offr, int shCount)
6390 if (sameRegs (AOP (result), AOP (left)) &&
6391 ((offl + MSB16) == offr))
6393 /* don't crash result[offr] */
6394 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6395 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6399 movLeft2Result (left, offl, result, offr, 0);
6400 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6402 /* ax << shCount (x = lsb(result)) */
6403 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6404 aopPut (AOP (result), "a", offr + MSB16);
6410 /*-----------------------------------------------------------------*/
6411 /* shiftR2Left2Result - shift right two bytes from left to result */
6412 /*-----------------------------------------------------------------*/
6414 shiftR2Left2Result (operand * left, int offl,
6415 operand * result, int offr,
6416 int shCount, int sign)
6418 if (sameRegs (AOP (result), AOP (left)) &&
6419 ((offl + MSB16) == offr))
6421 /* don't crash result[offr] */
6422 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6423 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6427 movLeft2Result (left, offl, result, offr, 0);
6428 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6430 /* a:x >> shCount (x = lsb(result)) */
6432 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6434 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6435 if (getDataSize (result) > 1)
6436 aopPut (AOP (result), "a", offr + MSB16);
6442 /*-----------------------------------------------------------------*/
6443 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6444 /*-----------------------------------------------------------------*/
6446 shiftLLeftOrResult (operand * left, int offl,
6447 operand * result, int offr, int shCount)
6449 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6450 /* shift left accumulator */
6452 /* or with result */
6453 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6454 /* back to result */
6455 aopPut (AOP (result), "a", offr);
6461 /*-----------------------------------------------------------------*/
6462 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6463 /*-----------------------------------------------------------------*/
6465 shiftRLeftOrResult (operand * left, int offl,
6466 operand * result, int offr, int shCount)
6468 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6469 /* shift right accumulator */
6471 /* or with result */
6472 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6473 /* back to result */
6474 aopPut (AOP (result), "a", offr);
6480 /*-----------------------------------------------------------------*/
6481 /* genlshOne - left shift a one byte quantity by known count */
6482 /*-----------------------------------------------------------------*/
6484 genlshOne (operand * result, operand * left, int shCount)
6486 D (emitcode (";", "genlshOne ");
6488 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6494 /*-----------------------------------------------------------------*/
6495 /* genlshTwo - left shift two bytes by known amount != 0 */
6496 /*-----------------------------------------------------------------*/
6498 genlshTwo (operand * result, operand * left, int shCount)
6502 D (emitcode (";", "genlshTwo ");
6505 size = getDataSize (result);
6507 /* if shCount >= 8 */
6515 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6517 movLeft2Result (left, LSB, result, MSB16, 0);
6519 aopPut (AOP (result), zero, LSB);
6522 /* 1 <= shCount <= 7 */
6526 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6528 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6535 /*-----------------------------------------------------------------*/
6536 /* shiftLLong - shift left one long from left to result */
6537 /* offl = LSB or MSB16 */
6538 /*-----------------------------------------------------------------*/
6540 shiftLLong (operand * left, operand * result, int offr)
6543 int size = AOP_SIZE (result);
6545 if (size >= LSB + offr)
6547 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6549 emitcode ("add", "a,acc");
6550 if (sameRegs (AOP (left), AOP (result)) &&
6551 size >= MSB16 + offr && offr != LSB)
6552 emitcode ("xch", "a,%s",
6553 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6555 aopPut (AOP (result), "a", LSB + offr);
6558 if (size >= MSB16 + offr)
6560 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6562 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6565 emitcode ("rlc", "a");
6566 if (sameRegs (AOP (left), AOP (result)) &&
6567 size >= MSB24 + offr && offr != LSB)
6568 emitcode ("xch", "a,%s",
6569 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6571 aopPut (AOP (result), "a", MSB16 + offr);
6574 if (size >= MSB24 + offr)
6576 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6578 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6581 emitcode ("rlc", "a");
6582 if (sameRegs (AOP (left), AOP (result)) &&
6583 size >= MSB32 + offr && offr != LSB)
6584 emitcode ("xch", "a,%s",
6585 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6587 aopPut (AOP (result), "a", MSB24 + offr);
6590 if (size > MSB32 + offr)
6592 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6594 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6597 emitcode ("rlc", "a");
6598 aopPut (AOP (result), "a", MSB32 + offr);
6601 aopPut (AOP (result), zero, LSB);
6607 /*-----------------------------------------------------------------*/
6608 /* genlshFour - shift four byte by a known amount != 0 */
6609 /*-----------------------------------------------------------------*/
6611 genlshFour (operand * result, operand * left, int shCount)
6615 D (emitcode (";", "genlshFour ");
6618 size = AOP_SIZE (result);
6620 /* if shifting more that 3 bytes */
6625 /* lowest order of left goes to the highest
6626 order of the destination */
6627 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6629 movLeft2Result (left, LSB, result, MSB32, 0);
6630 aopPut (AOP (result), zero, LSB);
6631 aopPut (AOP (result), zero, MSB16);
6632 aopPut (AOP (result), zero, MSB32);
6636 /* more than two bytes */
6637 else if (shCount >= 16)
6639 /* lower order two bytes goes to higher order two bytes */
6641 /* if some more remaining */
6643 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6646 movLeft2Result (left, MSB16, result, MSB32, 0);
6647 movLeft2Result (left, LSB, result, MSB24, 0);
6649 aopPut (AOP (result), zero, MSB16);
6650 aopPut (AOP (result), zero, LSB);
6654 /* if more than 1 byte */
6655 else if (shCount >= 8)
6657 /* lower order three bytes goes to higher order three bytes */
6662 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6664 movLeft2Result (left, LSB, result, MSB16, 0);
6670 movLeft2Result (left, MSB24, result, MSB32, 0);
6671 movLeft2Result (left, MSB16, result, MSB24, 0);
6672 movLeft2Result (left, LSB, result, MSB16, 0);
6673 aopPut (AOP (result), zero, LSB);
6675 else if (shCount == 1)
6676 shiftLLong (left, result, MSB16);
6679 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6680 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6681 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6682 aopPut (AOP (result), zero, LSB);
6687 /* 1 <= shCount <= 7 */
6688 else if (shCount <= 2)
6690 shiftLLong (left, result, LSB);
6692 shiftLLong (result, result, LSB);
6694 /* 3 <= shCount <= 7, optimize */
6697 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6698 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6699 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6706 /*-----------------------------------------------------------------*/
6707 /* genLeftShiftLiteral - left shifting by known count */
6708 /*-----------------------------------------------------------------*/
6710 genLeftShiftLiteral (operand * left,
6715 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6718 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6721 freeAsmop (right, NULL, ic, TRUE);
6723 aopOp (left, ic, FALSE, FALSE);
6724 aopOp (result, ic, FALSE, TRUE);
6726 size = getSize (operandType (result));
6729 emitcode ("; shift left ", "result %d, left %d", size,
6733 /* I suppose that the left size >= result size */
6738 movLeft2Result (left, size, result, size, 0);
6742 else if (shCount >= (size * 8))
6744 aopPut (AOP (result), zero, size);
6750 genlshOne (result, left, shCount);
6754 case 3: /* bug: this is for generic pointers, I bet. */
6755 genlshTwo (result, left, shCount);
6759 genlshFour (result, left, shCount);
6763 freeAsmop (left, NULL, ic, TRUE);
6764 freeAsmop (result, NULL, ic, TRUE);
6768 /*-----------------------------------------------------------------*/
6769 /* genLeftShift - generates code for left shifting */
6770 /*-----------------------------------------------------------------*/
6772 genLeftShift (iCode * ic)
6774 operand *left, *right, *result;
6777 symbol *tlbl, *tlbl1;
6779 D (emitcode (";", "genLeftShift ");
6782 right = IC_RIGHT (ic);
6783 left = IC_LEFT (ic);
6784 result = IC_RESULT (ic);
6786 aopOp (right, ic, FALSE, FALSE);
6789 /* if the shift count is known then do it
6790 as efficiently as possible */
6791 if (AOP_TYPE (right) == AOP_LIT)
6793 genLeftShiftLiteral (left, right, result, ic);
6798 /* shift count is unknown then we have to form
6799 a loop get the loop count in B : Note: we take
6800 only the lower order byte since shifting
6801 more that 32 bits make no sense anyway, ( the
6802 largest size of an object can be only 32 bits ) */
6804 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6805 emitcode ("inc", "b");
6806 freeAsmop (right, NULL, ic, TRUE);
6807 aopOp (left, ic, FALSE, FALSE);
6808 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6810 /* now move the left to the result if they are not the
6812 if (!sameRegs (AOP (left), AOP (result)) &&
6813 AOP_SIZE (result) > 1)
6816 size = AOP_SIZE (result);
6818 _startLazyDPSEvaluation ();
6821 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6822 if (*l == '@' && (IS_AOP_PREG (result)))
6825 emitcode ("mov", "a,%s", l);
6826 aopPut (AOP (result), "a", offset);
6829 aopPut (AOP (result), l, offset);
6832 _endLazyDPSEvaluation ();
6835 tlbl = newiTempLabel (NULL);
6836 size = AOP_SIZE (result);
6838 tlbl1 = newiTempLabel (NULL);
6840 /* if it is only one byte then */
6843 symbol *tlbl1 = newiTempLabel (NULL);
6845 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6847 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6848 emitcode ("", "%05d$:", tlbl->key + 100);
6849 emitcode ("add", "a,acc");
6850 emitcode ("", "%05d$:", tlbl1->key + 100);
6851 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6852 aopPut (AOP (result), "a", 0);
6856 reAdjustPreg (AOP (result));
6858 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6859 emitcode ("", "%05d$:", tlbl->key + 100);
6860 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6862 emitcode ("add", "a,acc");
6863 aopPut (AOP (result), "a", offset++);
6864 _startLazyDPSEvaluation ();
6867 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6869 emitcode ("rlc", "a");
6870 aopPut (AOP (result), "a", offset++);
6872 _endLazyDPSEvaluation ();
6873 reAdjustPreg (AOP (result));
6875 emitcode ("", "%05d$:", tlbl1->key + 100);
6876 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6878 freeAsmop (left, NULL, ic, TRUE);
6879 freeAsmop (result, NULL, ic, TRUE);
6884 /*-----------------------------------------------------------------*/
6885 /* genrshOne - right shift a one byte quantity by known count */
6886 /*-----------------------------------------------------------------*/
6888 genrshOne (operand * result, operand * left,
6889 int shCount, int sign)
6891 D (emitcode (";", "genrshOne");
6893 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6899 /*-----------------------------------------------------------------*/
6900 /* genrshTwo - right shift two bytes by known amount != 0 */
6901 /*-----------------------------------------------------------------*/
6903 genrshTwo (operand * result, operand * left,
6904 int shCount, int sign)
6906 D (emitcode (";", "genrshTwo");
6909 /* if shCount >= 8 */
6914 shiftR1Left2Result (left, MSB16, result, LSB,
6917 movLeft2Result (left, MSB16, result, LSB, sign);
6918 addSign (result, MSB16, sign);
6921 /* 1 <= shCount <= 7 */
6923 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6929 /*-----------------------------------------------------------------*/
6930 /* shiftRLong - shift right one long from left to result */
6931 /* offl = LSB or MSB16 */
6932 /*-----------------------------------------------------------------*/
6934 shiftRLong (operand * left, int offl,
6935 operand * result, int sign)
6938 emitcode ("clr", "c");
6939 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6941 emitcode ("mov", "c,acc.7");
6942 emitcode ("rrc", "a");
6943 aopPut (AOP (result), "a", MSB32 - offl);
6945 /* add sign of "a" */
6946 addSign (result, MSB32, sign);
6948 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6949 emitcode ("rrc", "a");
6950 aopPut (AOP (result), "a", MSB24 - offl);
6952 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6953 emitcode ("rrc", "a");
6954 aopPut (AOP (result), "a", MSB16 - offl);
6958 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6959 emitcode ("rrc", "a");
6960 aopPut (AOP (result), "a", LSB);
6967 /*-----------------------------------------------------------------*/
6968 /* genrshFour - shift four byte by a known amount != 0 */
6969 /*-----------------------------------------------------------------*/
6971 genrshFour (operand * result, operand * left,
6972 int shCount, int sign)
6974 D (emitcode (";", "genrshFour");
6977 /* if shifting more that 3 bytes */
6982 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6984 movLeft2Result (left, MSB32, result, LSB, sign);
6985 addSign (result, MSB16, sign);
6987 else if (shCount >= 16)
6991 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6994 movLeft2Result (left, MSB24, result, LSB, 0);
6995 movLeft2Result (left, MSB32, result, MSB16, sign);
6997 addSign (result, MSB24, sign);
6999 else if (shCount >= 8)
7003 shiftRLong (left, MSB16, result, sign);
7004 else if (shCount == 0)
7006 movLeft2Result (left, MSB16, result, LSB, 0);
7007 movLeft2Result (left, MSB24, result, MSB16, 0);
7008 movLeft2Result (left, MSB32, result, MSB24, sign);
7009 addSign (result, MSB32, sign);
7013 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7014 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7015 /* the last shift is signed */
7016 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7017 addSign (result, MSB32, sign);
7021 { /* 1 <= shCount <= 7 */
7024 shiftRLong (left, LSB, result, sign);
7026 shiftRLong (result, LSB, result, sign);
7030 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7031 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7032 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7040 /*-----------------------------------------------------------------*/
7041 /* genRightShiftLiteral - right shifting by known count */
7042 /*-----------------------------------------------------------------*/
7044 genRightShiftLiteral (operand * left,
7050 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7053 D (emitcode (";", "genRightShiftLiteral");
7056 freeAsmop (right, NULL, ic, TRUE);
7058 aopOp (left, ic, FALSE, FALSE);
7059 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7062 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7066 size = getDataSize (left);
7067 /* test the LEFT size !!! */
7069 /* I suppose that the left size >= result size */
7072 size = getDataSize (result);
7074 movLeft2Result (left, size, result, size, 0);
7077 else if (shCount >= (size * 8))
7080 /* get sign in acc.7 */
7081 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7082 addSign (result, LSB, sign);
7089 genrshOne (result, left, shCount, sign);
7093 genrshTwo (result, left, shCount, sign);
7097 genrshFour (result, left, shCount, sign);
7103 freeAsmop (left, NULL, ic, TRUE);
7104 freeAsmop (result, NULL, ic, TRUE);
7109 /*-----------------------------------------------------------------*/
7110 /* genSignedRightShift - right shift of signed number */
7111 /*-----------------------------------------------------------------*/
7113 genSignedRightShift (iCode * ic)
7115 operand *right, *left, *result;
7118 symbol *tlbl, *tlbl1;
7120 D (emitcode (";", "genSignedRightShift ");
7123 /* we do it the hard way put the shift count in b
7124 and loop thru preserving the sign */
7126 right = IC_RIGHT (ic);
7127 left = IC_LEFT (ic);
7128 result = IC_RESULT (ic);
7130 aopOp (right, ic, FALSE, FALSE);
7133 if (AOP_TYPE (right) == AOP_LIT)
7135 genRightShiftLiteral (left, right, result, ic, 1);
7139 /* shift count is unknown then we have to form
7140 a loop get the loop count in B : Note: we take
7141 only the lower order byte since shifting
7142 more that 32 bits make no sense anyway, ( the
7143 largest size of an object can be only 32 bits ) */
7145 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7146 emitcode ("inc", "b");
7147 freeAsmop (right, NULL, ic, TRUE);
7148 aopOp (left, ic, FALSE, FALSE);
7149 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7151 /* now move the left to the result if they are not the
7153 if (!sameRegs (AOP (left), AOP (result)) &&
7154 AOP_SIZE (result) > 1)
7157 size = AOP_SIZE (result);
7159 _startLazyDPSEvaluation ();
7162 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7163 if (*l == '@' && IS_AOP_PREG (result))
7166 emitcode ("mov", "a,%s", l);
7167 aopPut (AOP (result), "a", offset);
7170 aopPut (AOP (result), l, offset);
7173 _endLazyDPSEvaluation ();
7176 /* mov the highest order bit to OVR */
7177 tlbl = newiTempLabel (NULL);
7178 tlbl1 = newiTempLabel (NULL);
7180 size = AOP_SIZE (result);
7182 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7183 emitcode ("rlc", "a");
7184 emitcode ("mov", "ov,c");
7185 /* if it is only one byte then */
7188 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7190 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7191 emitcode ("", "%05d$:", tlbl->key + 100);
7192 emitcode ("mov", "c,ov");
7193 emitcode ("rrc", "a");
7194 emitcode ("", "%05d$:", tlbl1->key + 100);
7195 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7196 aopPut (AOP (result), "a", 0);
7200 reAdjustPreg (AOP (result));
7201 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7202 emitcode ("", "%05d$:", tlbl->key + 100);
7203 emitcode ("mov", "c,ov");
7204 _startLazyDPSEvaluation ();
7207 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7209 emitcode ("rrc", "a");
7210 aopPut (AOP (result), "a", offset--);
7212 _endLazyDPSEvaluation ();
7213 reAdjustPreg (AOP (result));
7214 emitcode ("", "%05d$:", tlbl1->key + 100);
7215 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7218 freeAsmop (left, NULL, ic, TRUE);
7219 freeAsmop (result, NULL, ic, TRUE);
7222 /*-----------------------------------------------------------------*/
7223 /* genRightShift - generate code for right shifting */
7224 /*-----------------------------------------------------------------*/
7226 genRightShift (iCode * ic)
7228 operand *right, *left, *result;
7232 symbol *tlbl, *tlbl1;
7234 D (emitcode (";", "genRightShift ");
7237 /* if signed then we do it the hard way preserve the
7238 sign bit moving it inwards */
7239 retype = getSpec (operandType (IC_RESULT (ic)));
7241 if (!SPEC_USIGN (retype))
7243 genSignedRightShift (ic);
7247 /* signed & unsigned types are treated the same : i.e. the
7248 signed is NOT propagated inwards : quoting from the
7249 ANSI - standard : "for E1 >> E2, is equivalent to division
7250 by 2**E2 if unsigned or if it has a non-negative value,
7251 otherwise the result is implementation defined ", MY definition
7252 is that the sign does not get propagated */
7254 right = IC_RIGHT (ic);
7255 left = IC_LEFT (ic);
7256 result = IC_RESULT (ic);
7258 aopOp (right, ic, FALSE, FALSE);
7261 /* if the shift count is known then do it
7262 as efficiently as possible */
7263 if (AOP_TYPE (right) == AOP_LIT)
7265 genRightShiftLiteral (left, right, result, ic, 0);
7270 /* shift count is unknown then we have to form
7271 a loop get the loop count in B : Note: we take
7272 only the lower order byte since shifting
7273 more that 32 bits make no sense anyway, ( the
7274 largest size of an object can be only 32 bits ) */
7276 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7277 emitcode ("inc", "b");
7278 freeAsmop (right, NULL, ic, TRUE);
7279 aopOp (left, ic, FALSE, FALSE);
7280 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7282 /* now move the left to the result if they are not the
7284 if (!sameRegs (AOP (left), AOP (result)) &&
7285 AOP_SIZE (result) > 1)
7288 size = AOP_SIZE (result);
7290 _startLazyDPSEvaluation ();
7293 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7294 if (*l == '@' && IS_AOP_PREG (result))
7297 emitcode ("mov", "a,%s", l);
7298 aopPut (AOP (result), "a", offset);
7301 aopPut (AOP (result), l, offset);
7304 _endLazyDPSEvaluation ();
7307 tlbl = newiTempLabel (NULL);
7308 tlbl1 = newiTempLabel (NULL);
7309 size = AOP_SIZE (result);
7312 /* if it is only one byte then */
7315 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7317 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7318 emitcode ("", "%05d$:", tlbl->key + 100);
7320 emitcode ("rrc", "a");
7321 emitcode ("", "%05d$:", tlbl1->key + 100);
7322 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7323 aopPut (AOP (result), "a", 0);
7327 reAdjustPreg (AOP (result));
7328 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7329 emitcode ("", "%05d$:", tlbl->key + 100);
7331 _startLazyDPSEvaluation ();
7334 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7336 emitcode ("rrc", "a");
7337 aopPut (AOP (result), "a", offset--);
7339 _endLazyDPSEvaluation ();
7340 reAdjustPreg (AOP (result));
7342 emitcode ("", "%05d$:", tlbl1->key + 100);
7343 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7346 freeAsmop (left, NULL, ic, TRUE);
7347 freeAsmop (result, NULL, ic, TRUE);
7350 /*-----------------------------------------------------------------*/
7351 /* genUnpackBits - generates code for unpacking bits */
7352 /*-----------------------------------------------------------------*/
7354 genUnpackBits (operand * result, char *rname, int ptype)
7361 D (emitcode (";", "genUnpackBits ");
7364 etype = getSpec (operandType (result));
7366 /* read the first byte */
7372 emitcode ("mov", "a,@%s", rname);
7376 emitcode ("movx", "a,@%s", rname);
7380 emitcode ("movx", "a,@dptr");
7384 emitcode ("clr", "a");
7385 emitcode ("movc", "a", "@a+dptr");
7389 emitcode ("lcall", "__gptrget");
7393 /* if we have bitdisplacement then it fits */
7394 /* into this byte completely or if length is */
7395 /* less than a byte */
7396 if ((shCnt = SPEC_BSTR (etype)) ||
7397 (SPEC_BLEN (etype) <= 8))
7400 /* shift right acc */
7403 emitcode ("anl", "a,#0x%02x",
7404 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7405 aopPut (AOP (result), "a", offset);
7409 /* bit field did not fit in a byte */
7410 rlen = SPEC_BLEN (etype) - 8;
7411 aopPut (AOP (result), "a", offset++);
7420 emitcode ("inc", "%s", rname);
7421 emitcode ("mov", "a,@%s", rname);
7425 emitcode ("inc", "%s", rname);
7426 emitcode ("movx", "a,@%s", rname);
7430 emitcode ("inc", "dptr");
7431 emitcode ("movx", "a,@dptr");
7435 emitcode ("clr", "a");
7436 emitcode ("inc", "dptr");
7437 emitcode ("movc", "a", "@a+dptr");
7441 emitcode ("inc", "dptr");
7442 emitcode ("lcall", "__gptrget");
7447 /* if we are done */
7451 aopPut (AOP (result), "a", offset++);
7457 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7458 aopPut (AOP (result), "a", offset);
7465 /*-----------------------------------------------------------------*/
7466 /* genDataPointerGet - generates code when ptr offset is known */
7467 /*-----------------------------------------------------------------*/
7469 genDataPointerGet (operand * left,
7475 int size, offset = 0;
7476 aopOp (result, ic, TRUE, FALSE);
7478 /* get the string representation of the name */
7479 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7480 size = AOP_SIZE (result);
7481 _startLazyDPSEvaluation ();
7485 sprintf (buffer, "(%s + %d)", l + 1, offset);
7487 sprintf (buffer, "%s", l + 1);
7488 aopPut (AOP (result), buffer, offset++);
7490 _endLazyDPSEvaluation ();
7492 freeAsmop (left, NULL, ic, TRUE);
7493 freeAsmop (result, NULL, ic, TRUE);
7496 /*-----------------------------------------------------------------*/
7497 /* genNearPointerGet - emitcode for near pointer fetch */
7498 /*-----------------------------------------------------------------*/
7500 genNearPointerGet (operand * left,
7507 sym_link *rtype, *retype, *letype;
7508 sym_link *ltype = operandType (left);
7511 rtype = operandType (result);
7512 retype = getSpec (rtype);
7513 letype = getSpec (ltype);
7515 aopOp (left, ic, FALSE, FALSE);
7517 /* if left is rematerialisable and
7518 result is not bit variable type and
7519 the left is pointer to data space i.e
7520 lower 128 bytes of space */
7521 if (AOP_TYPE (left) == AOP_IMMD &&
7522 !IS_BITVAR (retype) &&
7523 !IS_BITVAR (letype) &&
7524 DCL_TYPE (ltype) == POINTER)
7526 genDataPointerGet (left, result, ic);
7530 /* if the value is already in a pointer register
7531 then don't need anything more */
7532 if (!AOP_INPREG (AOP (left)))
7534 /* otherwise get a free pointer register */
7536 preg = getFreePtr (ic, &aop, FALSE);
7537 emitcode ("mov", "%s,%s",
7539 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7543 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7545 freeAsmop (left, NULL, ic, TRUE);
7546 aopOp (result, ic, FALSE, FALSE);
7548 /* if bitfield then unpack the bits */
7549 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7550 genUnpackBits (result, rname, POINTER);
7553 /* we have can just get the values */
7554 int size = AOP_SIZE (result);
7559 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7562 emitcode ("mov", "a,@%s", rname);
7563 aopPut (AOP (result), "a", offset);
7567 sprintf (buffer, "@%s", rname);
7568 aopPut (AOP (result), buffer, offset);
7572 emitcode ("inc", "%s", rname);
7576 /* now some housekeeping stuff */
7579 /* we had to allocate for this iCode */
7580 freeAsmop (NULL, aop, ic, TRUE);
7584 /* we did not allocate which means left
7585 already in a pointer register, then
7586 if size > 0 && this could be used again
7587 we have to point it back to where it
7589 if (AOP_SIZE (result) > 1 &&
7590 !OP_SYMBOL (left)->remat &&
7591 (OP_SYMBOL (left)->liveTo > ic->seq ||
7594 int size = AOP_SIZE (result) - 1;
7596 emitcode ("dec", "%s", rname);
7601 freeAsmop (result, NULL, ic, TRUE);
7605 /*-----------------------------------------------------------------*/
7606 /* genPagedPointerGet - emitcode for paged pointer fetch */
7607 /*-----------------------------------------------------------------*/
7609 genPagedPointerGet (operand * left,
7616 sym_link *rtype, *retype, *letype;
7618 rtype = operandType (result);
7619 retype = getSpec (rtype);
7620 letype = getSpec (operandType (left));
7621 aopOp (left, ic, FALSE, FALSE);
7623 /* if the value is already in a pointer register
7624 then don't need anything more */
7625 if (!AOP_INPREG (AOP (left)))
7627 /* otherwise get a free pointer register */
7629 preg = getFreePtr (ic, &aop, FALSE);
7630 emitcode ("mov", "%s,%s",
7632 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7636 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7638 freeAsmop (left, NULL, ic, TRUE);
7639 aopOp (result, ic, FALSE, FALSE);
7641 /* if bitfield then unpack the bits */
7642 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7643 genUnpackBits (result, rname, PPOINTER);
7646 /* we have can just get the values */
7647 int size = AOP_SIZE (result);
7653 emitcode ("movx", "a,@%s", rname);
7654 aopPut (AOP (result), "a", offset);
7659 emitcode ("inc", "%s", rname);
7663 /* now some housekeeping stuff */
7666 /* we had to allocate for this iCode */
7667 freeAsmop (NULL, aop, ic, TRUE);
7671 /* we did not allocate which means left
7672 already in a pointer register, then
7673 if size > 0 && this could be used again
7674 we have to point it back to where it
7676 if (AOP_SIZE (result) > 1 &&
7677 !OP_SYMBOL (left)->remat &&
7678 (OP_SYMBOL (left)->liveTo > ic->seq ||
7681 int size = AOP_SIZE (result) - 1;
7683 emitcode ("dec", "%s", rname);
7688 freeAsmop (result, NULL, ic, TRUE);
7693 /*-----------------------------------------------------------------*/
7694 /* genFarPointerGet - gget value from far space */
7695 /*-----------------------------------------------------------------*/
7697 genFarPointerGet (operand * left,
7698 operand * result, iCode * ic)
7701 sym_link *retype = getSpec (operandType (result));
7702 sym_link *letype = getSpec (operandType (left));
7703 D (emitcode (";", "genFarPointerGet");
7706 aopOp (left, ic, FALSE, FALSE);
7708 /* if the operand is already in dptr
7709 then we do nothing else we move the value to dptr */
7710 if (AOP_TYPE (left) != AOP_STR)
7712 /* if this is remateriazable */
7713 if (AOP_TYPE (left) == AOP_IMMD)
7715 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7719 /* we need to get it byte by byte */
7720 _startLazyDPSEvaluation ();
7721 if (AOP_TYPE (left) != AOP_DPTR)
7723 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7724 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7725 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7729 /* We need to generate a load to DPTR indirect through DPTR. */
7730 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7732 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7733 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7734 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7735 emitcode ("pop", "dph");
7736 emitcode ("pop", "dpl");
7738 _endLazyDPSEvaluation ();
7741 /* so dptr know contains the address */
7742 freeAsmop (left, NULL, ic, TRUE);
7743 aopOp (result, ic, FALSE, TRUE);
7745 /* if bit then unpack */
7746 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7747 genUnpackBits (result, "dptr", FPOINTER);
7750 size = AOP_SIZE (result);
7753 _startLazyDPSEvaluation ();
7760 emitcode ("movx", "a,@dptr");
7762 emitcode ("inc", "dptr");
7764 aopPut (AOP (result), "a", offset++);
7766 _endLazyDPSEvaluation ();
7769 freeAsmop (result, NULL, ic, TRUE);
7772 /*-----------------------------------------------------------------*/
7773 /* emitcodePointerGet - gget value from code space */
7774 /*-----------------------------------------------------------------*/
7776 emitcodePointerGet (operand * left,
7777 operand * result, iCode * ic)
7780 sym_link *retype = getSpec (operandType (result));
7782 aopOp (left, ic, FALSE, FALSE);
7784 /* if the operand is already in dptr
7785 then we do nothing else we move the value to dptr */
7786 if (AOP_TYPE (left) != AOP_STR)
7788 /* if this is remateriazable */
7789 if (AOP_TYPE (left) == AOP_IMMD)
7791 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7794 { /* we need to get it byte by byte */
7795 _startLazyDPSEvaluation ();
7796 if (AOP_TYPE (left) != AOP_DPTR)
7798 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7799 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7800 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7804 /* We need to generate a load to DPTR indirect through DPTR. */
7805 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7807 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7808 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7809 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7810 emitcode ("pop", "dph");
7811 emitcode ("pop", "dpl");
7813 _endLazyDPSEvaluation ();
7816 /* so dptr know contains the address */
7817 freeAsmop (left, NULL, ic, TRUE);
7818 aopOp (result, ic, FALSE, TRUE);
7820 /* if bit then unpack */
7821 if (IS_BITVAR (retype))
7822 genUnpackBits (result, "dptr", CPOINTER);
7825 size = AOP_SIZE (result);
7828 _startLazyDPSEvaluation ();
7834 emitcode ("clr", "a");
7835 emitcode ("movc", "a,@a+dptr");
7837 emitcode ("inc", "dptr");
7838 aopPut (AOP (result), "a", offset++);
7840 _endLazyDPSEvaluation ();
7843 freeAsmop (result, NULL, ic, TRUE);
7846 /*-----------------------------------------------------------------*/
7847 /* genGenPointerGet - gget value from generic pointer space */
7848 /*-----------------------------------------------------------------*/
7850 genGenPointerGet (operand * left,
7851 operand * result, iCode * ic)
7854 sym_link *retype = getSpec (operandType (result));
7855 sym_link *letype = getSpec (operandType (left));
7857 D (emitcode (";", "genGenPointerGet "); );
7859 aopOp (left, ic, FALSE, TRUE);
7861 /* if the operand is already in dptr
7862 then we do nothing else we move the value to dptr */
7863 if (AOP_TYPE (left) != AOP_STR)
7865 /* if this is remateriazable */
7866 if (AOP_TYPE (left) == AOP_IMMD)
7868 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7869 emitcode ("mov", "b,#%d", pointerCode (retype));
7872 { /* we need to get it byte by byte */
7873 _startLazyDPSEvaluation ();
7874 if (AOP(left)->type==AOP_DPTR2) {
7876 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7879 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7880 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7883 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7884 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7887 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7888 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7890 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7891 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7892 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7893 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7895 _endLazyDPSEvaluation ();
7898 /* so dptr know contains the address */
7899 freeAsmop (left, NULL, ic, TRUE);
7900 aopOp (result, ic, FALSE, TRUE);
7902 /* if bit then unpack */
7903 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7904 genUnpackBits (result, "dptr", GPOINTER);
7907 size = AOP_SIZE (result);
7912 emitcode ("lcall", "__gptrget");
7913 aopPut (AOP (result), "a", offset++);
7915 emitcode ("inc", "dptr");
7919 freeAsmop (result, NULL, ic, TRUE);
7922 /*-----------------------------------------------------------------*/
7923 /* genPointerGet - generate code for pointer get */
7924 /*-----------------------------------------------------------------*/
7926 genPointerGet (iCode * ic)
7928 operand *left, *result;
7929 sym_link *type, *etype;
7932 D (emitcode (";", "genPointerGet ");
7935 left = IC_LEFT (ic);
7936 result = IC_RESULT (ic);
7938 /* depending on the type of pointer we need to
7939 move it to the correct pointer register */
7940 type = operandType (left);
7941 etype = getSpec (type);
7942 /* if left is of type of pointer then it is simple */
7943 if (IS_PTR (type) && !IS_FUNC (type->next))
7944 p_type = DCL_TYPE (type);
7947 /* we have to go by the storage class */
7948 p_type = PTR_TYPE (SPEC_OCLS (etype));
7951 /* now that we have the pointer type we assign
7952 the pointer values */
7958 genNearPointerGet (left, result, ic);
7962 genPagedPointerGet (left, result, ic);
7966 genFarPointerGet (left, result, ic);
7970 emitcodePointerGet (left, result, ic);
7974 genGenPointerGet (left, result, ic);
7980 /*-----------------------------------------------------------------*/
7981 /* genPackBits - generates code for packed bit storage */
7982 /*-----------------------------------------------------------------*/
7984 genPackBits (sym_link * etype,
7986 char *rname, int p_type)
7994 blen = SPEC_BLEN (etype);
7995 bstr = SPEC_BSTR (etype);
7997 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8000 /* if the bit lenth is less than or */
8001 /* it exactly fits a byte then */
8002 if (SPEC_BLEN (etype) <= 8)
8004 shCount = SPEC_BSTR (etype);
8006 /* shift left acc */
8009 if (SPEC_BLEN (etype) < 8)
8010 { /* if smaller than a byte */
8016 emitcode ("mov", "b,a");
8017 emitcode ("mov", "a,@%s", rname);
8021 emitcode ("mov", "b,a");
8022 emitcode ("movx", "a,@dptr");
8026 emitcode ("push", "b");
8027 emitcode ("push", "acc");
8028 emitcode ("lcall", "__gptrget");
8029 emitcode ("pop", "b");
8033 emitcode ("anl", "a,#0x%02x", (unsigned char)
8034 ((unsigned char) (0xFF << (blen + bstr)) |
8035 (unsigned char) (0xFF >> (8 - bstr))));
8036 emitcode ("orl", "a,b");
8037 if (p_type == GPOINTER)
8038 emitcode ("pop", "b");
8045 emitcode ("mov", "@%s,a", rname);
8049 emitcode ("movx", "@dptr,a");
8053 emitcode ("lcall", "__gptrput");
8058 if (SPEC_BLEN (etype) <= 8)
8061 emitcode ("inc", "%s", rname);
8062 rLen = SPEC_BLEN (etype);
8064 /* now generate for lengths greater than one byte */
8068 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8080 emitcode ("mov", "@%s,a", rname);
8083 emitcode ("mov", "@%s,%s", rname, l);
8088 emitcode ("movx", "@dptr,a");
8093 emitcode ("lcall", "__gptrput");
8096 emitcode ("inc", "%s", rname);
8101 /* last last was not complete */
8104 /* save the byte & read byte */
8108 emitcode ("mov", "b,a");
8109 emitcode ("mov", "a,@%s", rname);
8113 emitcode ("mov", "b,a");
8114 emitcode ("movx", "a,@dptr");
8118 emitcode ("push", "b");
8119 emitcode ("push", "acc");
8120 emitcode ("lcall", "__gptrget");
8121 emitcode ("pop", "b");
8125 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8126 emitcode ("orl", "a,b");
8129 if (p_type == GPOINTER)
8130 emitcode ("pop", "b");
8136 emitcode ("mov", "@%s,a", rname);
8140 emitcode ("movx", "@dptr,a");
8144 emitcode ("lcall", "__gptrput");
8148 /*-----------------------------------------------------------------*/
8149 /* genDataPointerSet - remat pointer to data space */
8150 /*-----------------------------------------------------------------*/
8152 genDataPointerSet (operand * right,
8156 int size, offset = 0;
8157 char *l, buffer[256];
8159 aopOp (right, ic, FALSE, FALSE);
8161 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8162 size = AOP_SIZE (right);
8166 sprintf (buffer, "(%s + %d)", l + 1, offset);
8168 sprintf (buffer, "%s", l + 1);
8169 emitcode ("mov", "%s,%s", buffer,
8170 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8173 freeAsmop (right, NULL, ic, TRUE);
8174 freeAsmop (result, NULL, ic, TRUE);
8177 /*-----------------------------------------------------------------*/
8178 /* genNearPointerSet - emitcode for near pointer put */
8179 /*-----------------------------------------------------------------*/
8181 genNearPointerSet (operand * right,
8188 sym_link *retype, *letype;
8189 sym_link *ptype = operandType (result);
8191 retype = getSpec (operandType (right));
8192 letype = getSpec (ptype);
8194 aopOp (result, ic, FALSE, FALSE);
8196 /* if the result is rematerializable &
8197 in data space & not a bit variable */
8198 if (AOP_TYPE (result) == AOP_IMMD &&
8199 DCL_TYPE (ptype) == POINTER &&
8200 !IS_BITVAR (retype) &&
8201 !IS_BITVAR (letype))
8203 genDataPointerSet (right, result, ic);
8207 /* if the value is already in a pointer register
8208 then don't need anything more */
8209 if (!AOP_INPREG (AOP (result)))
8211 /* otherwise get a free pointer register */
8213 preg = getFreePtr (ic, &aop, FALSE);
8214 emitcode ("mov", "%s,%s",
8216 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8220 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8222 freeAsmop (result, NULL, ic, TRUE);
8223 aopOp (right, ic, FALSE, FALSE);
8225 /* if bitfield then unpack the bits */
8226 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8227 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8230 /* we have can just get the values */
8231 int size = AOP_SIZE (right);
8236 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8240 emitcode ("mov", "@%s,a", rname);
8243 emitcode ("mov", "@%s,%s", rname, l);
8245 emitcode ("inc", "%s", rname);
8250 /* now some housekeeping stuff */
8253 /* we had to allocate for this iCode */
8254 freeAsmop (NULL, aop, ic, TRUE);
8258 /* we did not allocate which means left
8259 already in a pointer register, then
8260 if size > 0 && this could be used again
8261 we have to point it back to where it
8263 if (AOP_SIZE (right) > 1 &&
8264 !OP_SYMBOL (result)->remat &&
8265 (OP_SYMBOL (result)->liveTo > ic->seq ||
8268 int size = AOP_SIZE (right) - 1;
8270 emitcode ("dec", "%s", rname);
8275 freeAsmop (right, NULL, ic, TRUE);
8280 /*-----------------------------------------------------------------*/
8281 /* genPagedPointerSet - emitcode for Paged pointer put */
8282 /*-----------------------------------------------------------------*/
8284 genPagedPointerSet (operand * right,
8291 sym_link *retype, *letype;
8293 retype = getSpec (operandType (right));
8294 letype = getSpec (operandType (result));
8296 aopOp (result, ic, FALSE, FALSE);
8298 /* if the value is already in a pointer register
8299 then don't need anything more */
8300 if (!AOP_INPREG (AOP (result)))
8302 /* otherwise get a free pointer register */
8304 preg = getFreePtr (ic, &aop, FALSE);
8305 emitcode ("mov", "%s,%s",
8307 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8311 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8313 freeAsmop (result, NULL, ic, TRUE);
8314 aopOp (right, ic, FALSE, FALSE);
8316 /* if bitfield then unpack the bits */
8317 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8318 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8321 /* we have can just get the values */
8322 int size = AOP_SIZE (right);
8327 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8330 emitcode ("movx", "@%s,a", rname);
8333 emitcode ("inc", "%s", rname);
8339 /* now some housekeeping stuff */
8342 /* we had to allocate for this iCode */
8343 freeAsmop (NULL, aop, ic, TRUE);
8347 /* we did not allocate which means left
8348 already in a pointer register, then
8349 if size > 0 && this could be used again
8350 we have to point it back to where it
8352 if (AOP_SIZE (right) > 1 &&
8353 !OP_SYMBOL (result)->remat &&
8354 (OP_SYMBOL (result)->liveTo > ic->seq ||
8357 int size = AOP_SIZE (right) - 1;
8359 emitcode ("dec", "%s", rname);
8364 freeAsmop (right, NULL, ic, TRUE);
8369 /*-----------------------------------------------------------------*/
8370 /* genFarPointerSet - set value from far space */
8371 /*-----------------------------------------------------------------*/
8373 genFarPointerSet (operand * right,
8374 operand * result, iCode * ic)
8377 sym_link *retype = getSpec (operandType (right));
8378 sym_link *letype = getSpec (operandType (result));
8380 aopOp (result, ic, FALSE, FALSE);
8382 /* if the operand is already in dptr
8383 then we do nothing else we move the value to dptr */
8384 if (AOP_TYPE (result) != AOP_STR)
8386 /* if this is remateriazable */
8387 if (AOP_TYPE (result) == AOP_IMMD)
8388 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8391 /* we need to get it byte by byte */
8392 _startLazyDPSEvaluation ();
8393 if (AOP_TYPE (result) != AOP_DPTR)
8395 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8396 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8397 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8401 /* We need to generate a load to DPTR indirect through DPTR. */
8402 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8404 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8405 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8406 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8407 emitcode ("pop", "dph");
8408 emitcode ("pop", "dpl");
8410 _endLazyDPSEvaluation ();
8413 /* so dptr know contains the address */
8414 freeAsmop (result, NULL, ic, TRUE);
8415 aopOp (right, ic, FALSE, TRUE);
8417 /* if bit then unpack */
8418 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8419 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8422 size = AOP_SIZE (right);
8425 _startLazyDPSEvaluation ();
8428 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8434 emitcode ("movx", "@dptr,a");
8436 emitcode ("inc", "dptr");
8438 _endLazyDPSEvaluation ();
8441 freeAsmop (right, NULL, ic, TRUE);
8444 /*-----------------------------------------------------------------*/
8445 /* genGenPointerSet - set value from generic pointer space */
8446 /*-----------------------------------------------------------------*/
8448 genGenPointerSet (operand * right,
8449 operand * result, iCode * ic)
8452 sym_link *retype = getSpec (operandType (right));
8453 sym_link *letype = getSpec (operandType (result));
8455 aopOp (result, ic, FALSE, TRUE);
8457 /* if the operand is already in dptr
8458 then we do nothing else we move the value to dptr */
8459 if (AOP_TYPE (result) != AOP_STR)
8461 _startLazyDPSEvaluation ();
8462 /* if this is remateriazable */
8463 if (AOP_TYPE (result) == AOP_IMMD)
8465 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8466 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8469 { /* we need to get it byte by byte */
8470 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8471 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8472 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8473 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8475 _endLazyDPSEvaluation ();
8477 /* so dptr know contains the address */
8478 freeAsmop (result, NULL, ic, TRUE);
8479 aopOp (right, ic, FALSE, TRUE);
8481 /* if bit then unpack */
8482 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8483 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8486 size = AOP_SIZE (right);
8489 _startLazyDPSEvaluation ();
8492 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8498 emitcode ("lcall", "__gptrput");
8500 emitcode ("inc", "dptr");
8502 _endLazyDPSEvaluation ();
8505 freeAsmop (right, NULL, ic, TRUE);
8508 /*-----------------------------------------------------------------*/
8509 /* genPointerSet - stores the value into a pointer location */
8510 /*-----------------------------------------------------------------*/
8512 genPointerSet (iCode * ic)
8514 operand *right, *result;
8515 sym_link *type, *etype;
8518 D (emitcode (";", "genPointerSet ");
8521 right = IC_RIGHT (ic);
8522 result = IC_RESULT (ic);
8524 /* depending on the type of pointer we need to
8525 move it to the correct pointer register */
8526 type = operandType (result);
8527 etype = getSpec (type);
8528 /* if left is of type of pointer then it is simple */
8529 if (IS_PTR (type) && !IS_FUNC (type->next))
8531 p_type = DCL_TYPE (type);
8535 /* we have to go by the storage class */
8536 p_type = PTR_TYPE (SPEC_OCLS (etype));
8539 /* now that we have the pointer type we assign
8540 the pointer values */
8546 genNearPointerSet (right, result, ic);
8550 genPagedPointerSet (right, result, ic);
8554 genFarPointerSet (right, result, ic);
8558 genGenPointerSet (right, result, ic);
8564 /*-----------------------------------------------------------------*/
8565 /* genIfx - generate code for Ifx statement */
8566 /*-----------------------------------------------------------------*/
8568 genIfx (iCode * ic, iCode * popIc)
8570 operand *cond = IC_COND (ic);
8573 D (emitcode (";", "genIfx ");
8576 aopOp (cond, ic, FALSE, FALSE);
8578 /* get the value into acc */
8579 if (AOP_TYPE (cond) != AOP_CRY)
8583 /* the result is now in the accumulator */
8584 freeAsmop (cond, NULL, ic, TRUE);
8586 /* if there was something to be popped then do it */
8590 /* if the condition is a bit variable */
8591 if (isbit && IS_ITEMP (cond) &&
8593 genIfxJump (ic, SPIL_LOC (cond)->rname);
8594 else if (isbit && !IS_ITEMP (cond))
8595 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8597 genIfxJump (ic, "a");
8602 /*-----------------------------------------------------------------*/
8603 /* genAddrOf - generates code for address of */
8604 /*-----------------------------------------------------------------*/
8606 genAddrOf (iCode * ic)
8608 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8611 D (emitcode (";", "genAddrOf ");
8614 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8616 /* if the operand is on the stack then we
8617 need to get the stack offset of this
8621 /* if it has an offset then we need to compute
8625 emitcode ("mov", "a,_bp");
8626 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8627 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8631 /* we can just move _bp */
8632 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8634 /* fill the result with zero */
8635 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8638 if (options.stack10bit && size < (FPTRSIZE - 1))
8641 "*** warning: pointer to stack var truncated.\n");
8648 if (options.stack10bit && offset == 2)
8650 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8654 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8661 /* object not on stack then we need the name */
8662 size = AOP_SIZE (IC_RESULT (ic));
8667 char s[SDCC_NAME_MAX];
8669 sprintf (s, "#(%s >> %d)",
8673 sprintf (s, "#%s", sym->rname);
8674 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8678 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8682 /*-----------------------------------------------------------------*/
8683 /* genFarFarAssign - assignment when both are in far space */
8684 /*-----------------------------------------------------------------*/
8686 genFarFarAssign (operand * result, operand * right, iCode * ic)
8688 int size = AOP_SIZE (right);
8694 /* This is a net loss for size == 1, but a big gain
8697 D (emitcode (";", "genFarFarAssign (improved)");
8700 aopOp (result, ic, TRUE, TRUE);
8702 _startLazyDPSEvaluation ();
8705 aopPut (AOP (result),
8706 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8709 _endLazyDPSEvaluation ();
8710 freeAsmop (result, NULL, ic, FALSE);
8711 freeAsmop (right, NULL, ic, FALSE);
8715 D (emitcode (";", "genFarFarAssign ");
8718 /* first push the right side on to the stack */
8719 _startLazyDPSEvaluation ();
8722 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8724 emitcode ("push", "acc");
8727 freeAsmop (right, NULL, ic, FALSE);
8728 /* now assign DPTR to result */
8729 aopOp (result, ic, FALSE, FALSE);
8730 size = AOP_SIZE (result);
8733 emitcode ("pop", "acc");
8734 aopPut (AOP (result), "a", --offset);
8736 freeAsmop (result, NULL, ic, FALSE);
8737 _endLazyDPSEvaluation ();
8741 /*-----------------------------------------------------------------*/
8742 /* genAssign - generate code for assignment */
8743 /*-----------------------------------------------------------------*/
8745 genAssign (iCode * ic)
8747 operand *result, *right;
8749 unsigned long lit = 0L;
8751 D (emitcode (";", "genAssign ");
8754 result = IC_RESULT (ic);
8755 right = IC_RIGHT (ic);
8757 /* if they are the same */
8758 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8761 aopOp (right, ic, FALSE, FALSE);
8763 emitcode (";", "genAssign: resultIsFar = %s",
8764 isOperandInFarSpace (result) ?
8767 /* special case both in far space */
8768 if ((AOP_TYPE (right) == AOP_DPTR ||
8769 AOP_TYPE (right) == AOP_DPTR2) &&
8770 /* IS_TRUE_SYMOP(result) && */
8771 isOperandInFarSpace (result))
8773 genFarFarAssign (result, right, ic);
8777 aopOp (result, ic, TRUE, FALSE);
8779 /* if they are the same registers */
8780 if (sameRegs (AOP (right), AOP (result)))
8783 /* if the result is a bit */
8784 if (AOP_TYPE (result) == AOP_CRY)
8787 /* if the right size is a literal then
8788 we know what the value is */
8789 if (AOP_TYPE (right) == AOP_LIT)
8791 if (((int) operandLitValue (right)))
8792 aopPut (AOP (result), one, 0);
8794 aopPut (AOP (result), zero, 0);
8798 /* the right is also a bit variable */
8799 if (AOP_TYPE (right) == AOP_CRY)
8801 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8802 aopPut (AOP (result), "c", 0);
8808 aopPut (AOP (result), "a", 0);
8812 /* bit variables done */
8814 size = AOP_SIZE (result);
8816 if (AOP_TYPE (right) == AOP_LIT)
8817 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8820 (AOP_TYPE (result) != AOP_REG) &&
8821 (AOP_TYPE (right) == AOP_LIT) &&
8822 !IS_FLOAT (operandType (right)))
8824 D (emitcode (";", "Kevin's better literal load code");
8826 _startLazyDPSEvaluation ();
8827 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8829 aopPut (AOP (result),
8830 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8835 /* And now fill the rest with zeros. */
8838 emitcode ("clr", "a");
8842 aopPut (AOP (result), "a", offset++);
8844 _endLazyDPSEvaluation ();
8848 _startLazyDPSEvaluation ();
8851 aopPut (AOP (result),
8852 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8856 _endLazyDPSEvaluation ();
8860 freeAsmop (right, NULL, ic, FALSE);
8861 freeAsmop (result, NULL, ic, TRUE);
8864 /*-----------------------------------------------------------------*/
8865 /* genJumpTab - generates code for jump table */
8866 /*-----------------------------------------------------------------*/
8868 genJumpTab (iCode * ic)
8873 D (emitcode (";", "genJumpTab ");
8876 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8877 /* get the condition into accumulator */
8878 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8880 /* multiply by four! */
8881 emitcode ("add", "a,acc");
8882 emitcode ("add", "a,acc");
8883 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8885 jtab = newiTempLabel (NULL);
8886 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8887 emitcode ("jmp", "@a+dptr");
8888 emitcode ("", "%05d$:", jtab->key + 100);
8889 /* now generate the jump labels */
8890 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8891 jtab = setNextItem (IC_JTLABELS (ic)))
8892 emitcode ("ljmp", "%05d$", jtab->key + 100);
8896 /*-----------------------------------------------------------------*/
8897 /* genCast - gen code for casting */
8898 /*-----------------------------------------------------------------*/
8900 genCast (iCode * ic)
8902 operand *result = IC_RESULT (ic);
8903 sym_link *ctype = operandType (IC_LEFT (ic));
8904 sym_link *rtype = operandType (IC_RIGHT (ic));
8905 operand *right = IC_RIGHT (ic);
8908 D (emitcode (";", "genCast ");
8911 /* if they are equivalent then do nothing */
8912 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8915 aopOp (right, ic, FALSE, FALSE);
8916 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8918 /* if the result is a bit */
8919 if (AOP_TYPE (result) == AOP_CRY)
8921 /* if the right size is a literal then
8922 we know what the value is */
8923 if (AOP_TYPE (right) == AOP_LIT)
8925 if (((int) operandLitValue (right)))
8926 aopPut (AOP (result), one, 0);
8928 aopPut (AOP (result), zero, 0);
8933 /* the right is also a bit variable */
8934 if (AOP_TYPE (right) == AOP_CRY)
8936 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8937 aopPut (AOP (result), "c", 0);
8943 aopPut (AOP (result), "a", 0);
8947 /* if they are the same size : or less */
8948 if (AOP_SIZE (result) <= AOP_SIZE (right))
8951 /* if they are in the same place */
8952 if (sameRegs (AOP (right), AOP (result)))
8955 /* if they in different places then copy */
8956 size = AOP_SIZE (result);
8958 _startLazyDPSEvaluation ();
8961 aopPut (AOP (result),
8962 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8966 _endLazyDPSEvaluation ();
8971 /* if the result is of type pointer */
8976 sym_link *type = operandType (right);
8978 /* pointer to generic pointer */
8979 if (IS_GENPTR (ctype))
8985 p_type = DCL_TYPE (type);
8989 #if OLD_CAST_BEHAVIOR
8990 /* KV: we are converting a non-pointer type to
8991 * a generic pointer. This (ifdef'd out) code
8992 * says that the resulting generic pointer
8993 * should have the same class as the storage
8994 * location of the non-pointer variable.
8996 * For example, converting an int (which happens
8997 * to be stored in DATA space) to a pointer results
8998 * in a DATA generic pointer; if the original int
8999 * in XDATA space, so will be the resulting pointer.
9001 * I don't like that behavior, and thus this change:
9002 * all such conversions will be forced to XDATA and
9003 * throw a warning. If you want some non-XDATA
9004 * type, or you want to suppress the warning, you
9005 * must go through an intermediate cast, like so:
9007 * char _generic *gp = (char _xdata *)(intVar);
9009 sym_link *etype = getSpec (type);
9011 /* we have to go by the storage class */
9012 if (SPEC_OCLS (etype) != generic)
9014 p_type = PTR_TYPE (SPEC_OCLS (etype));
9019 /* Converting unknown class (i.e. register variable)
9020 * to generic pointer. This is not good, but
9021 * we'll make a guess (and throw a warning).
9024 werror (W_INT_TO_GEN_PTR_CAST);
9028 /* the first two bytes are known */
9029 size = GPTRSIZE - 1;
9031 _startLazyDPSEvaluation ();
9034 aopPut (AOP (result),
9035 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9039 _endLazyDPSEvaluation ();
9041 /* the last byte depending on type */
9059 /* this should never happen */
9060 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9061 "got unknown pointer type");
9064 aopPut (AOP (result), l, GPTRSIZE - 1);
9068 /* just copy the pointers */
9069 size = AOP_SIZE (result);
9071 _startLazyDPSEvaluation ();
9074 aopPut (AOP (result),
9075 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9079 _endLazyDPSEvaluation ();
9083 /* so we now know that the size of destination is greater
9084 than the size of the source */
9085 /* we move to result for the size of source */
9086 size = AOP_SIZE (right);
9088 _startLazyDPSEvaluation ();
9091 aopPut (AOP (result),
9092 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9096 _endLazyDPSEvaluation ();
9098 /* now depending on the sign of the source && destination */
9099 size = AOP_SIZE (result) - AOP_SIZE (right);
9100 /* if unsigned or not an integral type */
9101 /* also, if the source is a bit, we don't need to sign extend, because
9102 * it can't possibly have set the sign bit.
9104 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9108 aopPut (AOP (result), zero, offset++);
9113 /* we need to extend the sign :{ */
9114 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9115 FALSE, FALSE, TRUE);
9117 emitcode ("rlc", "a");
9118 emitcode ("subb", "a,acc");
9120 aopPut (AOP (result), "a", offset++);
9123 /* we are done hurray !!!! */
9126 freeAsmop (right, NULL, ic, TRUE);
9127 freeAsmop (result, NULL, ic, TRUE);
9131 /*-----------------------------------------------------------------*/
9132 /* genDjnz - generate decrement & jump if not zero instrucion */
9133 /*-----------------------------------------------------------------*/
9135 genDjnz (iCode * ic, iCode * ifx)
9141 /* if the if condition has a false label
9142 then we cannot save */
9146 /* if the minus is not of the form
9148 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9149 !IS_OP_LITERAL (IC_RIGHT (ic)))
9152 if (operandLitValue (IC_RIGHT (ic)) != 1)
9155 /* if the size of this greater than one then no
9157 if (getSize (operandType (IC_RESULT (ic))) > 1)
9160 /* otherwise we can save BIG */
9161 lbl = newiTempLabel (NULL);
9162 lbl1 = newiTempLabel (NULL);
9164 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9166 if (IS_AOP_PREG (IC_RESULT (ic)))
9168 emitcode ("dec", "%s",
9169 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9170 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9171 emitcode ("jnz", "%05d$", lbl->key + 100);
9175 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9178 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9179 emitcode ("", "%05d$:", lbl->key + 100);
9180 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9181 emitcode ("", "%05d$:", lbl1->key + 100);
9183 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9188 /*-----------------------------------------------------------------*/
9189 /* genReceive - generate code for a receive iCode */
9190 /*-----------------------------------------------------------------*/
9192 genReceive (iCode * ic)
9195 D (emitcode (";", "genReceive ");
9198 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9199 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9200 IS_TRUE_SYMOP (IC_RESULT (ic))))
9202 int size = getSize (operandType (IC_RESULT (ic)));
9203 int offset = fReturnSizeDS390 - size;
9206 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9207 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9210 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9211 size = AOP_SIZE (IC_RESULT (ic));
9215 emitcode ("pop", "acc");
9216 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9223 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9225 assignResultValue (IC_RESULT (ic));
9228 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9231 /*-----------------------------------------------------------------*/
9232 /* gen390Code - generate code for Dallas 390 based controllers */
9233 /*-----------------------------------------------------------------*/
9235 gen390Code (iCode * lic)
9240 lineHead = lineCurr = NULL;
9244 /* print the allocation information */
9246 printAllocInfo (currFunc, codeOutFile);
9248 /* if debug information required */
9249 if (options.debug && currFunc)
9251 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9253 if (IS_STATIC (currFunc->etype))
9254 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9256 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9259 /* stack pointer name */
9260 if (options.useXstack)
9266 for (ic = lic; ic; ic = ic->next)
9269 if (cln != ic->lineno)
9274 emitcode ("", "C$%s$%d$%d$%d ==.",
9275 FileBaseName (ic->filename), ic->lineno,
9276 ic->level, ic->block);
9279 emitcode (";", "%s %d", ic->filename, ic->lineno);
9282 /* if the result is marked as
9283 spilt and rematerializable or code for
9284 this has already been generated then
9286 if (resultRemat (ic) || ic->generated)
9289 /* depending on the operation */
9309 /* IPOP happens only when trying to restore a
9310 spilt live range, if there is an ifx statement
9311 following this pop then the if statement might
9312 be using some of the registers being popped which
9313 would destory the contents of the register so
9314 we need to check for this condition and handle it */
9316 ic->next->op == IFX &&
9317 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9318 genIfx (ic->next, ic);
9336 genEndFunction (ic);
9356 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9373 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9377 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9384 /* note these two are xlated by algebraic equivalence
9385 during parsing SDCC.y */
9386 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9387 "got '>=' or '<=' shouldn't have come here");
9391 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9403 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9407 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9411 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9438 case GET_VALUE_AT_ADDRESS:
9443 if (POINTER_SET (ic))
9470 addSet (&_G.sendSet, ic);
9475 /* piCode(ic,stdout); */
9481 /* now we are ready to call the
9482 peep hole optimizer */
9483 if (!options.nopeep)
9484 peepHole (&lineHead);
9486 /* now do the actual printing */
9487 printLine (lineHead, codeOutFile);