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 */
1273 /*-----------------------------------------------------------------*/
1275 reAdjustPreg (asmop * aop)
1280 if ((size = aop->size) <= 1)
1288 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1292 if (aop->type == AOP_DPTR2)
1299 emitcode ("lcall", "__decdptr");
1302 if (aop->type == AOP_DPTR2)
1312 #define AOP(op) op->aop
1313 #define AOP_TYPE(op) AOP(op)->type
1314 #define AOP_SIZE(op) AOP(op)->size
1315 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1316 AOP_TYPE(x) == AOP_R0))
1318 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1319 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1322 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1323 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1324 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1326 /* Workaround for DS80C390 bug: div ab may return bogus results
1327 * if A is accessed in instruction immediately before the div.
1329 * Will be fixed in B4 rev of processor, Dallas claims.
1332 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1333 if (!AOP_NEEDSACC(RIGHT)) \
1335 /* We can load A first, then B, since \
1336 * B (the RIGHT operand) won't clobber A, \
1337 * thus avoiding touching A right before the div. \
1339 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1340 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1342 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1346 /* Just stuff in a nop after loading A. */ \
1347 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1348 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1350 emitcode("nop", "; workaround for DS80C390 div bug."); \
1353 /*-----------------------------------------------------------------*/
1354 /* genNotFloat - generates not for float operations */
1355 /*-----------------------------------------------------------------*/
1357 genNotFloat (operand * op, operand * res)
1363 D (emitcode (";", "genNotFloat ");
1366 /* we will put 127 in the first byte of
1368 aopPut (AOP (res), "#127", 0);
1369 size = AOP_SIZE (op) - 1;
1372 _startLazyDPSEvaluation ();
1373 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1378 emitcode ("orl", "a,%s",
1380 offset++, FALSE, FALSE, FALSE));
1382 _endLazyDPSEvaluation ();
1383 tlbl = newiTempLabel (NULL);
1385 tlbl = newiTempLabel (NULL);
1386 aopPut (res->aop, one, 1);
1387 emitcode ("jz", "%05d$", (tlbl->key + 100));
1388 aopPut (res->aop, zero, 1);
1389 emitcode ("", "%05d$:", (tlbl->key + 100));
1391 size = res->aop->size - 2;
1393 /* put zeros in the rest */
1395 aopPut (res->aop, zero, offset++);
1398 /*-----------------------------------------------------------------*/
1399 /* opIsGptr: returns non-zero if the passed operand is */
1400 /* a generic pointer type. */
1401 /*-----------------------------------------------------------------*/
1403 opIsGptr (operand * op)
1405 sym_link *type = operandType (op);
1407 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1414 /*-----------------------------------------------------------------*/
1415 /* getDataSize - get the operand data size */
1416 /*-----------------------------------------------------------------*/
1418 getDataSize (operand * op)
1421 size = AOP_SIZE (op);
1422 if (size == GPTRSIZE)
1424 sym_link *type = operandType (op);
1425 if (IS_GENPTR (type))
1427 /* generic pointer; arithmetic operations
1428 * should ignore the high byte (pointer type).
1436 /*-----------------------------------------------------------------*/
1437 /* outAcc - output Acc */
1438 /*-----------------------------------------------------------------*/
1440 outAcc (operand * result)
1443 size = getDataSize (result);
1446 aopPut (AOP (result), "a", 0);
1449 /* unsigned or positive */
1452 aopPut (AOP (result), zero, offset++);
1457 /*-----------------------------------------------------------------*/
1458 /* outBitC - output a bit C */
1459 /*-----------------------------------------------------------------*/
1461 outBitC (operand * result)
1463 /* if the result is bit */
1464 if (AOP_TYPE (result) == AOP_CRY)
1466 aopPut (AOP (result), "c", 0);
1470 emitcode ("clr", "a");
1471 emitcode ("rlc", "a");
1476 /*-----------------------------------------------------------------*/
1477 /* toBoolean - emit code for orl a,operator(sizeop) */
1478 /*-----------------------------------------------------------------*/
1480 toBoolean (operand * oper)
1482 int size = AOP_SIZE (oper) - 1;
1485 /* The generic part of a generic pointer should
1486 * not participate in it's truth value.
1488 * i.e. 0x10000000 is zero.
1490 if (opIsGptr (oper))
1492 D (emitcode (";", "toBoolean: generic ptr special case.");
1497 _startLazyDPSEvaluation ();
1498 if (AOP_NEEDSACC (oper))
1500 emitcode ("push", "b");
1501 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1505 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1509 if (AOP_NEEDSACC (oper))
1511 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1515 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1518 _endLazyDPSEvaluation ();
1520 if (AOP_NEEDSACC (oper))
1522 emitcode ("mov", "a,b");
1523 emitcode ("pop", "b");
1528 /*-----------------------------------------------------------------*/
1529 /* genNot - generate code for ! operation */
1530 /*-----------------------------------------------------------------*/
1535 sym_link *optype = operandType (IC_LEFT (ic));
1537 D (emitcode (";", "genNot ");
1540 /* assign asmOps to operand & result */
1541 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1542 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1544 /* if in bit space then a special case */
1545 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1547 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1548 emitcode ("cpl", "c");
1549 outBitC (IC_RESULT (ic));
1553 /* if type float then do float */
1554 if (IS_FLOAT (optype))
1556 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1560 toBoolean (IC_LEFT (ic));
1562 tlbl = newiTempLabel (NULL);
1563 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1564 emitcode ("", "%05d$:", tlbl->key + 100);
1565 outBitC (IC_RESULT (ic));
1568 /* release the aops */
1569 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1570 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1574 /*-----------------------------------------------------------------*/
1575 /* genCpl - generate code for complement */
1576 /*-----------------------------------------------------------------*/
1583 D (emitcode (";", "genCpl ");
1587 /* assign asmOps to operand & result */
1588 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1589 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1591 /* if both are in bit space then
1593 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1594 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1597 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1598 emitcode ("cpl", "c");
1599 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1603 size = AOP_SIZE (IC_RESULT (ic));
1604 _startLazyDPSEvaluation ();
1607 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1609 emitcode ("cpl", "a");
1610 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1612 _endLazyDPSEvaluation ();
1616 /* release the aops */
1617 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1618 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1621 /*-----------------------------------------------------------------*/
1622 /* genUminusFloat - unary minus for floating points */
1623 /*-----------------------------------------------------------------*/
1625 genUminusFloat (operand * op, operand * result)
1627 int size, offset = 0;
1629 /* for this we just need to flip the
1630 first it then copy the rest in place */
1631 D (emitcode (";", "genUminusFloat");
1634 _startLazyDPSEvaluation ();
1635 size = AOP_SIZE (op) - 1;
1636 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1639 emitcode ("cpl", "acc.7");
1640 aopPut (AOP (result), "a", 3);
1644 aopPut (AOP (result),
1645 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1649 _endLazyDPSEvaluation ();
1652 /*-----------------------------------------------------------------*/
1653 /* genUminus - unary minus code generation */
1654 /*-----------------------------------------------------------------*/
1656 genUminus (iCode * ic)
1659 sym_link *optype, *rtype;
1661 D (emitcode (";", "genUminus ");
1666 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1667 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1669 /* if both in bit space then special
1671 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1672 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1675 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1676 emitcode ("cpl", "c");
1677 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1681 optype = operandType (IC_LEFT (ic));
1682 rtype = operandType (IC_RESULT (ic));
1684 /* if float then do float stuff */
1685 if (IS_FLOAT (optype))
1687 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1691 /* otherwise subtract from zero */
1692 size = AOP_SIZE (IC_LEFT (ic));
1694 _startLazyDPSEvaluation ();
1697 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1698 if (!strcmp (l, "a"))
1702 emitcode ("cpl", "a");
1703 emitcode ("addc", "a,#0");
1709 emitcode ("clr", "a");
1710 emitcode ("subb", "a,%s", l);
1712 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1714 _endLazyDPSEvaluation ();
1716 /* if any remaining bytes in the result */
1717 /* we just need to propagate the sign */
1718 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1720 emitcode ("rlc", "a");
1721 emitcode ("subb", "a,acc");
1723 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1727 /* release the aops */
1728 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1729 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1732 /*-----------------------------------------------------------------*/
1733 /* saveRegisters - will look for a call and save the registers */
1734 /*-----------------------------------------------------------------*/
1736 saveRegisters (iCode * lic)
1744 for (ic = lic; ic; ic = ic->next)
1745 if (ic->op == CALL || ic->op == PCALL)
1750 fprintf (stderr, "found parameter push with no function call\n");
1754 /* if the registers have been saved already then
1756 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1759 /* find the registers in use at this time
1760 and push them away to safety */
1761 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1765 if (options.useXstack)
1767 if (bitVectBitValue (rsave, R0_IDX))
1768 emitcode ("mov", "b,r0");
1769 emitcode ("mov", "r0,%s", spname);
1770 for (i = 0; i < ds390_nRegs; i++)
1772 if (bitVectBitValue (rsave, i))
1775 emitcode ("mov", "a,b");
1777 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1778 emitcode ("movx", "@r0,a");
1779 emitcode ("inc", "r0");
1782 emitcode ("mov", "%s,r0", spname);
1783 if (bitVectBitValue (rsave, R0_IDX))
1784 emitcode ("mov", "r0,b");
1787 for (i = 0; i < ds390_nRegs; i++)
1789 if (bitVectBitValue (rsave, i))
1790 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1793 detype = getSpec (operandType (IC_LEFT (ic)));
1795 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1796 IS_ISR (currFunc->etype) &&
1799 saverbank (SPEC_BANK (detype), ic, TRUE);
1802 /*-----------------------------------------------------------------*/
1803 /* unsaveRegisters - pop the pushed registers */
1804 /*-----------------------------------------------------------------*/
1806 unsaveRegisters (iCode * ic)
1810 /* find the registers in use at this time
1811 and push them away to safety */
1812 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1815 if (options.useXstack)
1817 emitcode ("mov", "r0,%s", spname);
1818 for (i = ds390_nRegs; i >= 0; i--)
1820 if (bitVectBitValue (rsave, i))
1822 emitcode ("dec", "r0");
1823 emitcode ("movx", "a,@r0");
1825 emitcode ("mov", "b,a");
1827 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1831 emitcode ("mov", "%s,r0", spname);
1832 if (bitVectBitValue (rsave, R0_IDX))
1833 emitcode ("mov", "r0,b");
1836 for (i = ds390_nRegs; i >= 0; i--)
1838 if (bitVectBitValue (rsave, i))
1839 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1845 /*-----------------------------------------------------------------*/
1847 /*-----------------------------------------------------------------*/
1849 pushSide (operand * oper, int size)
1852 _startLazyDPSEvaluation ();
1855 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1856 if (AOP_TYPE (oper) != AOP_REG &&
1857 AOP_TYPE (oper) != AOP_DIR &&
1860 emitcode ("mov", "a,%s", l);
1861 emitcode ("push", "acc");
1864 emitcode ("push", "%s", l);
1866 _endLazyDPSEvaluation ();
1869 /*-----------------------------------------------------------------*/
1870 /* assignResultValue - */
1871 /*-----------------------------------------------------------------*/
1873 assignResultValue (operand * oper)
1876 int size = AOP_SIZE (oper);
1878 _startLazyDPSEvaluation ();
1881 aopPut (AOP (oper), fReturn[offset], offset);
1884 _endLazyDPSEvaluation ();
1888 /*-----------------------------------------------------------------*/
1889 /* genXpush - pushes onto the external stack */
1890 /*-----------------------------------------------------------------*/
1892 genXpush (iCode * ic)
1894 asmop *aop = newAsmop (0);
1896 int size, offset = 0;
1898 D (emitcode (";", "genXpush ");
1901 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1902 r = getFreePtr (ic, &aop, FALSE);
1905 emitcode ("mov", "%s,_spx", r->name);
1907 size = AOP_SIZE (IC_LEFT (ic));
1908 _startLazyDPSEvaluation ();
1912 char *l = aopGet (AOP (IC_LEFT (ic)),
1913 offset++, FALSE, FALSE, TRUE);
1915 emitcode ("movx", "@%s,a", r->name);
1916 emitcode ("inc", "%s", r->name);
1919 _endLazyDPSEvaluation ();
1922 emitcode ("mov", "_spx,%s", r->name);
1924 freeAsmop (NULL, aop, ic, TRUE);
1925 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1928 /*-----------------------------------------------------------------*/
1929 /* genIpush - genrate code for pushing this gets a little complex */
1930 /*-----------------------------------------------------------------*/
1932 genIpush (iCode * ic)
1934 int size, offset = 0;
1937 D (emitcode (";", "genIpush ");
1940 /* if this is not a parm push : ie. it is spill push
1941 and spill push is always done on the local stack */
1945 /* and the item is spilt then do nothing */
1946 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1949 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1950 size = AOP_SIZE (IC_LEFT (ic));
1951 /* push it on the stack */
1952 _startLazyDPSEvaluation ();
1955 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1961 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1963 _endLazyDPSEvaluation ();
1967 /* this is a paramter push: in this case we call
1968 the routine to find the call and save those
1969 registers that need to be saved */
1972 /* if use external stack then call the external
1973 stack pushing routine */
1974 if (options.useXstack)
1980 /* then do the push */
1981 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1983 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1984 size = AOP_SIZE (IC_LEFT (ic));
1986 _startLazyDPSEvaluation ();
1989 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1990 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1991 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1994 emitcode ("mov", "a,%s", l);
1995 emitcode ("push", "acc");
1998 emitcode ("push", "%s ;jwk genIpush", l);
2000 _endLazyDPSEvaluation ();
2002 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2005 /*-----------------------------------------------------------------*/
2006 /* genIpop - recover the registers: can happen only for spilling */
2007 /*-----------------------------------------------------------------*/
2009 genIpop (iCode * ic)
2013 D (emitcode (";", "genIpop ");
2017 /* if the temp was not pushed then */
2018 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2021 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2022 size = AOP_SIZE (IC_LEFT (ic));
2023 offset = (size - 1);
2024 _startLazyDPSEvaluation ();
2027 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2028 FALSE, TRUE, TRUE));
2030 _endLazyDPSEvaluation ();
2032 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2035 /*-----------------------------------------------------------------*/
2036 /* unsaverbank - restores the resgister bank from stack */
2037 /*-----------------------------------------------------------------*/
2039 unsaverbank (int bank, iCode * ic, bool popPsw)
2047 if (options.useXstack)
2050 r = getFreePtr (ic, &aop, FALSE);
2053 emitcode ("mov", "%s,_spx", r->name);
2054 emitcode ("movx", "a,@%s", r->name);
2055 emitcode ("mov", "psw,a");
2056 emitcode ("dec", "%s", r->name);
2060 emitcode ("pop", "psw");
2063 for (i = (ds390_nRegs - 1); i >= 0; i--)
2065 if (options.useXstack)
2067 emitcode ("movx", "a,@%s", r->name);
2068 emitcode ("mov", "(%s+%d),a",
2069 regs390[i].base, 8 * bank + regs390[i].offset);
2070 emitcode ("dec", "%s", r->name);
2074 emitcode ("pop", "(%s+%d)",
2075 regs390[i].base, 8 * bank + regs390[i].offset);
2078 if (options.useXstack)
2081 emitcode ("mov", "_spx,%s", r->name);
2082 freeAsmop (NULL, aop, ic, TRUE);
2087 /*-----------------------------------------------------------------*/
2088 /* saverbank - saves an entire register bank on the stack */
2089 /*-----------------------------------------------------------------*/
2091 saverbank (int bank, iCode * ic, bool pushPsw)
2097 if (options.useXstack)
2101 r = getFreePtr (ic, &aop, FALSE);
2102 emitcode ("mov", "%s,_spx", r->name);
2106 for (i = 0; i < ds390_nRegs; i++)
2108 if (options.useXstack)
2110 emitcode ("inc", "%s", r->name);
2111 emitcode ("mov", "a,(%s+%d)",
2112 regs390[i].base, 8 * bank + regs390[i].offset);
2113 emitcode ("movx", "@%s,a", r->name);
2116 emitcode ("push", "(%s+%d)",
2117 regs390[i].base, 8 * bank + regs390[i].offset);
2122 if (options.useXstack)
2124 emitcode ("mov", "a,psw");
2125 emitcode ("movx", "@%s,a", r->name);
2126 emitcode ("inc", "%s", r->name);
2127 emitcode ("mov", "_spx,%s", r->name);
2128 freeAsmop (NULL, aop, ic, TRUE);
2132 emitcode ("push", "psw");
2134 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2140 /*-----------------------------------------------------------------*/
2141 /* genCall - generates a call statement */
2142 /*-----------------------------------------------------------------*/
2144 genCall (iCode * ic)
2148 D (emitcode (";", "genCall ");
2151 /* if caller saves & we have not saved then */
2155 /* if we are calling a function that is not using
2156 the same register bank then we need to save the
2157 destination registers on the stack */
2158 detype = getSpec (operandType (IC_LEFT (ic)));
2160 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2161 IS_ISR (currFunc->etype) &&
2164 saverbank (SPEC_BANK (detype), ic, TRUE);
2166 /* if send set is not empty the assign */
2171 for (sic = setFirstItem (_G.sendSet); sic;
2172 sic = setNextItem (_G.sendSet))
2174 int size, offset = 0;
2176 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2177 size = AOP_SIZE (IC_LEFT (sic));
2179 _startLazyDPSEvaluation ();
2182 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2183 FALSE, FALSE, TRUE);
2184 if (strcmp (l, fReturn[offset])) {
2187 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2193 _endLazyDPSEvaluation ();
2194 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2199 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2200 OP_SYMBOL (IC_LEFT (ic))->rname :
2201 OP_SYMBOL (IC_LEFT (ic))->name));
2203 /* if we need assign a result value */
2204 if ((IS_ITEMP (IC_RESULT (ic)) &&
2205 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2206 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2207 IS_TRUE_SYMOP (IC_RESULT (ic)))
2209 if (isOperandInFarSpace (IC_RESULT (ic))
2210 && getSize (operandType (IC_RESULT (ic))) <= 2)
2212 int size = getSize (operandType (IC_RESULT (ic)));
2214 /* Special case for 1 or 2 byte return in far space. */
2215 emitcode (";", "Kevin function call abuse #1");
2220 emitcode ("mov", "b,%s", fReturn[1]);
2223 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2224 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2228 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2230 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2235 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2238 assignResultValue (IC_RESULT (ic));
2240 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2244 /* adjust the stack for parameters if
2249 if (ic->parmBytes > 3)
2251 emitcode ("mov", "a,%s", spname);
2252 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2253 emitcode ("mov", "%s,a", spname);
2256 for (i = 0; i < ic->parmBytes; i++)
2257 emitcode ("dec", "%s", spname);
2261 /* if register bank was saved then pop them */
2263 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2265 /* if we hade saved some registers then unsave them */
2266 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2267 unsaveRegisters (ic);
2272 /*-----------------------------------------------------------------*/
2273 /* genPcall - generates a call by pointer statement */
2274 /*-----------------------------------------------------------------*/
2276 genPcall (iCode * ic)
2279 symbol *rlbl = newiTempLabel (NULL);
2281 D (emitcode (";", "genPcall ");
2285 /* if caller saves & we have not saved then */
2289 /* if we are calling a function that is not using
2290 the same register bank then we need to save the
2291 destination registers on the stack */
2292 detype = getSpec (operandType (IC_LEFT (ic)));
2294 IS_ISR (currFunc->etype) &&
2295 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2296 saverbank (SPEC_BANK (detype), ic, TRUE);
2299 /* push the return address on to the stack */
2300 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2301 emitcode ("push", "acc");
2302 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2303 emitcode ("push", "acc");
2305 if (options.model == MODEL_FLAT24)
2307 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2308 emitcode ("push", "acc");
2311 /* now push the calling address */
2312 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2314 pushSide (IC_LEFT (ic), FPTRSIZE);
2316 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2318 /* if send set is not empty the assign */
2323 for (sic = setFirstItem (_G.sendSet); sic;
2324 sic = setNextItem (_G.sendSet))
2326 int size, offset = 0;
2328 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2329 size = AOP_SIZE (IC_LEFT (sic));
2330 _startLazyDPSEvaluation ();
2333 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2334 FALSE, FALSE, TRUE);
2335 if (strcmp (l, fReturn[offset]))
2337 emitcode ("mov", "%s,%s",
2343 _endLazyDPSEvaluation ();
2344 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2349 emitcode ("ret", "");
2350 emitcode ("", "%05d$:", (rlbl->key + 100));
2353 /* if we need assign a result value */
2354 if ((IS_ITEMP (IC_RESULT (ic)) &&
2355 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2356 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2357 IS_TRUE_SYMOP (IC_RESULT (ic)))
2361 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2364 assignResultValue (IC_RESULT (ic));
2366 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2369 /* adjust the stack for parameters if
2374 if (ic->parmBytes > 3)
2376 emitcode ("mov", "a,%s", spname);
2377 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2378 emitcode ("mov", "%s,a", spname);
2381 for (i = 0; i < ic->parmBytes; i++)
2382 emitcode ("dec", "%s", spname);
2386 /* if register bank was saved then unsave them */
2388 (SPEC_BANK (currFunc->etype) !=
2389 SPEC_BANK (detype)))
2390 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2392 /* if we hade saved some registers then
2395 unsaveRegisters (ic);
2399 /*-----------------------------------------------------------------*/
2400 /* resultRemat - result is rematerializable */
2401 /*-----------------------------------------------------------------*/
2403 resultRemat (iCode * ic)
2405 if (SKIP_IC (ic) || ic->op == IFX)
2408 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2410 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2411 if (sym->remat && !POINTER_SET (ic))
2418 #if defined(__BORLANDC__) || defined(_MSC_VER)
2419 #define STRCASECMP stricmp
2421 #define STRCASECMP strcasecmp
2424 /*-----------------------------------------------------------------*/
2425 /* inExcludeList - return 1 if the string is in exclude Reg list */
2426 /*-----------------------------------------------------------------*/
2428 inExcludeList (char *s)
2432 if (options.excludeRegs[i] &&
2433 STRCASECMP (options.excludeRegs[i], "none") == 0)
2436 for (i = 0; options.excludeRegs[i]; i++)
2438 if (options.excludeRegs[i] &&
2439 STRCASECMP (s, options.excludeRegs[i]) == 0)
2445 /*-----------------------------------------------------------------*/
2446 /* genFunction - generated code for function entry */
2447 /*-----------------------------------------------------------------*/
2449 genFunction (iCode * ic)
2454 D (emitcode (";", "genFunction ");
2458 /* create the function header */
2459 emitcode (";", "-----------------------------------------");
2460 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2461 emitcode (";", "-----------------------------------------");
2463 emitcode ("", "%s:", sym->rname);
2464 fetype = getSpec (operandType (IC_LEFT (ic)));
2466 /* if critical function then turn interrupts off */
2467 if (SPEC_CRTCL (fetype))
2468 emitcode ("clr", "ea");
2470 /* here we need to generate the equates for the
2471 register bank if required */
2472 if (SPEC_BANK (fetype) != rbank)
2476 rbank = SPEC_BANK (fetype);
2477 for (i = 0; i < ds390_nRegs; i++)
2479 if (strcmp (regs390[i].base, "0") == 0)
2480 emitcode ("", "%s = 0x%02x",
2482 8 * rbank + regs390[i].offset);
2484 emitcode ("", "%s = %s + 0x%02x",
2487 8 * rbank + regs390[i].offset);
2491 /* if this is an interrupt service routine then
2492 save acc, b, dpl, dph */
2493 if (IS_ISR (sym->etype))
2496 if (!inExcludeList ("acc"))
2497 emitcode ("push", "acc");
2498 if (!inExcludeList ("b"))
2499 emitcode ("push", "b");
2500 if (!inExcludeList ("dpl"))
2501 emitcode ("push", "dpl");
2502 if (!inExcludeList ("dph"))
2503 emitcode ("push", "dph");
2504 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2506 emitcode ("push", "dpx");
2507 /* Make sure we're using standard DPTR */
2508 emitcode ("push", "dps");
2509 emitcode ("mov", "dps, #0x00");
2510 if (options.stack10bit)
2512 /* This ISR could conceivably use DPTR2. Better save it. */
2513 emitcode ("push", "dpl1");
2514 emitcode ("push", "dph1");
2515 emitcode ("push", "dpx1");
2516 emitcode ("push", "ap");
2519 /* if this isr has no bank i.e. is going to
2520 run with bank 0 , then we need to save more
2522 if (!SPEC_BANK (sym->etype))
2525 /* if this function does not call any other
2526 function then we can be economical and
2527 save only those registers that are used */
2532 /* if any registers used */
2535 /* save the registers used */
2536 for (i = 0; i < sym->regsUsed->size; i++)
2538 if (bitVectBitValue (sym->regsUsed, i) ||
2539 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2540 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2547 /* this function has a function call cannot
2548 determines register usage so we will have the
2550 saverbank (0, ic, FALSE);
2556 /* if callee-save to be used for this function
2557 then save the registers being used in this function */
2558 if (sym->calleeSave)
2562 /* if any registers used */
2565 /* save the registers used */
2566 for (i = 0; i < sym->regsUsed->size; i++)
2568 if (bitVectBitValue (sym->regsUsed, i) ||
2569 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2571 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2579 /* set the register bank to the desired value */
2580 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2582 emitcode ("push", "psw");
2583 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2586 if (IS_RENT (sym->etype) || options.stackAuto)
2589 if (options.useXstack)
2591 emitcode ("mov", "r0,%s", spname);
2592 emitcode ("mov", "a,_bp");
2593 emitcode ("movx", "@r0,a");
2594 emitcode ("inc", "%s", spname);
2598 /* set up the stack */
2599 emitcode ("push", "_bp"); /* save the callers stack */
2601 emitcode ("mov", "_bp,%s", spname);
2604 /* adjust the stack for the function */
2610 werror (W_STACK_OVERFLOW, sym->name);
2612 if (i > 3 && sym->recvSize < 4)
2615 emitcode ("mov", "a,sp");
2616 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2617 emitcode ("mov", "sp,a");
2622 emitcode ("inc", "sp");
2628 emitcode ("mov", "a,_spx");
2629 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2630 emitcode ("mov", "_spx,a");
2635 /*-----------------------------------------------------------------*/
2636 /* genEndFunction - generates epilogue for functions */
2637 /*-----------------------------------------------------------------*/
2639 genEndFunction (iCode * ic)
2641 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2643 D (emitcode (";", "genEndFunction ");
2646 if (IS_RENT (sym->etype) || options.stackAuto)
2648 emitcode ("mov", "%s,_bp", spname);
2651 /* if use external stack but some variables were
2652 added to the local stack then decrement the
2654 if (options.useXstack && sym->stack)
2656 emitcode ("mov", "a,sp");
2657 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2658 emitcode ("mov", "sp,a");
2662 if ((IS_RENT (sym->etype) || options.stackAuto))
2664 if (options.useXstack)
2666 emitcode ("mov", "r0,%s", spname);
2667 emitcode ("movx", "a,@r0");
2668 emitcode ("mov", "_bp,a");
2669 emitcode ("dec", "%s", spname);
2673 emitcode ("pop", "_bp");
2677 /* restore the register bank */
2678 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2679 emitcode ("pop", "psw");
2681 if (IS_ISR (sym->etype))
2684 /* now we need to restore the registers */
2685 /* if this isr has no bank i.e. is going to
2686 run with bank 0 , then we need to save more
2688 if (!SPEC_BANK (sym->etype))
2691 /* if this function does not call any other
2692 function then we can be economical and
2693 save only those registers that are used */
2698 /* if any registers used */
2701 /* save the registers used */
2702 for (i = sym->regsUsed->size; i >= 0; i--)
2704 if (bitVectBitValue (sym->regsUsed, i) ||
2705 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2706 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2713 /* this function has a function call cannot
2714 determines register usage so we will have the
2716 unsaverbank (0, ic, FALSE);
2720 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2722 if (options.stack10bit)
2724 emitcode ("pop", "ap");
2725 emitcode ("pop", "dpx1");
2726 emitcode ("pop", "dph1");
2727 emitcode ("pop", "dpl1");
2729 emitcode ("pop", "dps");
2730 emitcode ("pop", "dpx");
2732 if (!inExcludeList ("dph"))
2733 emitcode ("pop", "dph");
2734 if (!inExcludeList ("dpl"))
2735 emitcode ("pop", "dpl");
2736 if (!inExcludeList ("b"))
2737 emitcode ("pop", "b");
2738 if (!inExcludeList ("acc"))
2739 emitcode ("pop", "acc");
2741 if (SPEC_CRTCL (sym->etype))
2742 emitcode ("setb", "ea");
2744 /* if debug then send end of function */
2745 /* if (options.debug && currFunc) { */
2749 emitcode ("", "C$%s$%d$%d$%d ==.",
2750 FileBaseName (ic->filename), currFunc->lastLine,
2751 ic->level, ic->block);
2752 if (IS_STATIC (currFunc->etype))
2753 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2755 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2759 emitcode ("reti", "");
2763 if (SPEC_CRTCL (sym->etype))
2764 emitcode ("setb", "ea");
2766 if (sym->calleeSave)
2770 /* if any registers used */
2773 /* save the registers used */
2774 for (i = sym->regsUsed->size; i >= 0; i--)
2776 if (bitVectBitValue (sym->regsUsed, i) ||
2777 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2778 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2784 /* if debug then send end of function */
2788 emitcode ("", "C$%s$%d$%d$%d ==.",
2789 FileBaseName (ic->filename), currFunc->lastLine,
2790 ic->level, ic->block);
2791 if (IS_STATIC (currFunc->etype))
2792 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2794 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2798 emitcode ("ret", "");
2803 /*-----------------------------------------------------------------*/
2804 /* genRet - generate code for return statement */
2805 /*-----------------------------------------------------------------*/
2809 int size, offset = 0, pushed = 0;
2811 D (emitcode (";", "genRet ");
2814 /* if we have no return value then
2815 just generate the "ret" */
2819 /* we have something to return then
2820 move the return value into place */
2821 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2822 size = AOP_SIZE (IC_LEFT (ic));
2824 _startLazyDPSEvaluation ();
2828 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2830 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2831 FALSE, TRUE, FALSE);
2832 emitcode ("push", "%s", l);
2837 l = aopGet (AOP (IC_LEFT (ic)), offset,
2838 FALSE, FALSE, FALSE);
2839 if (strcmp (fReturn[offset], l))
2840 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2843 _endLazyDPSEvaluation ();
2850 if (strcmp (fReturn[pushed], "a"))
2851 emitcode ("pop", fReturn[pushed]);
2853 emitcode ("pop", "acc");
2856 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2859 /* generate a jump to the return label
2860 if the next is not the return statement */
2861 if (!(ic->next && ic->next->op == LABEL &&
2862 IC_LABEL (ic->next) == returnLabel))
2864 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2868 /*-----------------------------------------------------------------*/
2869 /* genLabel - generates a label */
2870 /*-----------------------------------------------------------------*/
2872 genLabel (iCode * ic)
2874 /* special case never generate */
2875 if (IC_LABEL (ic) == entryLabel)
2878 D (emitcode (";", "genLabel ");
2881 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2884 /*-----------------------------------------------------------------*/
2885 /* genGoto - generates a ljmp */
2886 /*-----------------------------------------------------------------*/
2888 genGoto (iCode * ic)
2890 D (emitcode (";", "genGoto ");
2892 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2895 /*-----------------------------------------------------------------*/
2896 /* findLabelBackwards: walks back through the iCode chain looking */
2897 /* for the given label. Returns number of iCode instructions */
2898 /* between that label and given ic. */
2899 /* Returns zero if label not found. */
2900 /*-----------------------------------------------------------------*/
2902 findLabelBackwards (iCode * ic, int key)
2911 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2913 /* printf("findLabelBackwards = %d\n", count); */
2921 /*-----------------------------------------------------------------*/
2922 /* genPlusIncr :- does addition with increment if possible */
2923 /*-----------------------------------------------------------------*/
2925 genPlusIncr (iCode * ic)
2927 unsigned int icount;
2928 unsigned int size = getDataSize (IC_RESULT (ic));
2930 /* will try to generate an increment */
2931 /* if the right side is not a literal
2933 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2936 /* if the literal value of the right hand side
2937 is greater than 4 then it is not worth it */
2938 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2941 /* if increment 16 bits in register */
2943 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2944 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2945 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2953 /* If the next instruction is a goto and the goto target
2954 * is <= 5 instructions previous to this, we can generate
2955 * jumps straight to that target.
2957 if (ic->next && ic->next->op == GOTO
2958 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2961 emitcode (";", "tail increment optimized (range %d)", labelRange);
2962 tlbl = IC_LABEL (ic->next);
2967 tlbl = newiTempLabel (NULL);
2970 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2971 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2972 IS_AOP_PREG (IC_RESULT (ic)))
2973 emitcode ("cjne", "%s,#0x00,%05d$"
2974 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2978 emitcode ("clr", "a");
2979 emitcode ("cjne", "a,%s,%05d$"
2980 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2984 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2987 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2988 IS_AOP_PREG (IC_RESULT (ic)))
2989 emitcode ("cjne", "%s,#0x00,%05d$"
2990 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2993 emitcode ("cjne", "a,%s,%05d$"
2994 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2997 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3001 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3002 IS_AOP_PREG (IC_RESULT (ic)))
3003 emitcode ("cjne", "%s,#0x00,%05d$"
3004 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3008 emitcode ("cjne", "a,%s,%05d$"
3009 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3012 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3017 emitcode ("", "%05d$:", tlbl->key + 100);
3022 /* if the sizes are greater than 1 then we cannot */
3023 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3024 AOP_SIZE (IC_LEFT (ic)) > 1)
3027 /* we can if the aops of the left & result match or
3028 if they are in registers and the registers are the
3031 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3032 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3033 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3038 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3039 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3040 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3045 _startLazyDPSEvaluation ();
3048 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3050 _endLazyDPSEvaluation ();
3059 /*-----------------------------------------------------------------*/
3060 /* outBitAcc - output a bit in acc */
3061 /*-----------------------------------------------------------------*/
3063 outBitAcc (operand * result)
3065 symbol *tlbl = newiTempLabel (NULL);
3066 /* if the result is a bit */
3067 if (AOP_TYPE (result) == AOP_CRY)
3069 aopPut (AOP (result), "a", 0);
3073 emitcode ("jz", "%05d$", tlbl->key + 100);
3074 emitcode ("mov", "a,%s", one);
3075 emitcode ("", "%05d$:", tlbl->key + 100);
3080 /*-----------------------------------------------------------------*/
3081 /* genPlusBits - generates code for addition of two bits */
3082 /*-----------------------------------------------------------------*/
3084 genPlusBits (iCode * ic)
3086 D (emitcode (";", "genPlusBits ");
3088 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3090 symbol *lbl = newiTempLabel (NULL);
3091 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3092 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3093 emitcode ("cpl", "c");
3094 emitcode ("", "%05d$:", (lbl->key + 100));
3095 outBitC (IC_RESULT (ic));
3099 emitcode ("clr", "a");
3100 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3101 emitcode ("rlc", "a");
3102 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3103 emitcode ("addc", "a,#0x00");
3104 outAcc (IC_RESULT (ic));
3109 adjustArithmeticResult (iCode * ic)
3111 if (opIsGptr (IC_RESULT (ic)) &&
3112 opIsGptr (IC_LEFT (ic)) &&
3113 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3115 aopPut (AOP (IC_RESULT (ic)),
3116 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3120 if (opIsGptr (IC_RESULT (ic)) &&
3121 opIsGptr (IC_RIGHT (ic)) &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3124 aopPut (AOP (IC_RESULT (ic)),
3125 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3129 if (opIsGptr (IC_RESULT (ic)) &&
3130 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3131 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3132 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3133 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3136 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3137 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3141 #define AOP_OP_3(ic) \
3142 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3143 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3144 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3145 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3146 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3147 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3149 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3151 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3154 #define AOP_OP_3_NOFATAL(ic, rc) \
3155 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3156 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3157 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3158 isOperandInFarSpace(IC_RESULT(ic))) \
3160 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3165 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3166 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3168 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3169 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3171 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3173 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3177 #define AOP_OP_2(ic) \
3178 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3179 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3181 #define AOP_SET_LOCALS(ic) \
3182 left = IC_LEFT(ic); \
3183 right = IC_RIGHT(ic); \
3184 result = IC_RESULT(ic);
3186 /*-----------------------------------------------------------------*/
3187 /* genPlus - generates code for addition */
3188 /*-----------------------------------------------------------------*/
3190 genPlus (iCode * ic)
3192 int size, offset = 0;
3193 bool pushResult = FALSE;
3196 D (emitcode (";", "genPlus ");
3199 /* special cases :- */
3201 AOP_OP_3_NOFATAL (ic, pushResult);
3204 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3210 /* if literal, literal on the right or
3211 if left requires ACC or right is already
3213 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3214 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3215 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3217 operand *t = IC_RIGHT (ic);
3218 IC_RIGHT (ic) = IC_LEFT (ic);
3220 emitcode (";", "Swapped plus args.");
3223 /* if both left & right are in bit
3225 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3226 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3232 /* if left in bit space & right literal */
3233 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3234 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3236 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3237 /* if result in bit space */
3238 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3240 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3241 emitcode ("cpl", "c");
3242 outBitC (IC_RESULT (ic));
3246 size = getDataSize (IC_RESULT (ic));
3247 _startLazyDPSEvaluation ();
3250 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3251 emitcode ("addc", "a,#00");
3252 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3254 _endLazyDPSEvaluation ();
3259 /* if I can do an increment instead
3260 of add then GOOD for ME */
3261 if (genPlusIncr (ic) == TRUE)
3263 emitcode (";", "did genPlusIncr");
3268 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3270 _startLazyDPSEvaluation ();
3273 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3275 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3277 emitcode ("add", "a,%s",
3278 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3280 emitcode ("addc", "a,%s",
3281 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3285 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3287 emitcode ("add", "a,%s",
3288 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3290 emitcode ("addc", "a,%s",
3291 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3295 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3299 emitcode ("push", "acc");
3303 _endLazyDPSEvaluation ();
3307 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3309 size = getDataSize (IC_LEFT (ic));
3310 rSize = getDataSize (IC_RESULT (ic));
3312 /* If the pushed data is bigger than the result,
3313 * simply discard unused bytes. Icky, but works.
3315 * Should we throw a warning here? We're losing data...
3317 while (size > rSize)
3319 D (emitcode (";", "discarding unused result byte.");
3321 emitcode ("pop", "acc");
3327 emitcode ("clr", "a");
3328 /* Conversly, we haven't pushed enough here.
3329 * just zero-pad, and all is well.
3331 while (size < rSize)
3333 emitcode ("push", "acc");
3339 _startLazyDPSEvaluation ();
3342 emitcode ("pop", "acc");
3343 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3345 _endLazyDPSEvaluation ();
3348 adjustArithmeticResult (ic);
3351 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3352 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3353 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3356 /*-----------------------------------------------------------------*/
3357 /* genMinusDec :- does subtraction with deccrement if possible */
3358 /*-----------------------------------------------------------------*/
3360 genMinusDec (iCode * ic)
3362 unsigned int icount;
3363 unsigned int size = getDataSize (IC_RESULT (ic));
3365 /* will try to generate an increment */
3366 /* if the right side is not a literal
3368 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3371 /* if the literal value of the right hand side
3372 is greater than 4 then it is not worth it */
3373 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3376 /* if decrement 16 bits in register */
3377 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3378 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3379 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3387 /* If the next instruction is a goto and the goto target
3388 * is <= 5 instructions previous to this, we can generate
3389 * jumps straight to that target.
3391 if (ic->next && ic->next->op == GOTO
3392 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3395 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3396 tlbl = IC_LABEL (ic->next);
3401 tlbl = newiTempLabel (NULL);
3405 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3406 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3407 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3408 IS_AOP_PREG (IC_RESULT (ic)))
3409 emitcode ("cjne", "%s,#0xff,%05d$"
3410 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3414 emitcode ("mov", "a,#0xff");
3415 emitcode ("cjne", "a,%s,%05d$"
3416 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3419 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3422 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3423 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3424 IS_AOP_PREG (IC_RESULT (ic)))
3425 emitcode ("cjne", "%s,#0xff,%05d$"
3426 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3430 emitcode ("cjne", "a,%s,%05d$"
3431 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3434 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3438 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3439 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3440 IS_AOP_PREG (IC_RESULT (ic)))
3441 emitcode ("cjne", "%s,#0xff,%05d$"
3442 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3446 emitcode ("cjne", "a,%s,%05d$"
3447 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3450 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3454 emitcode ("", "%05d$:", tlbl->key + 100);
3459 /* if the sizes are greater than 1 then we cannot */
3460 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3461 AOP_SIZE (IC_LEFT (ic)) > 1)
3464 /* we can if the aops of the left & result match or
3465 if they are in registers and the registers are the
3468 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3469 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3470 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3473 _startLazyDPSEvaluation ();
3476 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3478 _endLazyDPSEvaluation ();
3486 /*-----------------------------------------------------------------*/
3487 /* addSign - complete with sign */
3488 /*-----------------------------------------------------------------*/
3490 addSign (operand * result, int offset, int sign)
3492 int size = (getDataSize (result) - offset);
3497 emitcode ("rlc", "a");
3498 emitcode ("subb", "a,acc");
3500 aopPut (AOP (result), "a", offset++);
3504 aopPut (AOP (result), zero, offset++);
3508 /*-----------------------------------------------------------------*/
3509 /* genMinusBits - generates code for subtraction of two bits */
3510 /*-----------------------------------------------------------------*/
3512 genMinusBits (iCode * ic)
3514 symbol *lbl = newiTempLabel (NULL);
3516 D (emitcode (";", "genMinusBits ");
3519 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3521 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3522 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3523 emitcode ("cpl", "c");
3524 emitcode ("", "%05d$:", (lbl->key + 100));
3525 outBitC (IC_RESULT (ic));
3529 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3530 emitcode ("subb", "a,acc");
3531 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3532 emitcode ("inc", "a");
3533 emitcode ("", "%05d$:", (lbl->key + 100));
3534 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3535 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3539 /*-----------------------------------------------------------------*/
3540 /* genMinus - generates code for subtraction */
3541 /*-----------------------------------------------------------------*/
3543 genMinus (iCode * ic)
3545 int size, offset = 0;
3547 unsigned long lit = 0L;
3548 bool pushResult = FALSE;
3550 D (emitcode (";", "genMinus ");
3553 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3554 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3555 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3556 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3562 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3564 /* special cases :- */
3565 /* if both left & right are in bit space */
3566 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3567 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3573 /* if I can do an decrement instead
3574 of subtract then GOOD for ME */
3575 if (genMinusDec (ic) == TRUE)
3580 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3582 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3588 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3593 /* if literal, add a,#-lit, else normal subb */
3594 _startLazyDPSEvaluation ();
3597 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3598 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3599 emitcode ("subb", "a,%s",
3600 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3603 /* first add without previous c */
3605 emitcode ("add", "a,#0x%02x",
3606 (unsigned int) (lit & 0x0FFL));
3608 emitcode ("addc", "a,#0x%02x",
3609 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3614 emitcode ("push", "acc");
3618 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3622 _endLazyDPSEvaluation ();
3626 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3628 size = getDataSize (IC_LEFT (ic));
3629 rSize = getDataSize (IC_RESULT (ic));
3631 /* If the pushed data is bigger than the result,
3632 * simply discard unused bytes. Icky, but works.
3634 * Should we throw a warning here? We're losing data...
3636 while (size > getDataSize (IC_RESULT (ic)))
3638 emitcode (";", "discarding unused result byte.");
3639 emitcode ("pop", "acc");
3645 emitcode ("clr", "a");
3646 /* Conversly, we haven't pushed enough here.
3647 * just zero-pad, and all is well.
3649 while (size < rSize)
3651 emitcode ("push", "acc");
3659 emitcode ("pop", "acc");
3660 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3664 adjustArithmeticResult (ic);
3667 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3668 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3669 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3673 /*-----------------------------------------------------------------*/
3674 /* genMultbits :- multiplication of bits */
3675 /*-----------------------------------------------------------------*/
3677 genMultbits (operand * left,
3681 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3682 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3687 /*-----------------------------------------------------------------*/
3688 /* genMultOneByte : 8*8=16 bit multiplication */
3689 /*-----------------------------------------------------------------*/
3691 emitcode(";catch","me");
3695 genMultOneByte (operand * left,
3699 sym_link *opetype = operandType (result);
3702 if (AOP_SIZE (result)!=2) {
3703 // this should never happen
3704 fprintf (stderr, "size!=2 in geniCodeMultOneByte\n");
3707 if (SPEC_USIGN(opetype) ||
3708 // ignore the sign of left and right, what else can we do?
3709 (SPEC_USIGN(operandType(left)) &&
3710 SPEC_USIGN(operandType(right)))) {
3711 // just an unsigned 8*8=16 multiply
3712 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3713 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3714 emitcode ("mul", "ab");
3715 aopPut (AOP (result), "a", 0);
3716 aopPut (AOP (result), "b", 1);
3720 // we have to do a signed multiply
3723 // literals ignored for now
3725 /* (if two literals: the value is computed before) */
3726 /* if one literal, literal on the right */
3727 if (AOP_TYPE (left) == AOP_LIT)
3735 emitcode ("mov", "ap,#0"); // can't we use some flag bit here?
3736 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3737 lbl=newiTempLabel(NULL);
3738 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3739 // right side is negative, should test for litteral too
3740 emitcode ("inc", "ap"); // opRight is negative
3741 emitcode ("cpl", "a"); // 8-bit two's complement, this fails for -128
3742 emitcode ("inc", "a");
3743 emitcode ("", "%05d$:", lbl->key+100);
3744 emitcode ("mov", "b,a");
3746 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3747 lbl=newiTempLabel(NULL);
3748 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3749 // left side is negative
3750 emitcode ("inc", "ap"); // opLeft is negative
3751 emitcode ("cpl", "a"); // 8-bit two's complement, this fails for -128
3752 emitcode ("inc", "a");
3753 emitcode ("", "%05d$:", lbl->key+100);
3754 emitcode ("mul", "ab");
3756 lbl=newiTempLabel(NULL);
3757 emitcode ("xch", "a,ap");
3758 emitcode ("rrc", "a");
3759 emitcode ("xch", "a,ap");
3760 emitcode ("jnc", "%05d$", lbl->key+100);
3761 // only ONE op was negative, we have to do a 16-bit two's complement
3762 emitcode ("setb", "c");
3763 emitcode ("cpl", "a");
3764 emitcode ("addc", "a,#0");
3765 emitcode ("push", "acc"); // lsb
3766 emitcode ("mov", "a,b");
3767 emitcode ("cpl", "a");
3768 emitcode ("addc", "a,#0");
3769 emitcode ("mov", "b,a"); // msb
3770 emitcode ("pop", "acc"); // lsb
3772 emitcode ("", "%05d$:", lbl->key+100);
3773 aopPut (AOP (result), "a", 0);
3774 aopPut (AOP (result), "b", 1);
3777 /*-----------------------------------------------------------------*/
3778 /* genMult - generates code for multiplication */
3779 /*-----------------------------------------------------------------*/
3781 genMult (iCode * ic)
3783 operand *left = IC_LEFT (ic);
3784 operand *right = IC_RIGHT (ic);
3785 operand *result = IC_RESULT (ic);
3787 D (emitcode (";", "genMult ");
3790 /* assign the amsops */
3793 /* special cases first */
3795 if (AOP_TYPE (left) == AOP_CRY &&
3796 AOP_TYPE (right) == AOP_CRY)
3798 genMultbits (left, right, result);
3802 /* if both are of size == 1 */
3803 if (AOP_SIZE (left) == 1 &&
3804 AOP_SIZE (right) == 1)
3806 genMultOneByte (left, right, result);
3810 /* should have been converted to function call */
3814 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3815 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3816 freeAsmop (result, NULL, ic, TRUE);
3819 /*-----------------------------------------------------------------*/
3820 /* genDivbits :- division of bits */
3821 /*-----------------------------------------------------------------*/
3823 genDivbits (operand * left,
3830 /* the result must be bit */
3831 LOAD_AB_FOR_DIV (left, right, l);
3832 emitcode ("div", "ab");
3833 emitcode ("rrc", "a");
3834 aopPut (AOP (result), "c", 0);
3837 /*-----------------------------------------------------------------*/
3838 /* genDivOneByte : 8 bit division */
3839 /*-----------------------------------------------------------------*/
3841 genDivOneByte (operand * left,
3845 sym_link *opetype = operandType (result);
3850 size = AOP_SIZE (result) - 1;
3852 /* signed or unsigned */
3853 if (SPEC_USIGN (opetype))
3855 /* unsigned is easy */
3856 LOAD_AB_FOR_DIV (left, right, l);
3857 emitcode ("div", "ab");
3858 aopPut (AOP (result), "a", 0);
3860 aopPut (AOP (result), zero, offset++);
3864 /* signed is a little bit more difficult */
3866 /* save the signs of the operands */
3867 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3869 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3870 emitcode ("push", "acc"); /* save it on the stack */
3872 /* now sign adjust for both left & right */
3873 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3875 lbl = newiTempLabel (NULL);
3876 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3877 emitcode ("cpl", "a");
3878 emitcode ("inc", "a");
3879 emitcode ("", "%05d$:", (lbl->key + 100));
3880 emitcode ("mov", "b,a");
3882 /* sign adjust left side */
3883 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3886 lbl = newiTempLabel (NULL);
3887 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3888 emitcode ("cpl", "a");
3889 emitcode ("inc", "a");
3890 emitcode ("", "%05d$:", (lbl->key + 100));
3892 /* now the division */
3893 emitcode ("nop", "; workaround for DS80C390 div bug.");
3894 emitcode ("div", "ab");
3895 /* we are interested in the lower order
3897 emitcode ("mov", "b,a");
3898 lbl = newiTempLabel (NULL);
3899 emitcode ("pop", "acc");
3900 /* if there was an over flow we don't
3901 adjust the sign of the result */
3902 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3903 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3905 emitcode ("clr", "a");
3906 emitcode ("subb", "a,b");
3907 emitcode ("mov", "b,a");
3908 emitcode ("", "%05d$:", (lbl->key + 100));
3910 /* now we are done */
3911 aopPut (AOP (result), "b", 0);
3914 emitcode ("mov", "c,b.7");
3915 emitcode ("subb", "a,acc");
3918 aopPut (AOP (result), "a", offset++);
3922 /*-----------------------------------------------------------------*/
3923 /* genDiv - generates code for division */
3924 /*-----------------------------------------------------------------*/
3928 operand *left = IC_LEFT (ic);
3929 operand *right = IC_RIGHT (ic);
3930 operand *result = IC_RESULT (ic);
3932 D (emitcode (";", "genDiv ");
3935 /* assign the amsops */
3938 /* special cases first */
3940 if (AOP_TYPE (left) == AOP_CRY &&
3941 AOP_TYPE (right) == AOP_CRY)
3943 genDivbits (left, right, result);
3947 /* if both are of size == 1 */
3948 if (AOP_SIZE (left) == 1 &&
3949 AOP_SIZE (right) == 1)
3951 genDivOneByte (left, right, result);
3955 /* should have been converted to function call */
3958 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3959 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3960 freeAsmop (result, NULL, ic, TRUE);
3963 /*-----------------------------------------------------------------*/
3964 /* genModbits :- modulus of bits */
3965 /*-----------------------------------------------------------------*/
3967 genModbits (operand * left,
3974 /* the result must be bit */
3975 LOAD_AB_FOR_DIV (left, right, l);
3976 emitcode ("div", "ab");
3977 emitcode ("mov", "a,b");
3978 emitcode ("rrc", "a");
3979 aopPut (AOP (result), "c", 0);
3982 /*-----------------------------------------------------------------*/
3983 /* genModOneByte : 8 bit modulus */
3984 /*-----------------------------------------------------------------*/
3986 genModOneByte (operand * left,
3990 sym_link *opetype = operandType (result);
3994 /* signed or unsigned */
3995 if (SPEC_USIGN (opetype))
3997 /* unsigned is easy */
3998 LOAD_AB_FOR_DIV (left, right, l);
3999 emitcode ("div", "ab");
4000 aopPut (AOP (result), "b", 0);
4004 /* signed is a little bit more difficult */
4006 /* save the signs of the operands */
4007 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4010 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4011 emitcode ("push", "acc"); /* save it on the stack */
4013 /* now sign adjust for both left & right */
4014 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4017 lbl = newiTempLabel (NULL);
4018 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4019 emitcode ("cpl", "a");
4020 emitcode ("inc", "a");
4021 emitcode ("", "%05d$:", (lbl->key + 100));
4022 emitcode ("mov", "b,a");
4024 /* sign adjust left side */
4025 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4028 lbl = newiTempLabel (NULL);
4029 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4030 emitcode ("cpl", "a");
4031 emitcode ("inc", "a");
4032 emitcode ("", "%05d$:", (lbl->key + 100));
4034 /* now the multiplication */
4035 emitcode ("nop", "; workaround for DS80C390 div bug.");
4036 emitcode ("div", "ab");
4037 /* we are interested in the lower order
4039 lbl = newiTempLabel (NULL);
4040 emitcode ("pop", "acc");
4041 /* if there was an over flow we don't
4042 adjust the sign of the result */
4043 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4044 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4046 emitcode ("clr", "a");
4047 emitcode ("subb", "a,b");
4048 emitcode ("mov", "b,a");
4049 emitcode ("", "%05d$:", (lbl->key + 100));
4051 /* now we are done */
4052 aopPut (AOP (result), "b", 0);
4056 /*-----------------------------------------------------------------*/
4057 /* genMod - generates code for division */
4058 /*-----------------------------------------------------------------*/
4062 operand *left = IC_LEFT (ic);
4063 operand *right = IC_RIGHT (ic);
4064 operand *result = IC_RESULT (ic);
4066 D (emitcode (";", "genMod ");
4069 /* assign the amsops */
4072 /* special cases first */
4074 if (AOP_TYPE (left) == AOP_CRY &&
4075 AOP_TYPE (right) == AOP_CRY)
4077 genModbits (left, right, result);
4081 /* if both are of size == 1 */
4082 if (AOP_SIZE (left) == 1 &&
4083 AOP_SIZE (right) == 1)
4085 genModOneByte (left, right, result);
4089 /* should have been converted to function call */
4093 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4094 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4095 freeAsmop (result, NULL, ic, TRUE);
4098 /*-----------------------------------------------------------------*/
4099 /* genIfxJump :- will create a jump depending on the ifx */
4100 /*-----------------------------------------------------------------*/
4102 genIfxJump (iCode * ic, char *jval)
4105 symbol *tlbl = newiTempLabel (NULL);
4108 D (emitcode (";", "genIfxJump ");
4111 /* if true label then we jump if condition
4115 jlbl = IC_TRUE (ic);
4116 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4117 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4121 /* false label is present */
4122 jlbl = IC_FALSE (ic);
4123 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4124 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4126 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4127 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4129 emitcode (inst, "%05d$", tlbl->key + 100);
4130 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4131 emitcode ("", "%05d$:", tlbl->key + 100);
4133 /* mark the icode as generated */
4137 /*-----------------------------------------------------------------*/
4138 /* genCmp :- greater or less than comparison */
4139 /*-----------------------------------------------------------------*/
4141 genCmp (operand * left, operand * right,
4142 iCode * ic, iCode * ifx, int sign)
4144 int size, offset = 0;
4145 unsigned long lit = 0L;
4148 D (emitcode (";", "genCmp");
4151 result = IC_RESULT (ic);
4153 /* if left & right are bit variables */
4154 if (AOP_TYPE (left) == AOP_CRY &&
4155 AOP_TYPE (right) == AOP_CRY)
4157 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4158 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4162 /* subtract right from left if at the
4163 end the carry flag is set then we know that
4164 left is greater than right */
4165 size = max (AOP_SIZE (left), AOP_SIZE (right));
4167 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4168 if ((size == 1) && !sign &&
4169 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4171 symbol *lbl = newiTempLabel (NULL);
4172 emitcode ("cjne", "%s,%s,%05d$",
4173 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4174 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4176 emitcode ("", "%05d$:", lbl->key + 100);
4180 if (AOP_TYPE (right) == AOP_LIT)
4182 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4183 /* optimize if(x < 0) or if(x >= 0) */
4192 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4194 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4195 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4197 aopOp (result, ic, FALSE, FALSE);
4199 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4201 freeAsmop (result, NULL, ic, TRUE);
4202 genIfxJump (ifx, "acc.7");
4207 emitcode ("rlc", "a");
4209 goto release_freedLR;
4217 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4218 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4219 emitcode (";", "genCmp #2");
4220 if (sign && (size == 0))
4222 emitcode (";", "genCmp #3");
4223 emitcode ("xrl", "a,#0x80");
4224 if (AOP_TYPE (right) == AOP_LIT)
4226 unsigned long lit = (unsigned long)
4227 floatFromVal (AOP (right)->aopu.aop_lit);
4228 emitcode (";", "genCmp #3.1");
4229 emitcode ("subb", "a,#0x%02x",
4230 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4234 emitcode (";", "genCmp #3.2");
4235 if (AOP_NEEDSACC (right))
4237 emitcode ("push", "acc");
4239 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4240 FALSE, FALSE, FALSE));
4241 emitcode ("xrl", "b,#0x80");
4242 if (AOP_NEEDSACC (right))
4244 emitcode ("pop", "acc");
4246 emitcode ("subb", "a,b");
4253 emitcode (";", "genCmp #4");
4254 if (AOP_NEEDSACC (right))
4257 emitcode (";", "genCmp #4.1");
4258 emitcode ("xch", "a, b");
4259 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4260 emitcode ("xch", "a, b");
4265 emitcode (";", "genCmp #4.2");
4266 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4269 emitcode ("subb", "a,%s", s);
4276 /* Don't need the left & right operands any more; do need the result. */
4277 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4278 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4280 aopOp (result, ic, FALSE, FALSE);
4284 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4290 /* if the result is used in the next
4291 ifx conditional branch then generate
4292 code a little differently */
4295 genIfxJump (ifx, "c");
4301 /* leave the result in acc */
4303 freeAsmop (result, NULL, ic, TRUE);
4306 /*-----------------------------------------------------------------*/
4307 /* genCmpGt :- greater than comparison */
4308 /*-----------------------------------------------------------------*/
4310 genCmpGt (iCode * ic, iCode * ifx)
4312 operand *left, *right;
4313 sym_link *letype, *retype;
4316 D (emitcode (";", "genCmpGt ");
4319 left = IC_LEFT (ic);
4320 right = IC_RIGHT (ic);
4322 letype = getSpec (operandType (left));
4323 retype = getSpec (operandType (right));
4324 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4326 /* assign the left & right amsops */
4329 genCmp (right, left, ic, ifx, sign);
4332 /*-----------------------------------------------------------------*/
4333 /* genCmpLt - less than comparisons */
4334 /*-----------------------------------------------------------------*/
4336 genCmpLt (iCode * ic, iCode * ifx)
4338 operand *left, *right;
4339 sym_link *letype, *retype;
4342 D (emitcode (";", "genCmpLt ");
4345 left = IC_LEFT (ic);
4346 right = IC_RIGHT (ic);
4348 letype = getSpec (operandType (left));
4349 retype = getSpec (operandType (right));
4350 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4352 /* assign the left & right amsops */
4355 genCmp (left, right, ic, ifx, sign);
4358 /*-----------------------------------------------------------------*/
4359 /* gencjneshort - compare and jump if not equal */
4360 /*-----------------------------------------------------------------*/
4362 gencjneshort (operand * left, operand * right, symbol * lbl)
4364 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4366 unsigned long lit = 0L;
4368 D (emitcode (";", "gencjneshort");
4371 /* if the left side is a literal or
4372 if the right is in a pointer register and left
4374 if ((AOP_TYPE (left) == AOP_LIT) ||
4375 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4382 if (AOP_TYPE (right) == AOP_LIT)
4383 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4385 if (opIsGptr (left) || opIsGptr (right))
4387 /* We are comparing a generic pointer to something.
4388 * Exclude the generic type byte from the comparison.
4391 D (emitcode (";", "cjneshort: generic ptr special case.");
4396 /* if the right side is a literal then anything goes */
4397 if (AOP_TYPE (right) == AOP_LIT &&
4398 AOP_TYPE (left) != AOP_DIR)
4402 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4404 emitcode ("cjne", "a,%s,%05d$",
4405 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4411 /* if the right side is in a register or in direct space or
4412 if the left is a pointer register & right is not */
4413 else if (AOP_TYPE (right) == AOP_REG ||
4414 AOP_TYPE (right) == AOP_DIR ||
4415 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4416 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4420 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4421 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4422 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4423 emitcode ("jnz", "%05d$", lbl->key + 100);
4425 emitcode ("cjne", "a,%s,%05d$",
4426 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4433 /* right is a pointer reg need both a & b */
4436 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4437 if (strcmp (l, "b"))
4438 emitcode ("mov", "b,%s", l);
4439 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4440 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4446 /*-----------------------------------------------------------------*/
4447 /* gencjne - compare and jump if not equal */
4448 /*-----------------------------------------------------------------*/
4450 gencjne (operand * left, operand * right, symbol * lbl)
4452 symbol *tlbl = newiTempLabel (NULL);
4454 D (emitcode (";", "gencjne");
4457 gencjneshort (left, right, lbl);
4459 emitcode ("mov", "a,%s", one);
4460 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4461 emitcode ("", "%05d$:", lbl->key + 100);
4462 emitcode ("clr", "a");
4463 emitcode ("", "%05d$:", tlbl->key + 100);
4466 /*-----------------------------------------------------------------*/
4467 /* genCmpEq - generates code for equal to */
4468 /*-----------------------------------------------------------------*/
4470 genCmpEq (iCode * ic, iCode * ifx)
4472 operand *left, *right, *result;
4474 D (emitcode (";", "genCmpEq ");
4478 AOP_SET_LOCALS (ic);
4480 /* if literal, literal on the right or
4481 if the right is in a pointer register and left
4483 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4484 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4486 operand *t = IC_RIGHT (ic);
4487 IC_RIGHT (ic) = IC_LEFT (ic);
4491 if (ifx && /* !AOP_SIZE(result) */
4492 OP_SYMBOL (result) &&
4493 OP_SYMBOL (result)->regType == REG_CND)
4496 /* if they are both bit variables */
4497 if (AOP_TYPE (left) == AOP_CRY &&
4498 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4500 if (AOP_TYPE (right) == AOP_LIT)
4502 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4505 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4506 emitcode ("cpl", "c");
4510 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4514 emitcode ("clr", "c");
4516 /* AOP_TYPE(right) == AOP_CRY */
4520 symbol *lbl = newiTempLabel (NULL);
4521 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4522 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4523 emitcode ("cpl", "c");
4524 emitcode ("", "%05d$:", (lbl->key + 100));
4526 /* if true label then we jump if condition
4528 tlbl = newiTempLabel (NULL);
4531 emitcode ("jnc", "%05d$", tlbl->key + 100);
4532 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4536 emitcode ("jc", "%05d$", tlbl->key + 100);
4537 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4539 emitcode ("", "%05d$:", tlbl->key + 100);
4543 tlbl = newiTempLabel (NULL);
4544 gencjneshort (left, right, tlbl);
4547 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4548 emitcode ("", "%05d$:", tlbl->key + 100);
4552 symbol *lbl = newiTempLabel (NULL);
4553 emitcode ("sjmp", "%05d$", lbl->key + 100);
4554 emitcode ("", "%05d$:", tlbl->key + 100);
4555 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4556 emitcode ("", "%05d$:", lbl->key + 100);
4559 /* mark the icode as generated */
4562 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4563 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4567 /* if they are both bit variables */
4568 if (AOP_TYPE (left) == AOP_CRY &&
4569 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4571 if (AOP_TYPE (right) == AOP_LIT)
4573 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4576 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4577 emitcode ("cpl", "c");
4581 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4585 emitcode ("clr", "c");
4587 /* AOP_TYPE(right) == AOP_CRY */
4591 symbol *lbl = newiTempLabel (NULL);
4592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4593 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4594 emitcode ("cpl", "c");
4595 emitcode ("", "%05d$:", (lbl->key + 100));
4598 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4599 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4601 aopOp (result, ic, TRUE, FALSE);
4604 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4611 genIfxJump (ifx, "c");
4614 /* if the result is used in an arithmetic operation
4615 then put the result in place */
4620 gencjne (left, right, newiTempLabel (NULL));
4622 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4623 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4625 aopOp (result, ic, TRUE, FALSE);
4627 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4629 aopPut (AOP (result), "a", 0);
4634 genIfxJump (ifx, "a");
4637 /* if the result is used in an arithmetic operation
4638 then put the result in place */
4639 if (AOP_TYPE (result) != AOP_CRY)
4641 /* leave the result in acc */
4645 freeAsmop (result, NULL, ic, TRUE);
4648 /*-----------------------------------------------------------------*/
4649 /* ifxForOp - returns the icode containing the ifx for operand */
4650 /*-----------------------------------------------------------------*/
4652 ifxForOp (operand * op, iCode * ic)
4654 /* if true symbol then needs to be assigned */
4655 if (IS_TRUE_SYMOP (op))
4658 /* if this has register type condition and
4659 the next instruction is ifx with the same operand
4660 and live to of the operand is upto the ifx only then */
4662 ic->next->op == IFX &&
4663 IC_COND (ic->next)->key == op->key &&
4664 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4669 /*-----------------------------------------------------------------*/
4670 /* genAndOp - for && operation */
4671 /*-----------------------------------------------------------------*/
4673 genAndOp (iCode * ic)
4675 operand *left, *right, *result;
4678 D (emitcode (";", "genAndOp ");
4681 /* note here that && operations that are in an
4682 if statement are taken away by backPatchLabels
4683 only those used in arthmetic operations remain */
4685 AOP_SET_LOCALS (ic);
4687 /* if both are bit variables */
4688 if (AOP_TYPE (left) == AOP_CRY &&
4689 AOP_TYPE (right) == AOP_CRY)
4691 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4692 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4697 tlbl = newiTempLabel (NULL);
4699 emitcode ("jz", "%05d$", tlbl->key + 100);
4701 emitcode ("", "%05d$:", tlbl->key + 100);
4705 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4707 freeAsmop (result, NULL, ic, TRUE);
4711 /*-----------------------------------------------------------------*/
4712 /* genOrOp - for || operation */
4713 /*-----------------------------------------------------------------*/
4715 genOrOp (iCode * ic)
4717 operand *left, *right, *result;
4720 D (emitcode (";", "genOrOp ");
4723 /* note here that || operations that are in an
4724 if statement are taken away by backPatchLabels
4725 only those used in arthmetic operations remain */
4727 AOP_SET_LOCALS (ic);
4729 /* if both are bit variables */
4730 if (AOP_TYPE (left) == AOP_CRY &&
4731 AOP_TYPE (right) == AOP_CRY)
4733 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4734 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4739 tlbl = newiTempLabel (NULL);
4741 emitcode ("jnz", "%05d$", tlbl->key + 100);
4743 emitcode ("", "%05d$:", tlbl->key + 100);
4747 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4749 freeAsmop (result, NULL, ic, TRUE);
4752 /*-----------------------------------------------------------------*/
4753 /* isLiteralBit - test if lit == 2^n */
4754 /*-----------------------------------------------------------------*/
4756 isLiteralBit (unsigned long lit)
4758 unsigned long pw[32] =
4759 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4760 0x100L, 0x200L, 0x400L, 0x800L,
4761 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4762 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4763 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4764 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4765 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4768 for (idx = 0; idx < 32; idx++)
4774 /*-----------------------------------------------------------------*/
4775 /* continueIfTrue - */
4776 /*-----------------------------------------------------------------*/
4778 continueIfTrue (iCode * ic)
4781 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4785 /*-----------------------------------------------------------------*/
4787 /*-----------------------------------------------------------------*/
4789 jumpIfTrue (iCode * ic)
4792 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4796 /*-----------------------------------------------------------------*/
4797 /* jmpTrueOrFalse - */
4798 /*-----------------------------------------------------------------*/
4800 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4802 // ugly but optimized by peephole
4805 symbol *nlbl = newiTempLabel (NULL);
4806 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4807 emitcode ("", "%05d$:", tlbl->key + 100);
4808 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4809 emitcode ("", "%05d$:", nlbl->key + 100);
4813 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4814 emitcode ("", "%05d$:", tlbl->key + 100);
4819 /*-----------------------------------------------------------------*/
4820 /* genAnd - code for and */
4821 /*-----------------------------------------------------------------*/
4823 genAnd (iCode * ic, iCode * ifx)
4825 operand *left, *right, *result;
4826 int size, offset = 0;
4827 unsigned long lit = 0L;
4831 D (emitcode (";", "genAnd ");
4835 AOP_SET_LOCALS (ic);
4838 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4840 AOP_TYPE (left), AOP_TYPE (right));
4841 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4843 AOP_SIZE (left), AOP_SIZE (right));
4846 /* if left is a literal & right is not then exchange them */
4847 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4848 AOP_NEEDSACC (left))
4850 operand *tmp = right;
4855 /* if result = right then exchange them */
4856 if (sameRegs (AOP (result), AOP (right)))
4858 operand *tmp = right;
4863 /* if right is bit then exchange them */
4864 if (AOP_TYPE (right) == AOP_CRY &&
4865 AOP_TYPE (left) != AOP_CRY)
4867 operand *tmp = right;
4871 if (AOP_TYPE (right) == AOP_LIT)
4872 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4874 size = AOP_SIZE (result);
4877 // result = bit & yy;
4878 if (AOP_TYPE (left) == AOP_CRY)
4880 // c = bit & literal;
4881 if (AOP_TYPE (right) == AOP_LIT)
4885 if (size && sameRegs (AOP (result), AOP (left)))
4888 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4893 if (size && (AOP_TYPE (result) == AOP_CRY))
4895 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4898 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4903 emitcode ("clr", "c");
4908 if (AOP_TYPE (right) == AOP_CRY)
4911 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4912 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4917 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4919 emitcode ("rrc", "a");
4920 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4928 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4929 genIfxJump (ifx, "c");
4933 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4934 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4935 if ((AOP_TYPE (right) == AOP_LIT) &&
4936 (AOP_TYPE (result) == AOP_CRY) &&
4937 (AOP_TYPE (left) != AOP_CRY))
4939 int posbit = isLiteralBit (lit);
4944 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4947 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4953 sprintf (buffer, "acc.%d", posbit & 0x07);
4954 genIfxJump (ifx, buffer);
4961 symbol *tlbl = newiTempLabel (NULL);
4962 int sizel = AOP_SIZE (left);
4964 emitcode ("setb", "c");
4967 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4969 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4971 if ((posbit = isLiteralBit (bytelit)) != 0)
4972 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4975 if (bytelit != 0x0FFL)
4976 emitcode ("anl", "a,%s",
4977 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4978 emitcode ("jnz", "%05d$", tlbl->key + 100);
4983 // bit = left & literal
4986 emitcode ("clr", "c");
4987 emitcode ("", "%05d$:", tlbl->key + 100);
4989 // if(left & literal)
4993 jmpTrueOrFalse (ifx, tlbl);
5001 /* if left is same as result */
5002 if (sameRegs (AOP (result), AOP (left)))
5004 for (; size--; offset++)
5006 if (AOP_TYPE (right) == AOP_LIT)
5008 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5010 else if (bytelit == 0)
5011 aopPut (AOP (result), zero, offset);
5012 else if (IS_AOP_PREG (result))
5014 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5015 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5016 aopPut (AOP (result), "a", offset);
5019 emitcode ("anl", "%s,%s",
5020 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5021 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5025 if (AOP_TYPE (left) == AOP_ACC)
5026 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5029 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5030 if (IS_AOP_PREG (result))
5032 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5033 aopPut (AOP (result), "a", offset);
5037 emitcode ("anl", "%s,a",
5038 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5045 // left & result in different registers
5046 if (AOP_TYPE (result) == AOP_CRY)
5049 // if(size), result in bit
5050 // if(!size && ifx), conditional oper: if(left & right)
5051 symbol *tlbl = newiTempLabel (NULL);
5052 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5054 emitcode ("setb", "c");
5057 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5058 emitcode ("anl", "a,%s",
5059 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5060 emitcode ("jnz", "%05d$", tlbl->key + 100);
5066 emitcode ("", "%05d$:", tlbl->key + 100);
5070 jmpTrueOrFalse (ifx, tlbl);
5074 for (; (size--); offset++)
5077 // result = left & right
5078 if (AOP_TYPE (right) == AOP_LIT)
5080 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5082 aopPut (AOP (result),
5083 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5087 else if (bytelit == 0)
5089 aopPut (AOP (result), zero, offset);
5092 D (emitcode (";", "better literal AND.");
5094 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5095 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5096 FALSE, FALSE, FALSE));
5101 // faster than result <- left, anl result,right
5102 // and better if result is SFR
5103 if (AOP_TYPE (left) == AOP_ACC)
5105 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5106 FALSE, FALSE, FALSE));
5110 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5111 emitcode ("anl", "a,%s",
5112 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5115 aopPut (AOP (result), "a", offset);
5121 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5123 freeAsmop (result, NULL, ic, TRUE);
5126 /*-----------------------------------------------------------------*/
5127 /* genOr - code for or */
5128 /*-----------------------------------------------------------------*/
5130 genOr (iCode * ic, iCode * ifx)
5132 operand *left, *right, *result;
5133 int size, offset = 0;
5134 unsigned long lit = 0L;
5136 D (emitcode (";", "genOr ");
5140 AOP_SET_LOCALS (ic);
5143 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5145 AOP_TYPE (left), AOP_TYPE (right));
5146 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5148 AOP_SIZE (left), AOP_SIZE (right));
5151 /* if left is a literal & right is not then exchange them */
5152 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5153 AOP_NEEDSACC (left))
5155 operand *tmp = right;
5160 /* if result = right then exchange them */
5161 if (sameRegs (AOP (result), AOP (right)))
5163 operand *tmp = right;
5168 /* if right is bit then exchange them */
5169 if (AOP_TYPE (right) == AOP_CRY &&
5170 AOP_TYPE (left) != AOP_CRY)
5172 operand *tmp = right;
5176 if (AOP_TYPE (right) == AOP_LIT)
5177 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5179 size = AOP_SIZE (result);
5183 if (AOP_TYPE (left) == AOP_CRY)
5185 if (AOP_TYPE (right) == AOP_LIT)
5187 // c = bit & literal;
5190 // lit != 0 => result = 1
5191 if (AOP_TYPE (result) == AOP_CRY)
5194 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5196 continueIfTrue (ifx);
5199 emitcode ("setb", "c");
5203 // lit == 0 => result = left
5204 if (size && sameRegs (AOP (result), AOP (left)))
5206 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5211 if (AOP_TYPE (right) == AOP_CRY)
5214 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5215 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5220 symbol *tlbl = newiTempLabel (NULL);
5221 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5222 emitcode ("setb", "c");
5223 emitcode ("jb", "%s,%05d$",
5224 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5226 emitcode ("jnz", "%05d$", tlbl->key + 100);
5227 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5229 jmpTrueOrFalse (ifx, tlbl);
5235 emitcode ("", "%05d$:", tlbl->key + 100);
5244 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5245 genIfxJump (ifx, "c");
5249 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5250 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5251 if ((AOP_TYPE (right) == AOP_LIT) &&
5252 (AOP_TYPE (result) == AOP_CRY) &&
5253 (AOP_TYPE (left) != AOP_CRY))
5259 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5261 continueIfTrue (ifx);
5266 // lit = 0, result = boolean(left)
5268 emitcode ("setb", "c");
5272 symbol *tlbl = newiTempLabel (NULL);
5273 emitcode ("jnz", "%05d$", tlbl->key + 100);
5275 emitcode ("", "%05d$:", tlbl->key + 100);
5279 genIfxJump (ifx, "a");
5287 /* if left is same as result */
5288 if (sameRegs (AOP (result), AOP (left)))
5290 for (; size--; offset++)
5292 if (AOP_TYPE (right) == AOP_LIT)
5294 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5300 if (IS_AOP_PREG (left))
5302 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5303 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5304 aopPut (AOP (result), "a", offset);
5308 emitcode ("orl", "%s,%s",
5309 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5310 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5316 if (AOP_TYPE (left) == AOP_ACC)
5318 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5322 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5323 if (IS_AOP_PREG (left))
5325 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5326 aopPut (AOP (result), "a", offset);
5330 emitcode ("orl", "%s,a",
5331 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5339 // left & result in different registers
5340 if (AOP_TYPE (result) == AOP_CRY)
5343 // if(size), result in bit
5344 // if(!size && ifx), conditional oper: if(left | right)
5345 symbol *tlbl = newiTempLabel (NULL);
5346 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5348 emitcode ("setb", "c");
5351 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5352 emitcode ("orl", "a,%s",
5353 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5354 emitcode ("jnz", "%05d$", tlbl->key + 100);
5360 emitcode ("", "%05d$:", tlbl->key + 100);
5364 jmpTrueOrFalse (ifx, tlbl);
5368 for (; (size--); offset++)
5371 // result = left & right
5372 if (AOP_TYPE (right) == AOP_LIT)
5374 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5376 aopPut (AOP (result),
5377 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5381 D (emitcode (";", "better literal OR.");
5383 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5384 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5385 FALSE, FALSE, FALSE));
5390 // faster than result <- left, anl result,right
5391 // and better if result is SFR
5392 if (AOP_TYPE (left) == AOP_ACC)
5394 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5395 FALSE, FALSE, FALSE));
5399 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5400 emitcode ("orl", "a,%s",
5401 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5404 aopPut (AOP (result), "a", offset);
5410 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5411 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5412 freeAsmop (result, NULL, ic, TRUE);
5415 /*-----------------------------------------------------------------*/
5416 /* genXor - code for xclusive or */
5417 /*-----------------------------------------------------------------*/
5419 genXor (iCode * ic, iCode * ifx)
5421 operand *left, *right, *result;
5422 int size, offset = 0;
5423 unsigned long lit = 0L;
5425 D (emitcode (";", "genXor ");
5429 AOP_SET_LOCALS (ic);
5432 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5434 AOP_TYPE (left), AOP_TYPE (right));
5435 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5437 AOP_SIZE (left), AOP_SIZE (right));
5440 /* if left is a literal & right is not ||
5441 if left needs acc & right does not */
5442 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5443 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5445 operand *tmp = right;
5450 /* if result = right then exchange them */
5451 if (sameRegs (AOP (result), AOP (right)))
5453 operand *tmp = right;
5458 /* if right is bit then exchange them */
5459 if (AOP_TYPE (right) == AOP_CRY &&
5460 AOP_TYPE (left) != AOP_CRY)
5462 operand *tmp = right;
5466 if (AOP_TYPE (right) == AOP_LIT)
5467 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5469 size = AOP_SIZE (result);
5473 if (AOP_TYPE (left) == AOP_CRY)
5475 if (AOP_TYPE (right) == AOP_LIT)
5477 // c = bit & literal;
5480 // lit>>1 != 0 => result = 1
5481 if (AOP_TYPE (result) == AOP_CRY)
5484 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5486 continueIfTrue (ifx);
5489 emitcode ("setb", "c");
5496 // lit == 0, result = left
5497 if (size && sameRegs (AOP (result), AOP (left)))
5499 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5503 // lit == 1, result = not(left)
5504 if (size && sameRegs (AOP (result), AOP (left)))
5506 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5511 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5512 emitcode ("cpl", "c");
5521 symbol *tlbl = newiTempLabel (NULL);
5522 if (AOP_TYPE (right) == AOP_CRY)
5525 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5529 int sizer = AOP_SIZE (right);
5531 // if val>>1 != 0, result = 1
5532 emitcode ("setb", "c");
5535 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5537 // test the msb of the lsb
5538 emitcode ("anl", "a,#0xfe");
5539 emitcode ("jnz", "%05d$", tlbl->key + 100);
5543 emitcode ("rrc", "a");
5545 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5546 emitcode ("cpl", "c");
5547 emitcode ("", "%05d$:", (tlbl->key + 100));
5554 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5555 genIfxJump (ifx, "c");
5559 if (sameRegs (AOP (result), AOP (left)))
5561 /* if left is same as result */
5562 for (; size--; offset++)
5564 if (AOP_TYPE (right) == AOP_LIT)
5566 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5568 else if (IS_AOP_PREG (left))
5570 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5571 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5572 aopPut (AOP (result), "a", offset);
5575 emitcode ("xrl", "%s,%s",
5576 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5577 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5581 if (AOP_TYPE (left) == AOP_ACC)
5582 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5585 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5586 if (IS_AOP_PREG (left))
5588 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5589 aopPut (AOP (result), "a", offset);
5592 emitcode ("xrl", "%s,a",
5593 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5600 // left & result in different registers
5601 if (AOP_TYPE (result) == AOP_CRY)
5604 // if(size), result in bit
5605 // if(!size && ifx), conditional oper: if(left ^ right)
5606 symbol *tlbl = newiTempLabel (NULL);
5607 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5609 emitcode ("setb", "c");
5612 if ((AOP_TYPE (right) == AOP_LIT) &&
5613 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5615 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5619 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5620 emitcode ("xrl", "a,%s",
5621 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5623 emitcode ("jnz", "%05d$", tlbl->key + 100);
5629 emitcode ("", "%05d$:", tlbl->key + 100);
5633 jmpTrueOrFalse (ifx, tlbl);
5636 for (; (size--); offset++)
5639 // result = left & right
5640 if (AOP_TYPE (right) == AOP_LIT)
5642 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5644 aopPut (AOP (result),
5645 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5649 D (emitcode (";", "better literal XOR.");
5651 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5652 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5653 FALSE, FALSE, FALSE));
5657 // faster than result <- left, anl result,right
5658 // and better if result is SFR
5659 if (AOP_TYPE (left) == AOP_ACC)
5661 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5662 FALSE, FALSE, FALSE));
5666 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5667 emitcode ("xrl", "a,%s",
5668 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5671 aopPut (AOP (result), "a", offset);
5676 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5677 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5678 freeAsmop (result, NULL, ic, TRUE);
5681 /*-----------------------------------------------------------------*/
5682 /* genInline - write the inline code out */
5683 /*-----------------------------------------------------------------*/
5685 genInline (iCode * ic)
5687 char buffer[MAX_INLINEASM];
5691 D (emitcode (";", "genInline ");
5694 _G.inLine += (!options.asmpeep);
5695 strcpy (buffer, IC_INLINE (ic));
5697 /* emit each line as a code */
5722 /* emitcode("",buffer); */
5723 _G.inLine -= (!options.asmpeep);
5726 /*-----------------------------------------------------------------*/
5727 /* genRRC - rotate right with carry */
5728 /*-----------------------------------------------------------------*/
5732 operand *left, *result;
5733 int size, offset = 0;
5736 D (emitcode (";", "genRRC ");
5739 /* rotate right with carry */
5740 left = IC_LEFT (ic);
5741 result = IC_RESULT (ic);
5742 aopOp (left, ic, FALSE, FALSE);
5743 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5745 /* move it to the result */
5746 size = AOP_SIZE (result);
5750 _startLazyDPSEvaluation ();
5753 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5755 emitcode ("rrc", "a");
5756 if (AOP_SIZE (result) > 1)
5757 aopPut (AOP (result), "a", offset--);
5759 _endLazyDPSEvaluation ();
5761 /* now we need to put the carry into the
5762 highest order byte of the result */
5763 if (AOP_SIZE (result) > 1)
5765 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5768 emitcode ("mov", "acc.7,c");
5769 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5770 freeAsmop (left, NULL, ic, TRUE);
5771 freeAsmop (result, NULL, ic, TRUE);
5774 /*-----------------------------------------------------------------*/
5775 /* genRLC - generate code for rotate left with carry */
5776 /*-----------------------------------------------------------------*/
5780 operand *left, *result;
5781 int size, offset = 0;
5784 D (emitcode (";", "genRLC ");
5787 /* rotate right with carry */
5788 left = IC_LEFT (ic);
5789 result = IC_RESULT (ic);
5790 aopOp (left, ic, FALSE, FALSE);
5791 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5793 /* move it to the result */
5794 size = AOP_SIZE (result);
5798 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5800 emitcode ("add", "a,acc");
5801 if (AOP_SIZE (result) > 1)
5803 aopPut (AOP (result), "a", offset++);
5806 _startLazyDPSEvaluation ();
5809 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5811 emitcode ("rlc", "a");
5812 if (AOP_SIZE (result) > 1)
5813 aopPut (AOP (result), "a", offset++);
5815 _endLazyDPSEvaluation ();
5817 /* now we need to put the carry into the
5818 highest order byte of the result */
5819 if (AOP_SIZE (result) > 1)
5821 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5824 emitcode ("mov", "acc.0,c");
5825 aopPut (AOP (result), "a", 0);
5826 freeAsmop (left, NULL, ic, TRUE);
5827 freeAsmop (result, NULL, ic, TRUE);
5830 /*-----------------------------------------------------------------*/
5831 /* genGetHbit - generates code get highest order bit */
5832 /*-----------------------------------------------------------------*/
5834 genGetHbit (iCode * ic)
5836 operand *left, *result;
5837 left = IC_LEFT (ic);
5838 result = IC_RESULT (ic);
5839 aopOp (left, ic, FALSE, FALSE);
5840 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5842 D (emitcode (";", "genGetHbit ");
5845 /* get the highest order byte into a */
5846 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5847 if (AOP_TYPE (result) == AOP_CRY)
5849 emitcode ("rlc", "a");
5854 emitcode ("rl", "a");
5855 emitcode ("anl", "a,#0x01");
5860 freeAsmop (left, NULL, ic, TRUE);
5861 freeAsmop (result, NULL, ic, TRUE);
5864 /*-----------------------------------------------------------------*/
5865 /* AccRol - rotate left accumulator by known count */
5866 /*-----------------------------------------------------------------*/
5868 AccRol (int shCount)
5870 shCount &= 0x0007; // shCount : 0..7
5877 emitcode ("rl", "a");
5880 emitcode ("rl", "a");
5881 emitcode ("rl", "a");
5884 emitcode ("swap", "a");
5885 emitcode ("rr", "a");
5888 emitcode ("swap", "a");
5891 emitcode ("swap", "a");
5892 emitcode ("rl", "a");
5895 emitcode ("rr", "a");
5896 emitcode ("rr", "a");
5899 emitcode ("rr", "a");
5904 /*-----------------------------------------------------------------*/
5905 /* AccLsh - left shift accumulator by known count */
5906 /*-----------------------------------------------------------------*/
5908 AccLsh (int shCount)
5913 emitcode ("add", "a,acc");
5914 else if (shCount == 2)
5916 emitcode ("add", "a,acc");
5917 emitcode ("add", "a,acc");
5921 /* rotate left accumulator */
5923 /* and kill the lower order bits */
5924 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5929 /*-----------------------------------------------------------------*/
5930 /* AccRsh - right shift accumulator by known count */
5931 /*-----------------------------------------------------------------*/
5933 AccRsh (int shCount)
5940 emitcode ("rrc", "a");
5944 /* rotate right accumulator */
5945 AccRol (8 - shCount);
5946 /* and kill the higher order bits */
5947 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5954 /*-----------------------------------------------------------------*/
5955 /* AccSRsh - signed right shift accumulator by known count */
5956 /*-----------------------------------------------------------------*/
5958 AccSRsh (int shCount)
5965 emitcode ("mov", "c,acc.7");
5966 emitcode ("rrc", "a");
5968 else if (shCount == 2)
5970 emitcode ("mov", "c,acc.7");
5971 emitcode ("rrc", "a");
5972 emitcode ("mov", "c,acc.7");
5973 emitcode ("rrc", "a");
5977 tlbl = newiTempLabel (NULL);
5978 /* rotate right accumulator */
5979 AccRol (8 - shCount);
5980 /* and kill the higher order bits */
5981 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5982 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5983 emitcode ("orl", "a,#0x%02x",
5984 (unsigned char) ~SRMask[shCount]);
5985 emitcode ("", "%05d$:", tlbl->key + 100);
5993 /*-----------------------------------------------------------------*/
5994 /* shiftR1Left2Result - shift right one byte from left to result */
5995 /*-----------------------------------------------------------------*/
5997 shiftR1Left2Result (operand * left, int offl,
5998 operand * result, int offr,
5999 int shCount, int sign)
6001 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6002 /* shift right accumulator */
6007 aopPut (AOP (result), "a", offr);
6013 /*-----------------------------------------------------------------*/
6014 /* shiftL1Left2Result - shift left one byte from left to result */
6015 /*-----------------------------------------------------------------*/
6017 shiftL1Left2Result (operand * left, int offl,
6018 operand * result, int offr, int shCount)
6021 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6023 /* shift left accumulator */
6025 aopPut (AOP (result), "a", offr);
6031 /*-----------------------------------------------------------------*/
6032 /* movLeft2Result - move byte from left to result */
6033 /*-----------------------------------------------------------------*/
6035 movLeft2Result (operand * left, int offl,
6036 operand * result, int offr, int sign)
6039 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6041 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6043 if (*l == '@' && (IS_AOP_PREG (result)))
6045 emitcode ("mov", "a,%s", l);
6046 aopPut (AOP (result), "a", offr);
6051 aopPut (AOP (result), l, offr);
6054 /* MSB sign in acc.7 ! */
6055 if (getDataSize (left) == offl + 1)
6057 emitcode ("mov", "a,%s", l);
6058 aopPut (AOP (result), "a", offr);
6068 /*-----------------------------------------------------------------*/
6069 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6070 /*-----------------------------------------------------------------*/
6074 emitcode ("rrc", "a");
6075 emitcode ("xch", "a,%s", x);
6076 emitcode ("rrc", "a");
6077 emitcode ("xch", "a,%s", x);
6083 /*-----------------------------------------------------------------*/
6084 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6085 /*-----------------------------------------------------------------*/
6089 emitcode ("xch", "a,%s", x);
6090 emitcode ("rlc", "a");
6091 emitcode ("xch", "a,%s", x);
6092 emitcode ("rlc", "a");
6098 /*-----------------------------------------------------------------*/
6099 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6100 /*-----------------------------------------------------------------*/
6104 emitcode ("xch", "a,%s", x);
6105 emitcode ("add", "a,acc");
6106 emitcode ("xch", "a,%s", x);
6107 emitcode ("rlc", "a");
6113 /*-----------------------------------------------------------------*/
6114 /* AccAXLsh - left shift a:x by known count (0..7) */
6115 /*-----------------------------------------------------------------*/
6117 AccAXLsh (char *x, int shCount)
6132 case 5: // AAAAABBB:CCCCCDDD
6134 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6136 emitcode ("anl", "a,#0x%02x",
6137 SLMask[shCount]); // BBB00000:CCCCCDDD
6139 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6141 AccRol (shCount); // DDDCCCCC:BBB00000
6143 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6145 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6147 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6149 emitcode ("anl", "a,#0x%02x",
6150 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6152 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6154 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6157 case 6: // AAAAAABB:CCCCCCDD
6159 emitcode ("anl", "a,#0x%02x",
6160 SRMask[shCount]); // 000000BB:CCCCCCDD
6162 emitcode ("mov", "c,acc.0"); // c = B
6164 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6166 AccAXRrl1 (x); // BCCCCCCD:D000000B
6168 AccAXRrl1 (x); // BBCCCCCC:DD000000
6171 case 7: // a:x <<= 7
6173 emitcode ("anl", "a,#0x%02x",
6174 SRMask[shCount]); // 0000000B:CCCCCCCD
6176 emitcode ("mov", "c,acc.0"); // c = B
6178 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6180 AccAXRrl1 (x); // BCCCCCCC:D0000000
6191 /*-----------------------------------------------------------------*/
6192 /* AccAXRsh - right shift a:x known count (0..7) */
6193 /*-----------------------------------------------------------------*/
6195 AccAXRsh (char *x, int shCount)
6203 AccAXRrl1 (x); // 0->a:x
6208 AccAXRrl1 (x); // 0->a:x
6211 AccAXRrl1 (x); // 0->a:x
6216 case 5: // AAAAABBB:CCCCCDDD = a:x
6218 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6220 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6222 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6224 emitcode ("anl", "a,#0x%02x",
6225 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6227 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6229 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6231 emitcode ("anl", "a,#0x%02x",
6232 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6234 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6236 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6238 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6241 case 6: // AABBBBBB:CCDDDDDD
6243 emitcode ("mov", "c,acc.7");
6244 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6246 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6248 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6250 emitcode ("anl", "a,#0x%02x",
6251 SRMask[shCount]); // 000000AA:BBBBBBCC
6254 case 7: // ABBBBBBB:CDDDDDDD
6256 emitcode ("mov", "c,acc.7"); // c = A
6258 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6260 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6262 emitcode ("anl", "a,#0x%02x",
6263 SRMask[shCount]); // 0000000A:BBBBBBBC
6274 /*-----------------------------------------------------------------*/
6275 /* AccAXRshS - right shift signed a:x known count (0..7) */
6276 /*-----------------------------------------------------------------*/
6278 AccAXRshS (char *x, int shCount)
6286 emitcode ("mov", "c,acc.7");
6287 AccAXRrl1 (x); // s->a:x
6291 emitcode ("mov", "c,acc.7");
6292 AccAXRrl1 (x); // s->a:x
6294 emitcode ("mov", "c,acc.7");
6295 AccAXRrl1 (x); // s->a:x
6300 case 5: // AAAAABBB:CCCCCDDD = a:x
6302 tlbl = newiTempLabel (NULL);
6303 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6305 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6307 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6309 emitcode ("anl", "a,#0x%02x",
6310 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6312 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6314 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6316 emitcode ("anl", "a,#0x%02x",
6317 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6319 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6321 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6323 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6325 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6326 emitcode ("orl", "a,#0x%02x",
6327 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6329 emitcode ("", "%05d$:", tlbl->key + 100);
6330 break; // SSSSAAAA:BBBCCCCC
6332 case 6: // AABBBBBB:CCDDDDDD
6334 tlbl = newiTempLabel (NULL);
6335 emitcode ("mov", "c,acc.7");
6336 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6338 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6340 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6342 emitcode ("anl", "a,#0x%02x",
6343 SRMask[shCount]); // 000000AA:BBBBBBCC
6345 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6346 emitcode ("orl", "a,#0x%02x",
6347 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6349 emitcode ("", "%05d$:", tlbl->key + 100);
6351 case 7: // ABBBBBBB:CDDDDDDD
6353 tlbl = newiTempLabel (NULL);
6354 emitcode ("mov", "c,acc.7"); // c = A
6356 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6358 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6360 emitcode ("anl", "a,#0x%02x",
6361 SRMask[shCount]); // 0000000A:BBBBBBBC
6363 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6364 emitcode ("orl", "a,#0x%02x",
6365 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6367 emitcode ("", "%05d$:", tlbl->key + 100);
6377 /*-----------------------------------------------------------------*/
6378 /* shiftL2Left2Result - shift left two bytes from left to result */
6379 /*-----------------------------------------------------------------*/
6381 shiftL2Left2Result (operand * left, int offl,
6382 operand * result, int offr, int shCount)
6384 if (sameRegs (AOP (result), AOP (left)) &&
6385 ((offl + MSB16) == offr))
6387 /* don't crash result[offr] */
6388 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6389 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6393 movLeft2Result (left, offl, result, offr, 0);
6394 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6396 /* ax << shCount (x = lsb(result)) */
6397 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6398 aopPut (AOP (result), "a", offr + MSB16);
6404 /*-----------------------------------------------------------------*/
6405 /* shiftR2Left2Result - shift right two bytes from left to result */
6406 /*-----------------------------------------------------------------*/
6408 shiftR2Left2Result (operand * left, int offl,
6409 operand * result, int offr,
6410 int shCount, int sign)
6412 if (sameRegs (AOP (result), AOP (left)) &&
6413 ((offl + MSB16) == offr))
6415 /* don't crash result[offr] */
6416 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6417 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6421 movLeft2Result (left, offl, result, offr, 0);
6422 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6424 /* a:x >> shCount (x = lsb(result)) */
6426 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6428 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6429 if (getDataSize (result) > 1)
6430 aopPut (AOP (result), "a", offr + MSB16);
6436 /*-----------------------------------------------------------------*/
6437 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6438 /*-----------------------------------------------------------------*/
6440 shiftLLeftOrResult (operand * left, int offl,
6441 operand * result, int offr, int shCount)
6443 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6444 /* shift left accumulator */
6446 /* or with result */
6447 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6448 /* back to result */
6449 aopPut (AOP (result), "a", offr);
6455 /*-----------------------------------------------------------------*/
6456 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6457 /*-----------------------------------------------------------------*/
6459 shiftRLeftOrResult (operand * left, int offl,
6460 operand * result, int offr, int shCount)
6462 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6463 /* shift right accumulator */
6465 /* or with result */
6466 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6467 /* back to result */
6468 aopPut (AOP (result), "a", offr);
6474 /*-----------------------------------------------------------------*/
6475 /* genlshOne - left shift a one byte quantity by known count */
6476 /*-----------------------------------------------------------------*/
6478 genlshOne (operand * result, operand * left, int shCount)
6480 D (emitcode (";", "genlshOne ");
6482 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6488 /*-----------------------------------------------------------------*/
6489 /* genlshTwo - left shift two bytes by known amount != 0 */
6490 /*-----------------------------------------------------------------*/
6492 genlshTwo (operand * result, operand * left, int shCount)
6496 D (emitcode (";", "genlshTwo ");
6499 size = getDataSize (result);
6501 /* if shCount >= 8 */
6509 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6511 movLeft2Result (left, LSB, result, MSB16, 0);
6513 aopPut (AOP (result), zero, LSB);
6516 /* 1 <= shCount <= 7 */
6520 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6522 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6529 /*-----------------------------------------------------------------*/
6530 /* shiftLLong - shift left one long from left to result */
6531 /* offl = LSB or MSB16 */
6532 /*-----------------------------------------------------------------*/
6534 shiftLLong (operand * left, operand * result, int offr)
6537 int size = AOP_SIZE (result);
6539 if (size >= LSB + offr)
6541 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6543 emitcode ("add", "a,acc");
6544 if (sameRegs (AOP (left), AOP (result)) &&
6545 size >= MSB16 + offr && offr != LSB)
6546 emitcode ("xch", "a,%s",
6547 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6549 aopPut (AOP (result), "a", LSB + offr);
6552 if (size >= MSB16 + offr)
6554 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6556 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6559 emitcode ("rlc", "a");
6560 if (sameRegs (AOP (left), AOP (result)) &&
6561 size >= MSB24 + offr && offr != LSB)
6562 emitcode ("xch", "a,%s",
6563 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6565 aopPut (AOP (result), "a", MSB16 + offr);
6568 if (size >= MSB24 + offr)
6570 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6572 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6575 emitcode ("rlc", "a");
6576 if (sameRegs (AOP (left), AOP (result)) &&
6577 size >= MSB32 + offr && offr != LSB)
6578 emitcode ("xch", "a,%s",
6579 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6581 aopPut (AOP (result), "a", MSB24 + offr);
6584 if (size > MSB32 + offr)
6586 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6588 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6591 emitcode ("rlc", "a");
6592 aopPut (AOP (result), "a", MSB32 + offr);
6595 aopPut (AOP (result), zero, LSB);
6601 /*-----------------------------------------------------------------*/
6602 /* genlshFour - shift four byte by a known amount != 0 */
6603 /*-----------------------------------------------------------------*/
6605 genlshFour (operand * result, operand * left, int shCount)
6609 D (emitcode (";", "genlshFour ");
6612 size = AOP_SIZE (result);
6614 /* if shifting more that 3 bytes */
6619 /* lowest order of left goes to the highest
6620 order of the destination */
6621 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6623 movLeft2Result (left, LSB, result, MSB32, 0);
6624 aopPut (AOP (result), zero, LSB);
6625 aopPut (AOP (result), zero, MSB16);
6626 aopPut (AOP (result), zero, MSB32);
6630 /* more than two bytes */
6631 else if (shCount >= 16)
6633 /* lower order two bytes goes to higher order two bytes */
6635 /* if some more remaining */
6637 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6640 movLeft2Result (left, MSB16, result, MSB32, 0);
6641 movLeft2Result (left, LSB, result, MSB24, 0);
6643 aopPut (AOP (result), zero, MSB16);
6644 aopPut (AOP (result), zero, LSB);
6648 /* if more than 1 byte */
6649 else if (shCount >= 8)
6651 /* lower order three bytes goes to higher order three bytes */
6656 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6658 movLeft2Result (left, LSB, result, MSB16, 0);
6664 movLeft2Result (left, MSB24, result, MSB32, 0);
6665 movLeft2Result (left, MSB16, result, MSB24, 0);
6666 movLeft2Result (left, LSB, result, MSB16, 0);
6667 aopPut (AOP (result), zero, LSB);
6669 else if (shCount == 1)
6670 shiftLLong (left, result, MSB16);
6673 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6674 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6675 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6676 aopPut (AOP (result), zero, LSB);
6681 /* 1 <= shCount <= 7 */
6682 else if (shCount <= 2)
6684 shiftLLong (left, result, LSB);
6686 shiftLLong (result, result, LSB);
6688 /* 3 <= shCount <= 7, optimize */
6691 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6692 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6693 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6700 /*-----------------------------------------------------------------*/
6701 /* genLeftShiftLiteral - left shifting by known count */
6702 /*-----------------------------------------------------------------*/
6704 genLeftShiftLiteral (operand * left,
6709 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6712 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6715 freeAsmop (right, NULL, ic, TRUE);
6717 aopOp (left, ic, FALSE, FALSE);
6718 aopOp (result, ic, FALSE, TRUE);
6720 size = getSize (operandType (result));
6723 emitcode ("; shift left ", "result %d, left %d", size,
6727 /* I suppose that the left size >= result size */
6732 movLeft2Result (left, size, result, size, 0);
6736 else if (shCount >= (size * 8))
6738 aopPut (AOP (result), zero, size);
6744 genlshOne (result, left, shCount);
6748 case 3: /* bug: this is for generic pointers, I bet. */
6749 genlshTwo (result, left, shCount);
6753 genlshFour (result, left, shCount);
6757 freeAsmop (left, NULL, ic, TRUE);
6758 freeAsmop (result, NULL, ic, TRUE);
6762 /*-----------------------------------------------------------------*/
6763 /* genLeftShift - generates code for left shifting */
6764 /*-----------------------------------------------------------------*/
6766 genLeftShift (iCode * ic)
6768 operand *left, *right, *result;
6771 symbol *tlbl, *tlbl1;
6773 D (emitcode (";", "genLeftShift ");
6776 right = IC_RIGHT (ic);
6777 left = IC_LEFT (ic);
6778 result = IC_RESULT (ic);
6780 aopOp (right, ic, FALSE, FALSE);
6783 /* if the shift count is known then do it
6784 as efficiently as possible */
6785 if (AOP_TYPE (right) == AOP_LIT)
6787 genLeftShiftLiteral (left, right, result, ic);
6792 /* shift count is unknown then we have to form
6793 a loop get the loop count in B : Note: we take
6794 only the lower order byte since shifting
6795 more that 32 bits make no sense anyway, ( the
6796 largest size of an object can be only 32 bits ) */
6798 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6799 emitcode ("inc", "b");
6800 freeAsmop (right, NULL, ic, TRUE);
6801 aopOp (left, ic, FALSE, FALSE);
6802 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6804 /* now move the left to the result if they are not the
6806 if (!sameRegs (AOP (left), AOP (result)) &&
6807 AOP_SIZE (result) > 1)
6810 size = AOP_SIZE (result);
6812 _startLazyDPSEvaluation ();
6815 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6816 if (*l == '@' && (IS_AOP_PREG (result)))
6819 emitcode ("mov", "a,%s", l);
6820 aopPut (AOP (result), "a", offset);
6823 aopPut (AOP (result), l, offset);
6826 _endLazyDPSEvaluation ();
6829 tlbl = newiTempLabel (NULL);
6830 size = AOP_SIZE (result);
6832 tlbl1 = newiTempLabel (NULL);
6834 /* if it is only one byte then */
6837 symbol *tlbl1 = newiTempLabel (NULL);
6839 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6841 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6842 emitcode ("", "%05d$:", tlbl->key + 100);
6843 emitcode ("add", "a,acc");
6844 emitcode ("", "%05d$:", tlbl1->key + 100);
6845 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6846 aopPut (AOP (result), "a", 0);
6850 reAdjustPreg (AOP (result));
6852 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6853 emitcode ("", "%05d$:", tlbl->key + 100);
6854 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6856 emitcode ("add", "a,acc");
6857 aopPut (AOP (result), "a", offset++);
6858 _startLazyDPSEvaluation ();
6861 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6863 emitcode ("rlc", "a");
6864 aopPut (AOP (result), "a", offset++);
6866 _endLazyDPSEvaluation ();
6867 reAdjustPreg (AOP (result));
6869 emitcode ("", "%05d$:", tlbl1->key + 100);
6870 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6872 freeAsmop (left, NULL, ic, TRUE);
6873 freeAsmop (result, NULL, ic, TRUE);
6878 /*-----------------------------------------------------------------*/
6879 /* genrshOne - right shift a one byte quantity by known count */
6880 /*-----------------------------------------------------------------*/
6882 genrshOne (operand * result, operand * left,
6883 int shCount, int sign)
6885 D (emitcode (";", "genrshOne");
6887 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6893 /*-----------------------------------------------------------------*/
6894 /* genrshTwo - right shift two bytes by known amount != 0 */
6895 /*-----------------------------------------------------------------*/
6897 genrshTwo (operand * result, operand * left,
6898 int shCount, int sign)
6900 D (emitcode (";", "genrshTwo");
6903 /* if shCount >= 8 */
6908 shiftR1Left2Result (left, MSB16, result, LSB,
6911 movLeft2Result (left, MSB16, result, LSB, sign);
6912 addSign (result, MSB16, sign);
6915 /* 1 <= shCount <= 7 */
6917 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6923 /*-----------------------------------------------------------------*/
6924 /* shiftRLong - shift right one long from left to result */
6925 /* offl = LSB or MSB16 */
6926 /*-----------------------------------------------------------------*/
6928 shiftRLong (operand * left, int offl,
6929 operand * result, int sign)
6932 emitcode ("clr", "c");
6933 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6935 emitcode ("mov", "c,acc.7");
6936 emitcode ("rrc", "a");
6937 aopPut (AOP (result), "a", MSB32 - offl);
6939 /* add sign of "a" */
6940 addSign (result, MSB32, sign);
6942 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6943 emitcode ("rrc", "a");
6944 aopPut (AOP (result), "a", MSB24 - offl);
6946 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6947 emitcode ("rrc", "a");
6948 aopPut (AOP (result), "a", MSB16 - offl);
6952 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6953 emitcode ("rrc", "a");
6954 aopPut (AOP (result), "a", LSB);
6961 /*-----------------------------------------------------------------*/
6962 /* genrshFour - shift four byte by a known amount != 0 */
6963 /*-----------------------------------------------------------------*/
6965 genrshFour (operand * result, operand * left,
6966 int shCount, int sign)
6968 D (emitcode (";", "genrshFour");
6971 /* if shifting more that 3 bytes */
6976 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6978 movLeft2Result (left, MSB32, result, LSB, sign);
6979 addSign (result, MSB16, sign);
6981 else if (shCount >= 16)
6985 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6988 movLeft2Result (left, MSB24, result, LSB, 0);
6989 movLeft2Result (left, MSB32, result, MSB16, sign);
6991 addSign (result, MSB24, sign);
6993 else if (shCount >= 8)
6997 shiftRLong (left, MSB16, result, sign);
6998 else if (shCount == 0)
7000 movLeft2Result (left, MSB16, result, LSB, 0);
7001 movLeft2Result (left, MSB24, result, MSB16, 0);
7002 movLeft2Result (left, MSB32, result, MSB24, sign);
7003 addSign (result, MSB32, sign);
7007 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7008 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7009 /* the last shift is signed */
7010 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7011 addSign (result, MSB32, sign);
7015 { /* 1 <= shCount <= 7 */
7018 shiftRLong (left, LSB, result, sign);
7020 shiftRLong (result, LSB, result, sign);
7024 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7025 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7026 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7034 /*-----------------------------------------------------------------*/
7035 /* genRightShiftLiteral - right shifting by known count */
7036 /*-----------------------------------------------------------------*/
7038 genRightShiftLiteral (operand * left,
7044 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7047 D (emitcode (";", "genRightShiftLiteral");
7050 freeAsmop (right, NULL, ic, TRUE);
7052 aopOp (left, ic, FALSE, FALSE);
7053 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7056 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7060 size = getDataSize (left);
7061 /* test the LEFT size !!! */
7063 /* I suppose that the left size >= result size */
7066 size = getDataSize (result);
7068 movLeft2Result (left, size, result, size, 0);
7071 else if (shCount >= (size * 8))
7074 /* get sign in acc.7 */
7075 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7076 addSign (result, LSB, sign);
7083 genrshOne (result, left, shCount, sign);
7087 genrshTwo (result, left, shCount, sign);
7091 genrshFour (result, left, shCount, sign);
7097 freeAsmop (left, NULL, ic, TRUE);
7098 freeAsmop (result, NULL, ic, TRUE);
7103 /*-----------------------------------------------------------------*/
7104 /* genSignedRightShift - right shift of signed number */
7105 /*-----------------------------------------------------------------*/
7107 genSignedRightShift (iCode * ic)
7109 operand *right, *left, *result;
7112 symbol *tlbl, *tlbl1;
7114 D (emitcode (";", "genSignedRightShift ");
7117 /* we do it the hard way put the shift count in b
7118 and loop thru preserving the sign */
7120 right = IC_RIGHT (ic);
7121 left = IC_LEFT (ic);
7122 result = IC_RESULT (ic);
7124 aopOp (right, ic, FALSE, FALSE);
7127 if (AOP_TYPE (right) == AOP_LIT)
7129 genRightShiftLiteral (left, right, result, ic, 1);
7133 /* shift count is unknown then we have to form
7134 a loop get the loop count in B : Note: we take
7135 only the lower order byte since shifting
7136 more that 32 bits make no sense anyway, ( the
7137 largest size of an object can be only 32 bits ) */
7139 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7140 emitcode ("inc", "b");
7141 freeAsmop (right, NULL, ic, TRUE);
7142 aopOp (left, ic, FALSE, FALSE);
7143 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7145 /* now move the left to the result if they are not the
7147 if (!sameRegs (AOP (left), AOP (result)) &&
7148 AOP_SIZE (result) > 1)
7151 size = AOP_SIZE (result);
7153 _startLazyDPSEvaluation ();
7156 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7157 if (*l == '@' && IS_AOP_PREG (result))
7160 emitcode ("mov", "a,%s", l);
7161 aopPut (AOP (result), "a", offset);
7164 aopPut (AOP (result), l, offset);
7167 _endLazyDPSEvaluation ();
7170 /* mov the highest order bit to OVR */
7171 tlbl = newiTempLabel (NULL);
7172 tlbl1 = newiTempLabel (NULL);
7174 size = AOP_SIZE (result);
7176 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7177 emitcode ("rlc", "a");
7178 emitcode ("mov", "ov,c");
7179 /* if it is only one byte then */
7182 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7184 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7185 emitcode ("", "%05d$:", tlbl->key + 100);
7186 emitcode ("mov", "c,ov");
7187 emitcode ("rrc", "a");
7188 emitcode ("", "%05d$:", tlbl1->key + 100);
7189 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7190 aopPut (AOP (result), "a", 0);
7194 reAdjustPreg (AOP (result));
7195 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7196 emitcode ("", "%05d$:", tlbl->key + 100);
7197 emitcode ("mov", "c,ov");
7198 _startLazyDPSEvaluation ();
7201 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7203 emitcode ("rrc", "a");
7204 aopPut (AOP (result), "a", offset--);
7206 _endLazyDPSEvaluation ();
7207 reAdjustPreg (AOP (result));
7208 emitcode ("", "%05d$:", tlbl1->key + 100);
7209 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7212 freeAsmop (left, NULL, ic, TRUE);
7213 freeAsmop (result, NULL, ic, TRUE);
7216 /*-----------------------------------------------------------------*/
7217 /* genRightShift - generate code for right shifting */
7218 /*-----------------------------------------------------------------*/
7220 genRightShift (iCode * ic)
7222 operand *right, *left, *result;
7226 symbol *tlbl, *tlbl1;
7228 D (emitcode (";", "genRightShift ");
7231 /* if signed then we do it the hard way preserve the
7232 sign bit moving it inwards */
7233 retype = getSpec (operandType (IC_RESULT (ic)));
7235 if (!SPEC_USIGN (retype))
7237 genSignedRightShift (ic);
7241 /* signed & unsigned types are treated the same : i.e. the
7242 signed is NOT propagated inwards : quoting from the
7243 ANSI - standard : "for E1 >> E2, is equivalent to division
7244 by 2**E2 if unsigned or if it has a non-negative value,
7245 otherwise the result is implementation defined ", MY definition
7246 is that the sign does not get propagated */
7248 right = IC_RIGHT (ic);
7249 left = IC_LEFT (ic);
7250 result = IC_RESULT (ic);
7252 aopOp (right, ic, FALSE, FALSE);
7255 /* if the shift count is known then do it
7256 as efficiently as possible */
7257 if (AOP_TYPE (right) == AOP_LIT)
7259 genRightShiftLiteral (left, right, result, ic, 0);
7264 /* shift count is unknown then we have to form
7265 a loop get the loop count in B : Note: we take
7266 only the lower order byte since shifting
7267 more that 32 bits make no sense anyway, ( the
7268 largest size of an object can be only 32 bits ) */
7270 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7271 emitcode ("inc", "b");
7272 freeAsmop (right, NULL, ic, TRUE);
7273 aopOp (left, ic, FALSE, FALSE);
7274 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7276 /* now move the left to the result if they are not the
7278 if (!sameRegs (AOP (left), AOP (result)) &&
7279 AOP_SIZE (result) > 1)
7282 size = AOP_SIZE (result);
7284 _startLazyDPSEvaluation ();
7287 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7288 if (*l == '@' && IS_AOP_PREG (result))
7291 emitcode ("mov", "a,%s", l);
7292 aopPut (AOP (result), "a", offset);
7295 aopPut (AOP (result), l, offset);
7298 _endLazyDPSEvaluation ();
7301 tlbl = newiTempLabel (NULL);
7302 tlbl1 = newiTempLabel (NULL);
7303 size = AOP_SIZE (result);
7306 /* if it is only one byte then */
7309 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7311 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7312 emitcode ("", "%05d$:", tlbl->key + 100);
7314 emitcode ("rrc", "a");
7315 emitcode ("", "%05d$:", tlbl1->key + 100);
7316 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7317 aopPut (AOP (result), "a", 0);
7321 reAdjustPreg (AOP (result));
7322 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7323 emitcode ("", "%05d$:", tlbl->key + 100);
7325 _startLazyDPSEvaluation ();
7328 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7330 emitcode ("rrc", "a");
7331 aopPut (AOP (result), "a", offset--);
7333 _endLazyDPSEvaluation ();
7334 reAdjustPreg (AOP (result));
7336 emitcode ("", "%05d$:", tlbl1->key + 100);
7337 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7340 freeAsmop (left, NULL, ic, TRUE);
7341 freeAsmop (result, NULL, ic, TRUE);
7344 /*-----------------------------------------------------------------*/
7345 /* genUnpackBits - generates code for unpacking bits */
7346 /*-----------------------------------------------------------------*/
7348 genUnpackBits (operand * result, char *rname, int ptype)
7355 D (emitcode (";", "genUnpackBits ");
7358 etype = getSpec (operandType (result));
7360 /* read the first byte */
7366 emitcode ("mov", "a,@%s", rname);
7370 emitcode ("movx", "a,@%s", rname);
7374 emitcode ("movx", "a,@dptr");
7378 emitcode ("clr", "a");
7379 emitcode ("movc", "a", "@a+dptr");
7383 emitcode ("lcall", "__gptrget");
7387 /* if we have bitdisplacement then it fits */
7388 /* into this byte completely or if length is */
7389 /* less than a byte */
7390 if ((shCnt = SPEC_BSTR (etype)) ||
7391 (SPEC_BLEN (etype) <= 8))
7394 /* shift right acc */
7397 emitcode ("anl", "a,#0x%02x",
7398 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7399 aopPut (AOP (result), "a", offset);
7403 /* bit field did not fit in a byte */
7404 rlen = SPEC_BLEN (etype) - 8;
7405 aopPut (AOP (result), "a", offset++);
7414 emitcode ("inc", "%s", rname);
7415 emitcode ("mov", "a,@%s", rname);
7419 emitcode ("inc", "%s", rname);
7420 emitcode ("movx", "a,@%s", rname);
7424 emitcode ("inc", "dptr");
7425 emitcode ("movx", "a,@dptr");
7429 emitcode ("clr", "a");
7430 emitcode ("inc", "dptr");
7431 emitcode ("movc", "a", "@a+dptr");
7435 emitcode ("inc", "dptr");
7436 emitcode ("lcall", "__gptrget");
7441 /* if we are done */
7445 aopPut (AOP (result), "a", offset++);
7451 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7452 aopPut (AOP (result), "a", offset);
7459 /*-----------------------------------------------------------------*/
7460 /* genDataPointerGet - generates code when ptr offset is known */
7461 /*-----------------------------------------------------------------*/
7463 genDataPointerGet (operand * left,
7469 int size, offset = 0;
7470 aopOp (result, ic, TRUE, FALSE);
7472 /* get the string representation of the name */
7473 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7474 size = AOP_SIZE (result);
7475 _startLazyDPSEvaluation ();
7479 sprintf (buffer, "(%s + %d)", l + 1, offset);
7481 sprintf (buffer, "%s", l + 1);
7482 aopPut (AOP (result), buffer, offset++);
7484 _endLazyDPSEvaluation ();
7486 freeAsmop (left, NULL, ic, TRUE);
7487 freeAsmop (result, NULL, ic, TRUE);
7490 /*-----------------------------------------------------------------*/
7491 /* genNearPointerGet - emitcode for near pointer fetch */
7492 /*-----------------------------------------------------------------*/
7494 genNearPointerGet (operand * left,
7501 sym_link *rtype, *retype, *letype;
7502 sym_link *ltype = operandType (left);
7505 rtype = operandType (result);
7506 retype = getSpec (rtype);
7507 letype = getSpec (ltype);
7509 aopOp (left, ic, FALSE, FALSE);
7511 /* if left is rematerialisable and
7512 result is not bit variable type and
7513 the left is pointer to data space i.e
7514 lower 128 bytes of space */
7515 if (AOP_TYPE (left) == AOP_IMMD &&
7516 !IS_BITVAR (retype) &&
7517 !IS_BITVAR (letype) &&
7518 DCL_TYPE (ltype) == POINTER)
7520 genDataPointerGet (left, result, ic);
7524 /* if the value is already in a pointer register
7525 then don't need anything more */
7526 if (!AOP_INPREG (AOP (left)))
7528 /* otherwise get a free pointer register */
7530 preg = getFreePtr (ic, &aop, FALSE);
7531 emitcode ("mov", "%s,%s",
7533 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7537 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7539 freeAsmop (left, NULL, ic, TRUE);
7540 aopOp (result, ic, FALSE, FALSE);
7542 /* if bitfield then unpack the bits */
7543 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7544 genUnpackBits (result, rname, POINTER);
7547 /* we have can just get the values */
7548 int size = AOP_SIZE (result);
7553 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7556 emitcode ("mov", "a,@%s", rname);
7557 aopPut (AOP (result), "a", offset);
7561 sprintf (buffer, "@%s", rname);
7562 aopPut (AOP (result), buffer, offset);
7566 emitcode ("inc", "%s", rname);
7570 /* now some housekeeping stuff */
7573 /* we had to allocate for this iCode */
7574 freeAsmop (NULL, aop, ic, TRUE);
7578 /* we did not allocate which means left
7579 already in a pointer register, then
7580 if size > 0 && this could be used again
7581 we have to point it back to where it
7583 if (AOP_SIZE (result) > 1 &&
7584 !OP_SYMBOL (left)->remat &&
7585 (OP_SYMBOL (left)->liveTo > ic->seq ||
7588 int size = AOP_SIZE (result) - 1;
7590 emitcode ("dec", "%s", rname);
7595 freeAsmop (result, NULL, ic, TRUE);
7599 /*-----------------------------------------------------------------*/
7600 /* genPagedPointerGet - emitcode for paged pointer fetch */
7601 /*-----------------------------------------------------------------*/
7603 genPagedPointerGet (operand * left,
7610 sym_link *rtype, *retype, *letype;
7612 rtype = operandType (result);
7613 retype = getSpec (rtype);
7614 letype = getSpec (operandType (left));
7615 aopOp (left, ic, FALSE, FALSE);
7617 /* if the value is already in a pointer register
7618 then don't need anything more */
7619 if (!AOP_INPREG (AOP (left)))
7621 /* otherwise get a free pointer register */
7623 preg = getFreePtr (ic, &aop, FALSE);
7624 emitcode ("mov", "%s,%s",
7626 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7630 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7632 freeAsmop (left, NULL, ic, TRUE);
7633 aopOp (result, ic, FALSE, FALSE);
7635 /* if bitfield then unpack the bits */
7636 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7637 genUnpackBits (result, rname, PPOINTER);
7640 /* we have can just get the values */
7641 int size = AOP_SIZE (result);
7647 emitcode ("movx", "a,@%s", rname);
7648 aopPut (AOP (result), "a", offset);
7653 emitcode ("inc", "%s", rname);
7657 /* now some housekeeping stuff */
7660 /* we had to allocate for this iCode */
7661 freeAsmop (NULL, aop, ic, TRUE);
7665 /* we did not allocate which means left
7666 already in a pointer register, then
7667 if size > 0 && this could be used again
7668 we have to point it back to where it
7670 if (AOP_SIZE (result) > 1 &&
7671 !OP_SYMBOL (left)->remat &&
7672 (OP_SYMBOL (left)->liveTo > ic->seq ||
7675 int size = AOP_SIZE (result) - 1;
7677 emitcode ("dec", "%s", rname);
7682 freeAsmop (result, NULL, ic, TRUE);
7687 /*-----------------------------------------------------------------*/
7688 /* genFarPointerGet - gget value from far space */
7689 /*-----------------------------------------------------------------*/
7691 genFarPointerGet (operand * left,
7692 operand * result, iCode * ic)
7695 sym_link *retype = getSpec (operandType (result));
7696 sym_link *letype = getSpec (operandType (left));
7697 D (emitcode (";", "genFarPointerGet");
7700 aopOp (left, ic, FALSE, FALSE);
7702 /* if the operand is already in dptr
7703 then we do nothing else we move the value to dptr */
7704 if (AOP_TYPE (left) != AOP_STR)
7706 /* if this is remateriazable */
7707 if (AOP_TYPE (left) == AOP_IMMD)
7709 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7713 /* we need to get it byte by byte */
7714 _startLazyDPSEvaluation ();
7715 if (AOP_TYPE (left) != AOP_DPTR)
7717 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7718 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7719 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7723 /* We need to generate a load to DPTR indirect through DPTR. */
7724 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7726 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7727 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7728 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7729 emitcode ("pop", "dph");
7730 emitcode ("pop", "dpl");
7732 _endLazyDPSEvaluation ();
7735 /* so dptr know contains the address */
7736 freeAsmop (left, NULL, ic, TRUE);
7737 aopOp (result, ic, FALSE, TRUE);
7739 /* if bit then unpack */
7740 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7741 genUnpackBits (result, "dptr", FPOINTER);
7744 size = AOP_SIZE (result);
7747 _startLazyDPSEvaluation ();
7754 emitcode ("movx", "a,@dptr");
7756 emitcode ("inc", "dptr");
7758 aopPut (AOP (result), "a", offset++);
7760 _endLazyDPSEvaluation ();
7763 freeAsmop (result, NULL, ic, TRUE);
7766 /*-----------------------------------------------------------------*/
7767 /* emitcodePointerGet - gget value from code space */
7768 /*-----------------------------------------------------------------*/
7770 emitcodePointerGet (operand * left,
7771 operand * result, iCode * ic)
7774 sym_link *retype = getSpec (operandType (result));
7776 aopOp (left, ic, FALSE, FALSE);
7778 /* if the operand is already in dptr
7779 then we do nothing else we move the value to dptr */
7780 if (AOP_TYPE (left) != AOP_STR)
7782 /* if this is remateriazable */
7783 if (AOP_TYPE (left) == AOP_IMMD)
7785 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7788 { /* we need to get it byte by byte */
7789 _startLazyDPSEvaluation ();
7790 if (AOP_TYPE (left) != AOP_DPTR)
7792 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7793 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7794 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7798 /* We need to generate a load to DPTR indirect through DPTR. */
7799 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7801 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7802 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7803 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7804 emitcode ("pop", "dph");
7805 emitcode ("pop", "dpl");
7807 _endLazyDPSEvaluation ();
7810 /* so dptr know contains the address */
7811 freeAsmop (left, NULL, ic, TRUE);
7812 aopOp (result, ic, FALSE, TRUE);
7814 /* if bit then unpack */
7815 if (IS_BITVAR (retype))
7816 genUnpackBits (result, "dptr", CPOINTER);
7819 size = AOP_SIZE (result);
7822 _startLazyDPSEvaluation ();
7828 emitcode ("clr", "a");
7829 emitcode ("movc", "a,@a+dptr");
7831 emitcode ("inc", "dptr");
7832 aopPut (AOP (result), "a", offset++);
7834 _endLazyDPSEvaluation ();
7837 freeAsmop (result, NULL, ic, TRUE);
7840 /*-----------------------------------------------------------------*/
7841 /* genGenPointerGet - gget value from generic pointer space */
7842 /*-----------------------------------------------------------------*/
7844 genGenPointerGet (operand * left,
7845 operand * result, iCode * ic)
7848 sym_link *retype = getSpec (operandType (result));
7849 sym_link *letype = getSpec (operandType (left));
7851 D (emitcode (";", "genGenPointerGet "); );
7853 aopOp (left, ic, FALSE, TRUE);
7855 /* if the operand is already in dptr
7856 then we do nothing else we move the value to dptr */
7857 if (AOP_TYPE (left) != AOP_STR)
7859 /* if this is remateriazable */
7860 if (AOP_TYPE (left) == AOP_IMMD)
7862 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7863 emitcode ("mov", "b,#%d", pointerCode (retype));
7866 { /* we need to get it byte by byte */
7867 _startLazyDPSEvaluation ();
7868 if (AOP(left)->type==AOP_DPTR2) {
7870 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7873 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7874 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7877 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7878 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7881 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7882 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7884 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7885 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7886 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7887 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7889 _endLazyDPSEvaluation ();
7892 /* so dptr know contains the address */
7893 freeAsmop (left, NULL, ic, TRUE);
7894 aopOp (result, ic, FALSE, TRUE);
7896 /* if bit then unpack */
7897 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7898 genUnpackBits (result, "dptr", GPOINTER);
7901 size = AOP_SIZE (result);
7906 emitcode ("lcall", "__gptrget");
7907 aopPut (AOP (result), "a", offset++);
7909 emitcode ("inc", "dptr");
7913 freeAsmop (result, NULL, ic, TRUE);
7916 /*-----------------------------------------------------------------*/
7917 /* genPointerGet - generate code for pointer get */
7918 /*-----------------------------------------------------------------*/
7920 genPointerGet (iCode * ic)
7922 operand *left, *result;
7923 sym_link *type, *etype;
7926 D (emitcode (";", "genPointerGet ");
7929 left = IC_LEFT (ic);
7930 result = IC_RESULT (ic);
7932 /* depending on the type of pointer we need to
7933 move it to the correct pointer register */
7934 type = operandType (left);
7935 etype = getSpec (type);
7936 /* if left is of type of pointer then it is simple */
7937 if (IS_PTR (type) && !IS_FUNC (type->next))
7938 p_type = DCL_TYPE (type);
7941 /* we have to go by the storage class */
7942 p_type = PTR_TYPE (SPEC_OCLS (etype));
7945 /* now that we have the pointer type we assign
7946 the pointer values */
7952 genNearPointerGet (left, result, ic);
7956 genPagedPointerGet (left, result, ic);
7960 genFarPointerGet (left, result, ic);
7964 emitcodePointerGet (left, result, ic);
7968 genGenPointerGet (left, result, ic);
7974 /*-----------------------------------------------------------------*/
7975 /* genPackBits - generates code for packed bit storage */
7976 /*-----------------------------------------------------------------*/
7978 genPackBits (sym_link * etype,
7980 char *rname, int p_type)
7988 blen = SPEC_BLEN (etype);
7989 bstr = SPEC_BSTR (etype);
7991 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
7994 /* if the bit lenth is less than or */
7995 /* it exactly fits a byte then */
7996 if (SPEC_BLEN (etype) <= 8)
7998 shCount = SPEC_BSTR (etype);
8000 /* shift left acc */
8003 if (SPEC_BLEN (etype) < 8)
8004 { /* if smaller than a byte */
8010 emitcode ("mov", "b,a");
8011 emitcode ("mov", "a,@%s", rname);
8015 emitcode ("mov", "b,a");
8016 emitcode ("movx", "a,@dptr");
8020 emitcode ("push", "b");
8021 emitcode ("push", "acc");
8022 emitcode ("lcall", "__gptrget");
8023 emitcode ("pop", "b");
8027 emitcode ("anl", "a,#0x%02x", (unsigned char)
8028 ((unsigned char) (0xFF << (blen + bstr)) |
8029 (unsigned char) (0xFF >> (8 - bstr))));
8030 emitcode ("orl", "a,b");
8031 if (p_type == GPOINTER)
8032 emitcode ("pop", "b");
8039 emitcode ("mov", "@%s,a", rname);
8043 emitcode ("movx", "@dptr,a");
8047 emitcode ("lcall", "__gptrput");
8052 if (SPEC_BLEN (etype) <= 8)
8055 emitcode ("inc", "%s", rname);
8056 rLen = SPEC_BLEN (etype);
8058 /* now generate for lengths greater than one byte */
8062 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8074 emitcode ("mov", "@%s,a", rname);
8077 emitcode ("mov", "@%s,%s", rname, l);
8082 emitcode ("movx", "@dptr,a");
8087 emitcode ("lcall", "__gptrput");
8090 emitcode ("inc", "%s", rname);
8095 /* last last was not complete */
8098 /* save the byte & read byte */
8102 emitcode ("mov", "b,a");
8103 emitcode ("mov", "a,@%s", rname);
8107 emitcode ("mov", "b,a");
8108 emitcode ("movx", "a,@dptr");
8112 emitcode ("push", "b");
8113 emitcode ("push", "acc");
8114 emitcode ("lcall", "__gptrget");
8115 emitcode ("pop", "b");
8119 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8120 emitcode ("orl", "a,b");
8123 if (p_type == GPOINTER)
8124 emitcode ("pop", "b");
8130 emitcode ("mov", "@%s,a", rname);
8134 emitcode ("movx", "@dptr,a");
8138 emitcode ("lcall", "__gptrput");
8142 /*-----------------------------------------------------------------*/
8143 /* genDataPointerSet - remat pointer to data space */
8144 /*-----------------------------------------------------------------*/
8146 genDataPointerSet (operand * right,
8150 int size, offset = 0;
8151 char *l, buffer[256];
8153 aopOp (right, ic, FALSE, FALSE);
8155 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8156 size = AOP_SIZE (right);
8160 sprintf (buffer, "(%s + %d)", l + 1, offset);
8162 sprintf (buffer, "%s", l + 1);
8163 emitcode ("mov", "%s,%s", buffer,
8164 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8167 freeAsmop (right, NULL, ic, TRUE);
8168 freeAsmop (result, NULL, ic, TRUE);
8171 /*-----------------------------------------------------------------*/
8172 /* genNearPointerSet - emitcode for near pointer put */
8173 /*-----------------------------------------------------------------*/
8175 genNearPointerSet (operand * right,
8182 sym_link *retype, *letype;
8183 sym_link *ptype = operandType (result);
8185 retype = getSpec (operandType (right));
8186 letype = getSpec (ptype);
8188 aopOp (result, ic, FALSE, FALSE);
8190 /* if the result is rematerializable &
8191 in data space & not a bit variable */
8192 if (AOP_TYPE (result) == AOP_IMMD &&
8193 DCL_TYPE (ptype) == POINTER &&
8194 !IS_BITVAR (retype) &&
8195 !IS_BITVAR (letype))
8197 genDataPointerSet (right, result, ic);
8201 /* if the value is already in a pointer register
8202 then don't need anything more */
8203 if (!AOP_INPREG (AOP (result)))
8205 /* otherwise get a free pointer register */
8207 preg = getFreePtr (ic, &aop, FALSE);
8208 emitcode ("mov", "%s,%s",
8210 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8214 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8216 freeAsmop (result, NULL, ic, TRUE);
8217 aopOp (right, ic, FALSE, FALSE);
8219 /* if bitfield then unpack the bits */
8220 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8221 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8224 /* we have can just get the values */
8225 int size = AOP_SIZE (right);
8230 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8234 emitcode ("mov", "@%s,a", rname);
8237 emitcode ("mov", "@%s,%s", rname, l);
8239 emitcode ("inc", "%s", rname);
8244 /* now some housekeeping stuff */
8247 /* we had to allocate for this iCode */
8248 freeAsmop (NULL, aop, ic, TRUE);
8252 /* we did not allocate which means left
8253 already in a pointer register, then
8254 if size > 0 && this could be used again
8255 we have to point it back to where it
8257 if (AOP_SIZE (right) > 1 &&
8258 !OP_SYMBOL (result)->remat &&
8259 (OP_SYMBOL (result)->liveTo > ic->seq ||
8262 int size = AOP_SIZE (right) - 1;
8264 emitcode ("dec", "%s", rname);
8269 freeAsmop (right, NULL, ic, TRUE);
8274 /*-----------------------------------------------------------------*/
8275 /* genPagedPointerSet - emitcode for Paged pointer put */
8276 /*-----------------------------------------------------------------*/
8278 genPagedPointerSet (operand * right,
8285 sym_link *retype, *letype;
8287 retype = getSpec (operandType (right));
8288 letype = getSpec (operandType (result));
8290 aopOp (result, ic, FALSE, FALSE);
8292 /* if the value is already in a pointer register
8293 then don't need anything more */
8294 if (!AOP_INPREG (AOP (result)))
8296 /* otherwise get a free pointer register */
8298 preg = getFreePtr (ic, &aop, FALSE);
8299 emitcode ("mov", "%s,%s",
8301 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8305 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8307 freeAsmop (result, NULL, ic, TRUE);
8308 aopOp (right, ic, FALSE, FALSE);
8310 /* if bitfield then unpack the bits */
8311 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8312 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8315 /* we have can just get the values */
8316 int size = AOP_SIZE (right);
8321 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8324 emitcode ("movx", "@%s,a", rname);
8327 emitcode ("inc", "%s", rname);
8333 /* now some housekeeping stuff */
8336 /* we had to allocate for this iCode */
8337 freeAsmop (NULL, aop, ic, TRUE);
8341 /* we did not allocate which means left
8342 already in a pointer register, then
8343 if size > 0 && this could be used again
8344 we have to point it back to where it
8346 if (AOP_SIZE (right) > 1 &&
8347 !OP_SYMBOL (result)->remat &&
8348 (OP_SYMBOL (result)->liveTo > ic->seq ||
8351 int size = AOP_SIZE (right) - 1;
8353 emitcode ("dec", "%s", rname);
8358 freeAsmop (right, NULL, ic, TRUE);
8363 /*-----------------------------------------------------------------*/
8364 /* genFarPointerSet - set value from far space */
8365 /*-----------------------------------------------------------------*/
8367 genFarPointerSet (operand * right,
8368 operand * result, iCode * ic)
8371 sym_link *retype = getSpec (operandType (right));
8372 sym_link *letype = getSpec (operandType (result));
8374 aopOp (result, ic, FALSE, FALSE);
8376 /* if the operand is already in dptr
8377 then we do nothing else we move the value to dptr */
8378 if (AOP_TYPE (result) != AOP_STR)
8380 /* if this is remateriazable */
8381 if (AOP_TYPE (result) == AOP_IMMD)
8382 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8385 /* we need to get it byte by byte */
8386 _startLazyDPSEvaluation ();
8387 if (AOP_TYPE (result) != AOP_DPTR)
8389 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8390 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8391 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8395 /* We need to generate a load to DPTR indirect through DPTR. */
8396 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8398 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8399 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8400 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8401 emitcode ("pop", "dph");
8402 emitcode ("pop", "dpl");
8404 _endLazyDPSEvaluation ();
8407 /* so dptr know contains the address */
8408 freeAsmop (result, NULL, ic, TRUE);
8409 aopOp (right, ic, FALSE, TRUE);
8411 /* if bit then unpack */
8412 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8413 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8416 size = AOP_SIZE (right);
8419 _startLazyDPSEvaluation ();
8422 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8428 emitcode ("movx", "@dptr,a");
8430 emitcode ("inc", "dptr");
8432 _endLazyDPSEvaluation ();
8435 freeAsmop (right, NULL, ic, TRUE);
8438 /*-----------------------------------------------------------------*/
8439 /* genGenPointerSet - set value from generic pointer space */
8440 /*-----------------------------------------------------------------*/
8442 genGenPointerSet (operand * right,
8443 operand * result, iCode * ic)
8446 sym_link *retype = getSpec (operandType (right));
8447 sym_link *letype = getSpec (operandType (result));
8449 aopOp (result, ic, FALSE, TRUE);
8451 /* if the operand is already in dptr
8452 then we do nothing else we move the value to dptr */
8453 if (AOP_TYPE (result) != AOP_STR)
8455 _startLazyDPSEvaluation ();
8456 /* if this is remateriazable */
8457 if (AOP_TYPE (result) == AOP_IMMD)
8459 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8460 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8463 { /* we need to get it byte by byte */
8464 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8465 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8466 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8467 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8469 _endLazyDPSEvaluation ();
8471 /* so dptr know contains the address */
8472 freeAsmop (result, NULL, ic, TRUE);
8473 aopOp (right, ic, FALSE, TRUE);
8475 /* if bit then unpack */
8476 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8477 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8480 size = AOP_SIZE (right);
8483 _startLazyDPSEvaluation ();
8486 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8492 emitcode ("lcall", "__gptrput");
8494 emitcode ("inc", "dptr");
8496 _endLazyDPSEvaluation ();
8499 freeAsmop (right, NULL, ic, TRUE);
8502 /*-----------------------------------------------------------------*/
8503 /* genPointerSet - stores the value into a pointer location */
8504 /*-----------------------------------------------------------------*/
8506 genPointerSet (iCode * ic)
8508 operand *right, *result;
8509 sym_link *type, *etype;
8512 D (emitcode (";", "genPointerSet ");
8515 right = IC_RIGHT (ic);
8516 result = IC_RESULT (ic);
8518 /* depending on the type of pointer we need to
8519 move it to the correct pointer register */
8520 type = operandType (result);
8521 etype = getSpec (type);
8522 /* if left is of type of pointer then it is simple */
8523 if (IS_PTR (type) && !IS_FUNC (type->next))
8525 p_type = DCL_TYPE (type);
8529 /* we have to go by the storage class */
8530 p_type = PTR_TYPE (SPEC_OCLS (etype));
8533 /* now that we have the pointer type we assign
8534 the pointer values */
8540 genNearPointerSet (right, result, ic);
8544 genPagedPointerSet (right, result, ic);
8548 genFarPointerSet (right, result, ic);
8552 genGenPointerSet (right, result, ic);
8558 /*-----------------------------------------------------------------*/
8559 /* genIfx - generate code for Ifx statement */
8560 /*-----------------------------------------------------------------*/
8562 genIfx (iCode * ic, iCode * popIc)
8564 operand *cond = IC_COND (ic);
8567 D (emitcode (";", "genIfx ");
8570 aopOp (cond, ic, FALSE, FALSE);
8572 /* get the value into acc */
8573 if (AOP_TYPE (cond) != AOP_CRY)
8577 /* the result is now in the accumulator */
8578 freeAsmop (cond, NULL, ic, TRUE);
8580 /* if there was something to be popped then do it */
8584 /* if the condition is a bit variable */
8585 if (isbit && IS_ITEMP (cond) &&
8587 genIfxJump (ic, SPIL_LOC (cond)->rname);
8588 else if (isbit && !IS_ITEMP (cond))
8589 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8591 genIfxJump (ic, "a");
8596 /*-----------------------------------------------------------------*/
8597 /* genAddrOf - generates code for address of */
8598 /*-----------------------------------------------------------------*/
8600 genAddrOf (iCode * ic)
8602 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8605 D (emitcode (";", "genAddrOf ");
8608 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8610 /* if the operand is on the stack then we
8611 need to get the stack offset of this
8615 /* if it has an offset then we need to compute
8619 emitcode ("mov", "a,_bp");
8620 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8621 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8625 /* we can just move _bp */
8626 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8628 /* fill the result with zero */
8629 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8632 if (options.stack10bit && size < (FPTRSIZE - 1))
8635 "*** warning: pointer to stack var truncated.\n");
8642 if (options.stack10bit && offset == 2)
8644 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8648 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8655 /* object not on stack then we need the name */
8656 size = AOP_SIZE (IC_RESULT (ic));
8661 char s[SDCC_NAME_MAX];
8663 sprintf (s, "#(%s >> %d)",
8667 sprintf (s, "#%s", sym->rname);
8668 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8672 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8676 /*-----------------------------------------------------------------*/
8677 /* genFarFarAssign - assignment when both are in far space */
8678 /*-----------------------------------------------------------------*/
8680 genFarFarAssign (operand * result, operand * right, iCode * ic)
8682 int size = AOP_SIZE (right);
8688 /* This is a net loss for size == 1, but a big gain
8691 D (emitcode (";", "genFarFarAssign (improved)");
8694 aopOp (result, ic, TRUE, TRUE);
8696 _startLazyDPSEvaluation ();
8699 aopPut (AOP (result),
8700 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8703 _endLazyDPSEvaluation ();
8704 freeAsmop (result, NULL, ic, FALSE);
8705 freeAsmop (right, NULL, ic, FALSE);
8709 D (emitcode (";", "genFarFarAssign ");
8712 /* first push the right side on to the stack */
8713 _startLazyDPSEvaluation ();
8716 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8718 emitcode ("push", "acc");
8721 freeAsmop (right, NULL, ic, FALSE);
8722 /* now assign DPTR to result */
8723 aopOp (result, ic, FALSE, FALSE);
8724 size = AOP_SIZE (result);
8727 emitcode ("pop", "acc");
8728 aopPut (AOP (result), "a", --offset);
8730 freeAsmop (result, NULL, ic, FALSE);
8731 _endLazyDPSEvaluation ();
8735 /*-----------------------------------------------------------------*/
8736 /* genAssign - generate code for assignment */
8737 /*-----------------------------------------------------------------*/
8739 genAssign (iCode * ic)
8741 operand *result, *right;
8743 unsigned long lit = 0L;
8745 D (emitcode (";", "genAssign ");
8748 result = IC_RESULT (ic);
8749 right = IC_RIGHT (ic);
8751 /* if they are the same */
8752 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8755 aopOp (right, ic, FALSE, FALSE);
8757 emitcode (";", "genAssign: resultIsFar = %s",
8758 isOperandInFarSpace (result) ?
8761 /* special case both in far space */
8762 if ((AOP_TYPE (right) == AOP_DPTR ||
8763 AOP_TYPE (right) == AOP_DPTR2) &&
8764 /* IS_TRUE_SYMOP(result) && */
8765 isOperandInFarSpace (result))
8767 genFarFarAssign (result, right, ic);
8771 aopOp (result, ic, TRUE, FALSE);
8773 /* if they are the same registers */
8774 if (sameRegs (AOP (right), AOP (result)))
8777 /* if the result is a bit */
8778 if (AOP_TYPE (result) == AOP_CRY)
8781 /* if the right size is a literal then
8782 we know what the value is */
8783 if (AOP_TYPE (right) == AOP_LIT)
8785 if (((int) operandLitValue (right)))
8786 aopPut (AOP (result), one, 0);
8788 aopPut (AOP (result), zero, 0);
8792 /* the right is also a bit variable */
8793 if (AOP_TYPE (right) == AOP_CRY)
8795 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8796 aopPut (AOP (result), "c", 0);
8802 aopPut (AOP (result), "a", 0);
8806 /* bit variables done */
8808 size = AOP_SIZE (result);
8810 if (AOP_TYPE (right) == AOP_LIT)
8811 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8814 (AOP_TYPE (result) != AOP_REG) &&
8815 (AOP_TYPE (right) == AOP_LIT) &&
8816 !IS_FLOAT (operandType (right)))
8818 D (emitcode (";", "Kevin's better literal load code");
8820 _startLazyDPSEvaluation ();
8821 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8823 aopPut (AOP (result),
8824 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8829 /* And now fill the rest with zeros. */
8832 emitcode ("clr", "a");
8836 aopPut (AOP (result), "a", offset++);
8838 _endLazyDPSEvaluation ();
8842 _startLazyDPSEvaluation ();
8845 aopPut (AOP (result),
8846 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8850 _endLazyDPSEvaluation ();
8854 freeAsmop (right, NULL, ic, FALSE);
8855 freeAsmop (result, NULL, ic, TRUE);
8858 /*-----------------------------------------------------------------*/
8859 /* genJumpTab - generates code for jump table */
8860 /*-----------------------------------------------------------------*/
8862 genJumpTab (iCode * ic)
8867 D (emitcode (";", "genJumpTab ");
8870 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8871 /* get the condition into accumulator */
8872 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8874 /* multiply by four! */
8875 emitcode ("add", "a,acc");
8876 emitcode ("add", "a,acc");
8877 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8879 jtab = newiTempLabel (NULL);
8880 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8881 emitcode ("jmp", "@a+dptr");
8882 emitcode ("", "%05d$:", jtab->key + 100);
8883 /* now generate the jump labels */
8884 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8885 jtab = setNextItem (IC_JTLABELS (ic)))
8886 emitcode ("ljmp", "%05d$", jtab->key + 100);
8890 /*-----------------------------------------------------------------*/
8891 /* genCast - gen code for casting */
8892 /*-----------------------------------------------------------------*/
8894 genCast (iCode * ic)
8896 operand *result = IC_RESULT (ic);
8897 sym_link *ctype = operandType (IC_LEFT (ic));
8898 sym_link *rtype = operandType (IC_RIGHT (ic));
8899 operand *right = IC_RIGHT (ic);
8902 D (emitcode (";", "genCast ");
8905 /* if they are equivalent then do nothing */
8906 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8909 aopOp (right, ic, FALSE, FALSE);
8910 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8912 /* if the result is a bit */
8913 if (AOP_TYPE (result) == AOP_CRY)
8915 /* if the right size is a literal then
8916 we know what the value is */
8917 if (AOP_TYPE (right) == AOP_LIT)
8919 if (((int) operandLitValue (right)))
8920 aopPut (AOP (result), one, 0);
8922 aopPut (AOP (result), zero, 0);
8927 /* the right is also a bit variable */
8928 if (AOP_TYPE (right) == AOP_CRY)
8930 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8931 aopPut (AOP (result), "c", 0);
8937 aopPut (AOP (result), "a", 0);
8941 /* if they are the same size : or less */
8942 if (AOP_SIZE (result) <= AOP_SIZE (right))
8945 /* if they are in the same place */
8946 if (sameRegs (AOP (right), AOP (result)))
8949 /* if they in different places then copy */
8950 size = AOP_SIZE (result);
8952 _startLazyDPSEvaluation ();
8955 aopPut (AOP (result),
8956 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8960 _endLazyDPSEvaluation ();
8965 /* if the result is of type pointer */
8970 sym_link *type = operandType (right);
8972 /* pointer to generic pointer */
8973 if (IS_GENPTR (ctype))
8979 p_type = DCL_TYPE (type);
8983 #if OLD_CAST_BEHAVIOR
8984 /* KV: we are converting a non-pointer type to
8985 * a generic pointer. This (ifdef'd out) code
8986 * says that the resulting generic pointer
8987 * should have the same class as the storage
8988 * location of the non-pointer variable.
8990 * For example, converting an int (which happens
8991 * to be stored in DATA space) to a pointer results
8992 * in a DATA generic pointer; if the original int
8993 * in XDATA space, so will be the resulting pointer.
8995 * I don't like that behavior, and thus this change:
8996 * all such conversions will be forced to XDATA and
8997 * throw a warning. If you want some non-XDATA
8998 * type, or you want to suppress the warning, you
8999 * must go through an intermediate cast, like so:
9001 * char _generic *gp = (char _xdata *)(intVar);
9003 sym_link *etype = getSpec (type);
9005 /* we have to go by the storage class */
9006 if (SPEC_OCLS (etype) != generic)
9008 p_type = PTR_TYPE (SPEC_OCLS (etype));
9013 /* Converting unknown class (i.e. register variable)
9014 * to generic pointer. This is not good, but
9015 * we'll make a guess (and throw a warning).
9018 werror (W_INT_TO_GEN_PTR_CAST);
9022 /* the first two bytes are known */
9023 size = GPTRSIZE - 1;
9025 _startLazyDPSEvaluation ();
9028 aopPut (AOP (result),
9029 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9033 _endLazyDPSEvaluation ();
9035 /* the last byte depending on type */
9053 /* this should never happen */
9054 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9055 "got unknown pointer type");
9058 aopPut (AOP (result), l, GPTRSIZE - 1);
9062 /* just copy the pointers */
9063 size = AOP_SIZE (result);
9065 _startLazyDPSEvaluation ();
9068 aopPut (AOP (result),
9069 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9073 _endLazyDPSEvaluation ();
9077 /* so we now know that the size of destination is greater
9078 than the size of the source */
9079 /* we move to result for the size of source */
9080 size = AOP_SIZE (right);
9082 _startLazyDPSEvaluation ();
9085 aopPut (AOP (result),
9086 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9090 _endLazyDPSEvaluation ();
9092 /* now depending on the sign of the source && destination */
9093 size = AOP_SIZE (result) - AOP_SIZE (right);
9094 /* if unsigned or not an integral type */
9095 /* also, if the source is a bit, we don't need to sign extend, because
9096 * it can't possibly have set the sign bit.
9098 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9102 aopPut (AOP (result), zero, offset++);
9107 /* we need to extend the sign :{ */
9108 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9109 FALSE, FALSE, TRUE);
9111 emitcode ("rlc", "a");
9112 emitcode ("subb", "a,acc");
9114 aopPut (AOP (result), "a", offset++);
9117 /* we are done hurray !!!! */
9120 freeAsmop (right, NULL, ic, TRUE);
9121 freeAsmop (result, NULL, ic, TRUE);
9125 /*-----------------------------------------------------------------*/
9126 /* genDjnz - generate decrement & jump if not zero instrucion */
9127 /*-----------------------------------------------------------------*/
9129 genDjnz (iCode * ic, iCode * ifx)
9135 /* if the if condition has a false label
9136 then we cannot save */
9140 /* if the minus is not of the form
9142 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9143 !IS_OP_LITERAL (IC_RIGHT (ic)))
9146 if (operandLitValue (IC_RIGHT (ic)) != 1)
9149 /* if the size of this greater than one then no
9151 if (getSize (operandType (IC_RESULT (ic))) > 1)
9154 /* otherwise we can save BIG */
9155 lbl = newiTempLabel (NULL);
9156 lbl1 = newiTempLabel (NULL);
9158 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9160 if (IS_AOP_PREG (IC_RESULT (ic)))
9162 emitcode ("dec", "%s",
9163 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9164 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9165 emitcode ("jnz", "%05d$", lbl->key + 100);
9169 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9172 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9173 emitcode ("", "%05d$:", lbl->key + 100);
9174 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9175 emitcode ("", "%05d$:", lbl1->key + 100);
9177 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9182 /*-----------------------------------------------------------------*/
9183 /* genReceive - generate code for a receive iCode */
9184 /*-----------------------------------------------------------------*/
9186 genReceive (iCode * ic)
9189 D (emitcode (";", "genReceive ");
9192 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9193 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9194 IS_TRUE_SYMOP (IC_RESULT (ic))))
9196 int size = getSize (operandType (IC_RESULT (ic)));
9197 int offset = fReturnSizeDS390 - size;
9200 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9201 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9204 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9205 size = AOP_SIZE (IC_RESULT (ic));
9209 emitcode ("pop", "acc");
9210 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9217 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9219 assignResultValue (IC_RESULT (ic));
9222 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9225 /*-----------------------------------------------------------------*/
9226 /* gen390Code - generate code for Dallas 390 based controllers */
9227 /*-----------------------------------------------------------------*/
9229 gen390Code (iCode * lic)
9234 lineHead = lineCurr = NULL;
9238 /* print the allocation information */
9240 printAllocInfo (currFunc, codeOutFile);
9242 /* if debug information required */
9243 if (options.debug && currFunc)
9245 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9247 if (IS_STATIC (currFunc->etype))
9248 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9250 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9253 /* stack pointer name */
9254 if (options.useXstack)
9260 for (ic = lic; ic; ic = ic->next)
9263 if (cln != ic->lineno)
9268 emitcode ("", "C$%s$%d$%d$%d ==.",
9269 FileBaseName (ic->filename), ic->lineno,
9270 ic->level, ic->block);
9273 emitcode (";", "%s %d", ic->filename, ic->lineno);
9276 /* if the result is marked as
9277 spilt and rematerializable or code for
9278 this has already been generated then
9280 if (resultRemat (ic) || ic->generated)
9283 /* depending on the operation */
9303 /* IPOP happens only when trying to restore a
9304 spilt live range, if there is an ifx statement
9305 following this pop then the if statement might
9306 be using some of the registers being popped which
9307 would destory the contents of the register so
9308 we need to check for this condition and handle it */
9310 ic->next->op == IFX &&
9311 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9312 genIfx (ic->next, ic);
9330 genEndFunction (ic);
9350 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9367 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9371 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9378 /* note these two are xlated by algebraic equivalence
9379 during parsing SDCC.y */
9380 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9381 "got '>=' or '<=' shouldn't have come here");
9385 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9397 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9401 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9405 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9432 case GET_VALUE_AT_ADDRESS:
9437 if (POINTER_SET (ic))
9464 addSet (&_G.sendSet, ic);
9469 /* piCode(ic,stdout); */
9475 /* now we are ready to call the
9476 peep hole optimizer */
9477 if (!options.nopeep)
9478 peepHole (&lineHead);
9480 /* now do the actual printing */
9481 printLine (lineHead, codeOutFile);