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 fReturnSize_390 = 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) fReturnSize_390; 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)
971 emitcode ("xch", "a, ap");
977 while (offset > aop->coff)
979 emitcode ("inc", "dptr");
983 while (offset < aop->coff)
985 emitcode ("lcall", "__decdptr");
992 emitcode ("clr", "a");
993 emitcode ("movc", "a,@a+dptr");
997 emitcode ("movx", "a,@dptr");
1000 if (aop->type == AOP_DPTR2)
1006 emitcode ("xch", "a, ap");
1011 return (dname ? "acc" : "a");
1015 sprintf (s, "#%s", aop->aopu.aop_immd);
1017 sprintf (s, "#(%s >> %d)",
1022 aop->aopu.aop_immd);
1023 rs = Safe_calloc (1, strlen (s) + 1);
1029 sprintf (s, "(%s + %d)",
1033 sprintf (s, "%s", aop->aopu.aop_dir);
1034 rs = Safe_calloc (1, strlen (s) + 1);
1040 return aop->aopu.aop_reg[offset]->dname;
1042 return aop->aopu.aop_reg[offset]->name;
1045 emitcode ("clr", "a");
1046 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1047 emitcode ("rlc", "a");
1048 return (dname ? "acc" : "a");
1051 if (!offset && dname)
1053 return aop->aopu.aop_str[offset];
1056 return aopLiteral (aop->aopu.aop_lit, offset);
1060 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1064 return aop->aopu.aop_str[offset];
1068 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1069 "aopget got unsupported aop->type");
1072 /*-----------------------------------------------------------------*/
1073 /* aopPut - puts a string for a aop */
1074 /*-----------------------------------------------------------------*/
1076 aopPut (asmop * aop, char *s, int offset)
1081 if (aop->size && offset > (aop->size - 1))
1083 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1084 "aopPut got offset > aop->size");
1088 /* will assign value to value */
1089 /* depending on where it is ofcourse */
1094 sprintf (d, "(%s + %d)",
1095 aop->aopu.aop_dir, offset);
1097 sprintf (d, "%s", aop->aopu.aop_dir);
1100 emitcode ("mov", "%s,%s", d, s);
1105 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1106 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1109 strcmp (s, "r0") == 0 ||
1110 strcmp (s, "r1") == 0 ||
1111 strcmp (s, "r2") == 0 ||
1112 strcmp (s, "r3") == 0 ||
1113 strcmp (s, "r4") == 0 ||
1114 strcmp (s, "r5") == 0 ||
1115 strcmp (s, "r6") == 0 ||
1116 strcmp (s, "r7") == 0)
1117 emitcode ("mov", "%s,%s",
1118 aop->aopu.aop_reg[offset]->dname, s);
1120 emitcode ("mov", "%s,%s",
1121 aop->aopu.aop_reg[offset]->name, s);
1128 if (aop->type == AOP_DPTR2)
1136 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1137 "aopPut writting to code space");
1141 while (offset > aop->coff)
1144 emitcode ("inc", "dptr");
1147 while (offset < aop->coff)
1150 emitcode ("lcall", "__decdptr");
1155 /* if not in accumulater */
1158 emitcode ("movx", "@dptr,a");
1160 if (aop->type == AOP_DPTR2)
1168 while (offset > aop->coff)
1171 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1173 while (offset < aop->coff)
1176 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1183 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1189 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1191 else if (strcmp (s, "r0") == 0 ||
1192 strcmp (s, "r1") == 0 ||
1193 strcmp (s, "r2") == 0 ||
1194 strcmp (s, "r3") == 0 ||
1195 strcmp (s, "r4") == 0 ||
1196 strcmp (s, "r5") == 0 ||
1197 strcmp (s, "r6") == 0 ||
1198 strcmp (s, "r7") == 0)
1201 sprintf (buffer, "a%s", s);
1202 emitcode ("mov", "@%s,%s",
1203 aop->aopu.aop_ptr->name, buffer);
1206 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1211 if (strcmp (s, "a") == 0)
1212 emitcode ("push", "acc");
1214 emitcode ("push", "%s", s);
1219 /* if bit variable */
1220 if (!aop->aopu.aop_dir)
1222 emitcode ("clr", "a");
1223 emitcode ("rlc", "a");
1228 emitcode ("clr", "%s", aop->aopu.aop_dir);
1230 emitcode ("setb", "%s", aop->aopu.aop_dir);
1231 else if (!strcmp (s, "c"))
1232 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1235 lbl = newiTempLabel (NULL);
1237 if (strcmp (s, "a"))
1241 emitcode ("clr", "c");
1242 emitcode ("jz", "%05d$", lbl->key + 100);
1243 emitcode ("cpl", "c");
1244 emitcode ("", "%05d$:", lbl->key + 100);
1245 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1252 if (strcmp (aop->aopu.aop_str[offset], s))
1253 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1258 if (!offset && (strcmp (s, "acc") == 0))
1261 if (strcmp (aop->aopu.aop_str[offset], s))
1262 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1266 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1267 "aopPut got unsupported aop->type");
1274 /*-----------------------------------------------------------------*/
1275 /* reAdjustPreg - points a register back to where it should */
1276 /*-----------------------------------------------------------------*/
1278 reAdjustPreg (asmop * aop)
1283 if ((size = aop->size) <= 1)
1291 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1295 if (aop->type == AOP_DPTR2)
1302 emitcode ("lcall", "__decdptr");
1305 if (aop->type == AOP_DPTR2)
1315 #define AOP(op) op->aop
1316 #define AOP_TYPE(op) AOP(op)->type
1317 #define AOP_SIZE(op) AOP(op)->size
1318 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1319 AOP_TYPE(x) == AOP_R0))
1321 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1322 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1325 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1326 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1327 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1329 /* Workaround for DS80C390 bug: div ab may return bogus results
1330 * if A is accessed in instruction immediately before the div.
1332 * Will be fixed in B4 rev of processor, Dallas claims.
1335 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1336 if (!AOP_NEEDSACC(RIGHT)) \
1338 /* We can load A first, then B, since \
1339 * B (the RIGHT operand) won't clobber A, \
1340 * thus avoiding touching A right before the div. \
1342 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1343 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1345 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1349 /* Just stuff in a nop after loading A. */ \
1350 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1351 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1353 emitcode("nop", "; workaround for DS80C390 div bug."); \
1356 /*-----------------------------------------------------------------*/
1357 /* genNotFloat - generates not for float operations */
1358 /*-----------------------------------------------------------------*/
1360 genNotFloat (operand * op, operand * res)
1366 D (emitcode (";", "genNotFloat ");
1369 /* we will put 127 in the first byte of
1371 aopPut (AOP (res), "#127", 0);
1372 size = AOP_SIZE (op) - 1;
1375 _startLazyDPSEvaluation ();
1376 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1381 emitcode ("orl", "a,%s",
1383 offset++, FALSE, FALSE, FALSE));
1385 _endLazyDPSEvaluation ();
1386 tlbl = newiTempLabel (NULL);
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1488 /* The generic part of a generic pointer should
1489 * not participate in it's truth value.
1491 * i.e. 0x10000000 is zero.
1493 if (opIsGptr (oper))
1495 D (emitcode (";", "toBoolean: generic ptr special case.");
1500 _startLazyDPSEvaluation ();
1501 if (AOP_NEEDSACC (oper))
1503 emitcode ("push", "b");
1504 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1508 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1512 if (AOP_NEEDSACC (oper))
1514 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1518 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1521 _endLazyDPSEvaluation ();
1523 if (AOP_NEEDSACC (oper))
1525 emitcode ("mov", "a,b");
1526 emitcode ("pop", "b");
1531 /*-----------------------------------------------------------------*/
1532 /* genNot - generate code for ! operation */
1533 /*-----------------------------------------------------------------*/
1538 sym_link *optype = operandType (IC_LEFT (ic));
1540 D (emitcode (";", "genNot ");
1543 /* assign asmOps to operand & result */
1544 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1545 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1547 /* if in bit space then a special case */
1548 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1550 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1551 emitcode ("cpl", "c");
1552 outBitC (IC_RESULT (ic));
1556 /* if type float then do float */
1557 if (IS_FLOAT (optype))
1559 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1563 toBoolean (IC_LEFT (ic));
1565 tlbl = newiTempLabel (NULL);
1566 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1567 emitcode ("", "%05d$:", tlbl->key + 100);
1568 outBitC (IC_RESULT (ic));
1571 /* release the aops */
1572 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1573 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1577 /*-----------------------------------------------------------------*/
1578 /* genCpl - generate code for complement */
1579 /*-----------------------------------------------------------------*/
1586 D (emitcode (";", "genCpl ");
1590 /* assign asmOps to operand & result */
1591 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1592 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1594 /* if both are in bit space then
1596 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1597 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1600 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1601 emitcode ("cpl", "c");
1602 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1606 size = AOP_SIZE (IC_RESULT (ic));
1607 _startLazyDPSEvaluation ();
1610 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1612 emitcode ("cpl", "a");
1613 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1615 _endLazyDPSEvaluation ();
1619 /* release the aops */
1620 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1621 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1624 /*-----------------------------------------------------------------*/
1625 /* genUminusFloat - unary minus for floating points */
1626 /*-----------------------------------------------------------------*/
1628 genUminusFloat (operand * op, operand * result)
1630 int size, offset = 0;
1632 /* for this we just need to flip the
1633 first it then copy the rest in place */
1634 D (emitcode (";", "genUminusFloat");
1637 _startLazyDPSEvaluation ();
1638 size = AOP_SIZE (op) - 1;
1639 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1642 emitcode ("cpl", "acc.7");
1643 aopPut (AOP (result), "a", 3);
1647 aopPut (AOP (result),
1648 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1652 _endLazyDPSEvaluation ();
1655 /*-----------------------------------------------------------------*/
1656 /* genUminus - unary minus code generation */
1657 /*-----------------------------------------------------------------*/
1659 genUminus (iCode * ic)
1662 sym_link *optype, *rtype;
1664 D (emitcode (";", "genUminus ");
1669 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1670 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1672 /* if both in bit space then special
1674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1675 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1678 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1679 emitcode ("cpl", "c");
1680 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1684 optype = operandType (IC_LEFT (ic));
1685 rtype = operandType (IC_RESULT (ic));
1687 /* if float then do float stuff */
1688 if (IS_FLOAT (optype))
1690 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1694 /* otherwise subtract from zero */
1695 size = AOP_SIZE (IC_LEFT (ic));
1697 _startLazyDPSEvaluation ();
1700 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1701 if (!strcmp (l, "a"))
1705 emitcode ("cpl", "a");
1706 emitcode ("addc", "a,#0");
1712 emitcode ("clr", "a");
1713 emitcode ("subb", "a,%s", l);
1715 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1717 _endLazyDPSEvaluation ();
1719 /* if any remaining bytes in the result */
1720 /* we just need to propagate the sign */
1721 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1723 emitcode ("rlc", "a");
1724 emitcode ("subb", "a,acc");
1726 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1730 /* release the aops */
1731 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1732 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1735 /*-----------------------------------------------------------------*/
1736 /* saveRegisters - will look for a call and save the registers */
1737 /*-----------------------------------------------------------------*/
1739 saveRegisters (iCode * lic)
1747 for (ic = lic; ic; ic = ic->next)
1748 if (ic->op == CALL || ic->op == PCALL)
1753 fprintf (stderr, "found parameter push with no function call\n");
1757 /* if the registers have been saved already then
1759 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1762 /* find the registers in use at this time
1763 and push them away to safety */
1764 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1768 if (options.useXstack)
1770 if (bitVectBitValue (rsave, R0_IDX))
1771 emitcode ("mov", "b,r0");
1772 emitcode ("mov", "r0,%s", spname);
1773 for (i = 0; i < ds390_nRegs; i++)
1775 if (bitVectBitValue (rsave, i))
1778 emitcode ("mov", "a,b");
1780 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1781 emitcode ("movx", "@r0,a");
1782 emitcode ("inc", "r0");
1785 emitcode ("mov", "%s,r0", spname);
1786 if (bitVectBitValue (rsave, R0_IDX))
1787 emitcode ("mov", "r0,b");
1790 for (i = 0; i < ds390_nRegs; i++)
1792 if (bitVectBitValue (rsave, i))
1793 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1796 detype = getSpec (operandType (IC_LEFT (ic)));
1798 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1799 IS_ISR (currFunc->etype) &&
1802 saverbank (SPEC_BANK (detype), ic, TRUE);
1805 /*-----------------------------------------------------------------*/
1806 /* unsaveRegisters - pop the pushed registers */
1807 /*-----------------------------------------------------------------*/
1809 unsaveRegisters (iCode * ic)
1813 /* find the registers in use at this time
1814 and push them away to safety */
1815 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1818 if (options.useXstack)
1820 emitcode ("mov", "r0,%s", spname);
1821 for (i = ds390_nRegs; i >= 0; i--)
1823 if (bitVectBitValue (rsave, i))
1825 emitcode ("dec", "r0");
1826 emitcode ("movx", "a,@r0");
1828 emitcode ("mov", "b,a");
1830 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1834 emitcode ("mov", "%s,r0", spname);
1835 if (bitVectBitValue (rsave, R0_IDX))
1836 emitcode ("mov", "r0,b");
1839 for (i = ds390_nRegs; i >= 0; i--)
1841 if (bitVectBitValue (rsave, i))
1842 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1848 /*-----------------------------------------------------------------*/
1850 /*-----------------------------------------------------------------*/
1852 pushSide (operand * oper, int size)
1855 _startLazyDPSEvaluation ();
1858 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1859 if (AOP_TYPE (oper) != AOP_REG &&
1860 AOP_TYPE (oper) != AOP_DIR &&
1863 emitcode ("mov", "a,%s", l);
1864 emitcode ("push", "acc");
1867 emitcode ("push", "%s", l);
1869 _endLazyDPSEvaluation ();
1872 /*-----------------------------------------------------------------*/
1873 /* assignResultValue - */
1874 /*-----------------------------------------------------------------*/
1876 assignResultValue (operand * oper)
1879 int size = AOP_SIZE (oper);
1881 _startLazyDPSEvaluation ();
1884 aopPut (AOP (oper), fReturn[offset], offset);
1887 _endLazyDPSEvaluation ();
1891 /*-----------------------------------------------------------------*/
1892 /* genXpush - pushes onto the external stack */
1893 /*-----------------------------------------------------------------*/
1895 genXpush (iCode * ic)
1897 asmop *aop = newAsmop (0);
1899 int size, offset = 0;
1901 D (emitcode (";", "genXpush ");
1904 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1905 r = getFreePtr (ic, &aop, FALSE);
1908 emitcode ("mov", "%s,_spx", r->name);
1910 size = AOP_SIZE (IC_LEFT (ic));
1911 _startLazyDPSEvaluation ();
1915 char *l = aopGet (AOP (IC_LEFT (ic)),
1916 offset++, FALSE, FALSE, TRUE);
1918 emitcode ("movx", "@%s,a", r->name);
1919 emitcode ("inc", "%s", r->name);
1922 _endLazyDPSEvaluation ();
1925 emitcode ("mov", "_spx,%s", r->name);
1927 freeAsmop (NULL, aop, ic, TRUE);
1928 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1931 /*-----------------------------------------------------------------*/
1932 /* genIpush - genrate code for pushing this gets a little complex */
1933 /*-----------------------------------------------------------------*/
1935 genIpush (iCode * ic)
1937 int size, offset = 0;
1940 D (emitcode (";", "genIpush ");
1943 /* if this is not a parm push : ie. it is spill push
1944 and spill push is always done on the local stack */
1948 /* and the item is spilt then do nothing */
1949 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1952 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1953 size = AOP_SIZE (IC_LEFT (ic));
1954 /* push it on the stack */
1955 _startLazyDPSEvaluation ();
1958 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1964 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1966 _endLazyDPSEvaluation ();
1970 /* this is a paramter push: in this case we call
1971 the routine to find the call and save those
1972 registers that need to be saved */
1975 /* if use external stack then call the external
1976 stack pushing routine */
1977 if (options.useXstack)
1983 /* then do the push */
1984 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1986 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1987 size = AOP_SIZE (IC_LEFT (ic));
1989 _startLazyDPSEvaluation ();
1992 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1993 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1994 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1997 emitcode ("mov", "a,%s", l);
1998 emitcode ("push", "acc");
2001 emitcode ("push", "%s ;jwk genIpush", l);
2003 _endLazyDPSEvaluation ();
2005 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2008 /*-----------------------------------------------------------------*/
2009 /* genIpop - recover the registers: can happen only for spilling */
2010 /*-----------------------------------------------------------------*/
2012 genIpop (iCode * ic)
2016 D (emitcode (";", "genIpop ");
2020 /* if the temp was not pushed then */
2021 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2024 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2025 size = AOP_SIZE (IC_LEFT (ic));
2026 offset = (size - 1);
2027 _startLazyDPSEvaluation ();
2030 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2031 FALSE, TRUE, TRUE));
2033 _endLazyDPSEvaluation ();
2035 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2038 /*-----------------------------------------------------------------*/
2039 /* unsaverbank - restores the resgister bank from stack */
2040 /*-----------------------------------------------------------------*/
2042 unsaverbank (int bank, iCode * ic, bool popPsw)
2050 if (options.useXstack)
2053 r = getFreePtr (ic, &aop, FALSE);
2056 emitcode ("mov", "%s,_spx", r->name);
2057 emitcode ("movx", "a,@%s", r->name);
2058 emitcode ("mov", "psw,a");
2059 emitcode ("dec", "%s", r->name);
2063 emitcode ("pop", "psw");
2066 for (i = (ds390_nRegs - 1); i >= 0; i--)
2068 if (options.useXstack)
2070 emitcode ("movx", "a,@%s", r->name);
2071 emitcode ("mov", "(%s+%d),a",
2072 regs390[i].base, 8 * bank + regs390[i].offset);
2073 emitcode ("dec", "%s", r->name);
2077 emitcode ("pop", "(%s+%d)",
2078 regs390[i].base, 8 * bank + regs390[i].offset);
2081 if (options.useXstack)
2084 emitcode ("mov", "_spx,%s", r->name);
2085 freeAsmop (NULL, aop, ic, TRUE);
2090 /*-----------------------------------------------------------------*/
2091 /* saverbank - saves an entire register bank on the stack */
2092 /*-----------------------------------------------------------------*/
2094 saverbank (int bank, iCode * ic, bool pushPsw)
2100 if (options.useXstack)
2104 r = getFreePtr (ic, &aop, FALSE);
2105 emitcode ("mov", "%s,_spx", r->name);
2109 for (i = 0; i < ds390_nRegs; i++)
2111 if (options.useXstack)
2113 emitcode ("inc", "%s", r->name);
2114 emitcode ("mov", "a,(%s+%d)",
2115 regs390[i].base, 8 * bank + regs390[i].offset);
2116 emitcode ("movx", "@%s,a", r->name);
2119 emitcode ("push", "(%s+%d)",
2120 regs390[i].base, 8 * bank + regs390[i].offset);
2125 if (options.useXstack)
2127 emitcode ("mov", "a,psw");
2128 emitcode ("movx", "@%s,a", r->name);
2129 emitcode ("inc", "%s", r->name);
2130 emitcode ("mov", "_spx,%s", r->name);
2131 freeAsmop (NULL, aop, ic, TRUE);
2135 emitcode ("push", "psw");
2137 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2143 /*-----------------------------------------------------------------*/
2144 /* genCall - generates a call statement */
2145 /*-----------------------------------------------------------------*/
2147 genCall (iCode * ic)
2151 D (emitcode (";", "genCall ");
2154 /* if caller saves & we have not saved then */
2158 /* if we are calling a function that is not using
2159 the same register bank then we need to save the
2160 destination registers on the stack */
2161 detype = getSpec (operandType (IC_LEFT (ic)));
2163 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2164 IS_ISR (currFunc->etype) &&
2167 saverbank (SPEC_BANK (detype), ic, TRUE);
2169 /* if send set is not empty the assign */
2174 for (sic = setFirstItem (_G.sendSet); sic;
2175 sic = setNextItem (_G.sendSet))
2177 int size, offset = 0;
2179 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2180 size = AOP_SIZE (IC_LEFT (sic));
2182 _startLazyDPSEvaluation ();
2185 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2186 FALSE, FALSE, TRUE);
2187 if (strcmp (l, fReturn[offset])) {
2190 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2196 _endLazyDPSEvaluation ();
2197 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2202 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2203 OP_SYMBOL (IC_LEFT (ic))->rname :
2204 OP_SYMBOL (IC_LEFT (ic))->name));
2206 /* if we need assign a result value */
2207 if ((IS_ITEMP (IC_RESULT (ic)) &&
2208 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2209 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2210 IS_TRUE_SYMOP (IC_RESULT (ic)))
2212 if (isOperandInFarSpace (IC_RESULT (ic))
2213 && getSize (operandType (IC_RESULT (ic))) <= 2)
2215 int size = getSize (operandType (IC_RESULT (ic)));
2217 /* Special case for 1 or 2 byte return in far space. */
2218 emitcode (";", "Kevin function call abuse #1");
2223 emitcode ("mov", "b,%s", fReturn[1]);
2226 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2227 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2231 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2233 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2238 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2241 assignResultValue (IC_RESULT (ic));
2243 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2247 /* adjust the stack for parameters if
2249 if (IC_LEFT (ic)->parmBytes)
2252 if (IC_LEFT (ic)->parmBytes > 3)
2254 emitcode ("mov", "a,%s", spname);
2255 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
2256 emitcode ("mov", "%s,a", spname);
2259 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
2260 emitcode ("dec", "%s", spname);
2264 /* if register bank was saved then pop them */
2266 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2268 /* if we hade saved some registers then unsave them */
2269 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2270 unsaveRegisters (ic);
2275 /*-----------------------------------------------------------------*/
2276 /* genPcall - generates a call by pointer statement */
2277 /*-----------------------------------------------------------------*/
2279 genPcall (iCode * ic)
2282 symbol *rlbl = newiTempLabel (NULL);
2284 D (emitcode (";", "genPcall ");
2288 /* if caller saves & we have not saved then */
2292 /* if we are calling a function that is not using
2293 the same register bank then we need to save the
2294 destination registers on the stack */
2295 detype = getSpec (operandType (IC_LEFT (ic)));
2297 IS_ISR (currFunc->etype) &&
2298 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2299 saverbank (SPEC_BANK (detype), ic, TRUE);
2302 /* push the return address on to the stack */
2303 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2304 emitcode ("push", "acc");
2305 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2306 emitcode ("push", "acc");
2308 if (options.model == MODEL_FLAT24)
2310 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2311 emitcode ("push", "acc");
2314 /* now push the calling address */
2315 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2317 pushSide (IC_LEFT (ic), FPTRSIZE);
2319 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2321 /* if send set is not empty the assign */
2326 for (sic = setFirstItem (_G.sendSet); sic;
2327 sic = setNextItem (_G.sendSet))
2329 int size, offset = 0;
2331 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2332 size = AOP_SIZE (IC_LEFT (sic));
2333 _startLazyDPSEvaluation ();
2336 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2337 FALSE, FALSE, TRUE);
2338 if (strcmp (l, fReturn[offset]))
2340 emitcode ("mov", "%s,%s",
2346 _endLazyDPSEvaluation ();
2347 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2352 emitcode ("ret", "");
2353 emitcode ("", "%05d$:", (rlbl->key + 100));
2356 /* if we need assign a result value */
2357 if ((IS_ITEMP (IC_RESULT (ic)) &&
2358 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2359 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2360 IS_TRUE_SYMOP (IC_RESULT (ic)))
2364 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2367 assignResultValue (IC_RESULT (ic));
2369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2372 /* adjust the stack for parameters if
2374 if (IC_LEFT (ic)->parmBytes)
2377 if (IC_LEFT (ic)->parmBytes > 3)
2379 emitcode ("mov", "a,%s", spname);
2380 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
2381 emitcode ("mov", "%s,a", spname);
2384 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
2385 emitcode ("dec", "%s", spname);
2389 /* if register bank was saved then unsave them */
2391 (SPEC_BANK (currFunc->etype) !=
2392 SPEC_BANK (detype)))
2393 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2395 /* if we hade saved some registers then
2398 unsaveRegisters (ic);
2402 /*-----------------------------------------------------------------*/
2403 /* resultRemat - result is rematerializable */
2404 /*-----------------------------------------------------------------*/
2406 resultRemat (iCode * ic)
2408 if (SKIP_IC (ic) || ic->op == IFX)
2411 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2413 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2414 if (sym->remat && !POINTER_SET (ic))
2421 #if defined(__BORLANDC__) || defined(_MSC_VER)
2422 #define STRCASECMP stricmp
2424 #define STRCASECMP strcasecmp
2427 /*-----------------------------------------------------------------*/
2428 /* inExcludeList - return 1 if the string is in exclude Reg list */
2429 /*-----------------------------------------------------------------*/
2431 inExcludeList (char *s)
2435 if (options.excludeRegs[i] &&
2436 STRCASECMP (options.excludeRegs[i], "none") == 0)
2439 for (i = 0; options.excludeRegs[i]; i++)
2441 if (options.excludeRegs[i] &&
2442 STRCASECMP (s, options.excludeRegs[i]) == 0)
2448 /*-----------------------------------------------------------------*/
2449 /* genFunction - generated code for function entry */
2450 /*-----------------------------------------------------------------*/
2452 genFunction (iCode * ic)
2457 D (emitcode (";", "genFunction ");
2461 /* create the function header */
2462 emitcode (";", "-----------------------------------------");
2463 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2464 emitcode (";", "-----------------------------------------");
2466 emitcode ("", "%s:", sym->rname);
2467 fetype = getSpec (operandType (IC_LEFT (ic)));
2469 /* if critical function then turn interrupts off */
2470 if (SPEC_CRTCL (fetype))
2471 emitcode ("clr", "ea");
2473 /* here we need to generate the equates for the
2474 register bank if required */
2475 if (SPEC_BANK (fetype) != rbank)
2479 rbank = SPEC_BANK (fetype);
2480 for (i = 0; i < ds390_nRegs; i++)
2482 if (strcmp (regs390[i].base, "0") == 0)
2483 emitcode ("", "%s = 0x%02x",
2485 8 * rbank + regs390[i].offset);
2487 emitcode ("", "%s = %s + 0x%02x",
2490 8 * rbank + regs390[i].offset);
2494 /* if this is an interrupt service routine then
2495 save acc, b, dpl, dph */
2496 if (IS_ISR (sym->etype))
2499 if (!inExcludeList ("acc"))
2500 emitcode ("push", "acc");
2501 if (!inExcludeList ("b"))
2502 emitcode ("push", "b");
2503 if (!inExcludeList ("dpl"))
2504 emitcode ("push", "dpl");
2505 if (!inExcludeList ("dph"))
2506 emitcode ("push", "dph");
2507 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2509 emitcode ("push", "dpx");
2510 /* Make sure we're using standard DPTR */
2511 emitcode ("push", "dps");
2512 emitcode ("mov", "dps, #0x00");
2513 if (options.stack10bit)
2515 /* This ISR could conceivably use DPTR2. Better save it. */
2516 emitcode ("push", "dpl1");
2517 emitcode ("push", "dph1");
2518 emitcode ("push", "dpx1");
2519 emitcode ("push", "ap");
2522 /* if this isr has no bank i.e. is going to
2523 run with bank 0 , then we need to save more
2525 if (!SPEC_BANK (sym->etype))
2528 /* if this function does not call any other
2529 function then we can be economical and
2530 save only those registers that are used */
2535 /* if any registers used */
2538 /* save the registers used */
2539 for (i = 0; i < sym->regsUsed->size; i++)
2541 if (bitVectBitValue (sym->regsUsed, i) ||
2542 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2543 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2550 /* this function has a function call cannot
2551 determines register usage so we will have the
2553 saverbank (0, ic, FALSE);
2559 /* if callee-save to be used for this function
2560 then save the registers being used in this function */
2561 if (sym->calleeSave)
2565 /* if any registers used */
2568 /* save the registers used */
2569 for (i = 0; i < sym->regsUsed->size; i++)
2571 if (bitVectBitValue (sym->regsUsed, i) ||
2572 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2574 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2582 /* set the register bank to the desired value */
2583 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2585 emitcode ("push", "psw");
2586 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2589 if (IS_RENT (sym->etype) || options.stackAuto)
2592 if (options.useXstack)
2594 emitcode ("mov", "r0,%s", spname);
2595 emitcode ("mov", "a,_bp");
2596 emitcode ("movx", "@r0,a");
2597 emitcode ("inc", "%s", spname);
2601 /* set up the stack */
2602 emitcode ("push", "_bp"); /* save the callers stack */
2604 emitcode ("mov", "_bp,%s", spname);
2607 /* adjust the stack for the function */
2613 werror (W_STACK_OVERFLOW, sym->name);
2615 if (i > 3 && sym->recvSize < 4)
2618 emitcode ("mov", "a,sp");
2619 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2620 emitcode ("mov", "sp,a");
2625 emitcode ("inc", "sp");
2631 emitcode ("mov", "a,_spx");
2632 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2633 emitcode ("mov", "_spx,a");
2638 /*-----------------------------------------------------------------*/
2639 /* genEndFunction - generates epilogue for functions */
2640 /*-----------------------------------------------------------------*/
2642 genEndFunction (iCode * ic)
2644 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2646 D (emitcode (";", "genEndFunction ");
2649 if (IS_RENT (sym->etype) || options.stackAuto)
2651 emitcode ("mov", "%s,_bp", spname);
2654 /* if use external stack but some variables were
2655 added to the local stack then decrement the
2657 if (options.useXstack && sym->stack)
2659 emitcode ("mov", "a,sp");
2660 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2661 emitcode ("mov", "sp,a");
2665 if ((IS_RENT (sym->etype) || options.stackAuto))
2667 if (options.useXstack)
2669 emitcode ("mov", "r0,%s", spname);
2670 emitcode ("movx", "a,@r0");
2671 emitcode ("mov", "_bp,a");
2672 emitcode ("dec", "%s", spname);
2676 emitcode ("pop", "_bp");
2680 /* restore the register bank */
2681 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2682 emitcode ("pop", "psw");
2684 if (IS_ISR (sym->etype))
2687 /* now we need to restore the registers */
2688 /* if this isr has no bank i.e. is going to
2689 run with bank 0 , then we need to save more
2691 if (!SPEC_BANK (sym->etype))
2694 /* if this function does not call any other
2695 function then we can be economical and
2696 save only those registers that are used */
2701 /* if any registers used */
2704 /* save the registers used */
2705 for (i = sym->regsUsed->size; i >= 0; i--)
2707 if (bitVectBitValue (sym->regsUsed, i) ||
2708 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2709 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2716 /* this function has a function call cannot
2717 determines register usage so we will have the
2719 unsaverbank (0, ic, FALSE);
2723 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2725 if (options.stack10bit)
2727 emitcode ("pop", "ap");
2728 emitcode ("pop", "dpx1");
2729 emitcode ("pop", "dph1");
2730 emitcode ("pop", "dpl1");
2732 emitcode ("pop", "dps");
2733 emitcode ("pop", "dpx");
2735 if (!inExcludeList ("dph"))
2736 emitcode ("pop", "dph");
2737 if (!inExcludeList ("dpl"))
2738 emitcode ("pop", "dpl");
2739 if (!inExcludeList ("b"))
2740 emitcode ("pop", "b");
2741 if (!inExcludeList ("acc"))
2742 emitcode ("pop", "acc");
2744 if (SPEC_CRTCL (sym->etype))
2745 emitcode ("setb", "ea");
2747 /* if debug then send end of function */
2748 /* if (options.debug && currFunc) { */
2752 emitcode ("", "C$%s$%d$%d$%d ==.",
2753 FileBaseName (ic->filename), currFunc->lastLine,
2754 ic->level, ic->block);
2755 if (IS_STATIC (currFunc->etype))
2756 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2758 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2762 emitcode ("reti", "");
2766 if (SPEC_CRTCL (sym->etype))
2767 emitcode ("setb", "ea");
2769 if (sym->calleeSave)
2773 /* if any registers used */
2776 /* save the registers used */
2777 for (i = sym->regsUsed->size; i >= 0; i--)
2779 if (bitVectBitValue (sym->regsUsed, i) ||
2780 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2781 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2787 /* if debug then send end of function */
2791 emitcode ("", "C$%s$%d$%d$%d ==.",
2792 FileBaseName (ic->filename), currFunc->lastLine,
2793 ic->level, ic->block);
2794 if (IS_STATIC (currFunc->etype))
2795 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2797 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2801 emitcode ("ret", "");
2806 /*-----------------------------------------------------------------*/
2807 /* genRet - generate code for return statement */
2808 /*-----------------------------------------------------------------*/
2812 int size, offset = 0, pushed = 0;
2814 D (emitcode (";", "genRet ");
2817 /* if we have no return value then
2818 just generate the "ret" */
2822 /* we have something to return then
2823 move the return value into place */
2824 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2825 size = AOP_SIZE (IC_LEFT (ic));
2827 _startLazyDPSEvaluation ();
2831 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2833 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2834 FALSE, TRUE, FALSE);
2835 emitcode ("push", "%s", l);
2840 l = aopGet (AOP (IC_LEFT (ic)), offset,
2841 FALSE, FALSE, FALSE);
2842 if (strcmp (fReturn[offset], l))
2843 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2846 _endLazyDPSEvaluation ();
2853 if (strcmp (fReturn[pushed], "a"))
2854 emitcode ("pop", fReturn[pushed]);
2856 emitcode ("pop", "acc");
2859 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2862 /* generate a jump to the return label
2863 if the next is not the return statement */
2864 if (!(ic->next && ic->next->op == LABEL &&
2865 IC_LABEL (ic->next) == returnLabel))
2867 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2871 /*-----------------------------------------------------------------*/
2872 /* genLabel - generates a label */
2873 /*-----------------------------------------------------------------*/
2875 genLabel (iCode * ic)
2877 /* special case never generate */
2878 if (IC_LABEL (ic) == entryLabel)
2881 D (emitcode (";", "genLabel ");
2884 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2887 /*-----------------------------------------------------------------*/
2888 /* genGoto - generates a ljmp */
2889 /*-----------------------------------------------------------------*/
2891 genGoto (iCode * ic)
2893 D (emitcode (";", "genGoto ");
2895 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2898 /*-----------------------------------------------------------------*/
2899 /* findLabelBackwards: walks back through the iCode chain looking */
2900 /* for the given label. Returns number of iCode instructions */
2901 /* between that label and given ic. */
2902 /* Returns zero if label not found. */
2903 /*-----------------------------------------------------------------*/
2905 findLabelBackwards (iCode * ic, int key)
2914 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2916 /* printf("findLabelBackwards = %d\n", count); */
2924 /*-----------------------------------------------------------------*/
2925 /* genPlusIncr :- does addition with increment if possible */
2926 /*-----------------------------------------------------------------*/
2928 genPlusIncr (iCode * ic)
2930 unsigned int icount;
2931 unsigned int size = getDataSize (IC_RESULT (ic));
2933 /* will try to generate an increment */
2934 /* if the right side is not a literal
2936 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2939 /* if the literal value of the right hand side
2940 is greater than 4 then it is not worth it */
2941 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2944 /* if increment 16 bits in register */
2946 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2947 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2948 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2956 /* If the next instruction is a goto and the goto target
2957 * is <= 5 instructions previous to this, we can generate
2958 * jumps straight to that target.
2960 if (ic->next && ic->next->op == GOTO
2961 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2964 emitcode (";", "tail increment optimized (range %d)", labelRange);
2965 tlbl = IC_LABEL (ic->next);
2970 tlbl = newiTempLabel (NULL);
2973 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2974 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2975 IS_AOP_PREG (IC_RESULT (ic)))
2976 emitcode ("cjne", "%s,#0x00,%05d$"
2977 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2981 emitcode ("clr", "a");
2982 emitcode ("cjne", "a,%s,%05d$"
2983 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2987 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2990 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2991 IS_AOP_PREG (IC_RESULT (ic)))
2992 emitcode ("cjne", "%s,#0x00,%05d$"
2993 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2996 emitcode ("cjne", "a,%s,%05d$"
2997 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3000 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3004 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3005 IS_AOP_PREG (IC_RESULT (ic)))
3006 emitcode ("cjne", "%s,#0x00,%05d$"
3007 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3011 emitcode ("cjne", "a,%s,%05d$"
3012 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3015 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3020 emitcode ("", "%05d$:", tlbl->key + 100);
3025 /* if the sizes are greater than 1 then we cannot */
3026 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3027 AOP_SIZE (IC_LEFT (ic)) > 1)
3030 /* we can if the aops of the left & result match or
3031 if they are in registers and the registers are the
3034 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3035 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3036 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3041 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3042 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3043 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3048 _startLazyDPSEvaluation ();
3051 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3053 _endLazyDPSEvaluation ();
3062 /*-----------------------------------------------------------------*/
3063 /* outBitAcc - output a bit in acc */
3064 /*-----------------------------------------------------------------*/
3066 outBitAcc (operand * result)
3068 symbol *tlbl = newiTempLabel (NULL);
3069 /* if the result is a bit */
3070 if (AOP_TYPE (result) == AOP_CRY)
3072 aopPut (AOP (result), "a", 0);
3076 emitcode ("jz", "%05d$", tlbl->key + 100);
3077 emitcode ("mov", "a,%s", one);
3078 emitcode ("", "%05d$:", tlbl->key + 100);
3083 /*-----------------------------------------------------------------*/
3084 /* genPlusBits - generates code for addition of two bits */
3085 /*-----------------------------------------------------------------*/
3087 genPlusBits (iCode * ic)
3089 D (emitcode (";", "genPlusBits ");
3091 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3093 symbol *lbl = newiTempLabel (NULL);
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3096 emitcode ("cpl", "c");
3097 emitcode ("", "%05d$:", (lbl->key + 100));
3098 outBitC (IC_RESULT (ic));
3102 emitcode ("clr", "a");
3103 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3104 emitcode ("rlc", "a");
3105 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3106 emitcode ("addc", "a,#0x00");
3107 outAcc (IC_RESULT (ic));
3112 adjustArithmeticResult (iCode * ic)
3114 if (opIsGptr (IC_RESULT (ic)) &&
3115 opIsGptr (IC_LEFT (ic)) &&
3116 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3118 aopPut (AOP (IC_RESULT (ic)),
3119 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3123 if (opIsGptr (IC_RESULT (ic)) &&
3124 opIsGptr (IC_RIGHT (ic)) &&
3125 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3127 aopPut (AOP (IC_RESULT (ic)),
3128 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3132 if (opIsGptr (IC_RESULT (ic)) &&
3133 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3134 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3135 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3139 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3140 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3144 #define AOP_OP_3(ic) \
3145 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3146 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3147 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3148 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3149 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3150 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3152 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3154 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3157 #define AOP_OP_3_NOFATAL(ic, rc) \
3158 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3159 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3160 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3161 isOperandInFarSpace(IC_RESULT(ic))) \
3163 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3168 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3169 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3171 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3172 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3174 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3176 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3180 #define AOP_OP_2(ic) \
3181 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3182 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3184 #define AOP_SET_LOCALS(ic) \
3185 left = IC_LEFT(ic); \
3186 right = IC_RIGHT(ic); \
3187 result = IC_RESULT(ic);
3189 /*-----------------------------------------------------------------*/
3190 /* genPlus - generates code for addition */
3191 /*-----------------------------------------------------------------*/
3193 genPlus (iCode * ic)
3195 int size, offset = 0;
3196 bool pushResult = FALSE;
3199 D (emitcode (";", "genPlus ");
3202 /* special cases :- */
3204 AOP_OP_3_NOFATAL (ic, pushResult);
3207 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3213 /* if literal, literal on the right or
3214 if left requires ACC or right is already
3216 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3217 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3218 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3220 operand *t = IC_RIGHT (ic);
3221 IC_RIGHT (ic) = IC_LEFT (ic);
3223 emitcode (";", "Swapped plus args.");
3226 /* if both left & right are in bit
3228 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3229 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3235 /* if left in bit space & right literal */
3236 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3237 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3239 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3240 /* if result in bit space */
3241 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3243 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3244 emitcode ("cpl", "c");
3245 outBitC (IC_RESULT (ic));
3249 size = getDataSize (IC_RESULT (ic));
3250 _startLazyDPSEvaluation ();
3253 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3254 emitcode ("addc", "a,#00");
3255 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3257 _endLazyDPSEvaluation ();
3262 /* if I can do an increment instead
3263 of add then GOOD for ME */
3264 if (genPlusIncr (ic) == TRUE)
3266 emitcode (";", "did genPlusIncr");
3271 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3273 _startLazyDPSEvaluation ();
3276 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3278 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3280 emitcode ("add", "a,%s",
3281 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3283 emitcode ("addc", "a,%s",
3284 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3288 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3290 emitcode ("add", "a,%s",
3291 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3293 emitcode ("addc", "a,%s",
3294 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3298 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3302 emitcode ("push", "acc");
3306 _endLazyDPSEvaluation ();
3310 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3312 size = getDataSize (IC_LEFT (ic));
3313 rSize = getDataSize (IC_RESULT (ic));
3315 /* If the pushed data is bigger than the result,
3316 * simply discard unused bytes. Icky, but works.
3318 * Should we throw a warning here? We're losing data...
3320 while (size > rSize)
3322 D (emitcode (";", "discarding unused result byte.");
3324 emitcode ("pop", "acc");
3330 emitcode ("clr", "a");
3331 /* Conversly, we haven't pushed enough here.
3332 * just zero-pad, and all is well.
3334 while (size < rSize)
3336 emitcode ("push", "acc");
3342 _startLazyDPSEvaluation ();
3345 emitcode ("pop", "acc");
3346 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3348 _endLazyDPSEvaluation ();
3351 adjustArithmeticResult (ic);
3354 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3355 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3356 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3359 /*-----------------------------------------------------------------*/
3360 /* genMinusDec :- does subtraction with deccrement if possible */
3361 /*-----------------------------------------------------------------*/
3363 genMinusDec (iCode * ic)
3365 unsigned int icount;
3366 unsigned int size = getDataSize (IC_RESULT (ic));
3368 /* will try to generate an increment */
3369 /* if the right side is not a literal
3371 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3374 /* if the literal value of the right hand side
3375 is greater than 4 then it is not worth it */
3376 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3379 /* if decrement 16 bits in register */
3380 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3381 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3382 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3390 /* If the next instruction is a goto and the goto target
3391 * is <= 5 instructions previous to this, we can generate
3392 * jumps straight to that target.
3394 if (ic->next && ic->next->op == GOTO
3395 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3398 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3399 tlbl = IC_LABEL (ic->next);
3404 tlbl = newiTempLabel (NULL);
3408 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3409 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3410 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3411 IS_AOP_PREG (IC_RESULT (ic)))
3412 emitcode ("cjne", "%s,#0xff,%05d$"
3413 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3417 emitcode ("mov", "a,#0xff");
3418 emitcode ("cjne", "a,%s,%05d$"
3419 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3422 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3425 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3426 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3427 IS_AOP_PREG (IC_RESULT (ic)))
3428 emitcode ("cjne", "%s,#0xff,%05d$"
3429 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3433 emitcode ("cjne", "a,%s,%05d$"
3434 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3437 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3441 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3442 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3443 IS_AOP_PREG (IC_RESULT (ic)))
3444 emitcode ("cjne", "%s,#0xff,%05d$"
3445 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3449 emitcode ("cjne", "a,%s,%05d$"
3450 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3453 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3457 emitcode ("", "%05d$:", tlbl->key + 100);
3462 /* if the sizes are greater than 1 then we cannot */
3463 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3464 AOP_SIZE (IC_LEFT (ic)) > 1)
3467 /* we can if the aops of the left & result match or
3468 if they are in registers and the registers are the
3471 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3472 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3473 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3476 _startLazyDPSEvaluation ();
3479 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3481 _endLazyDPSEvaluation ();
3489 /*-----------------------------------------------------------------*/
3490 /* addSign - complete with sign */
3491 /*-----------------------------------------------------------------*/
3493 addSign (operand * result, int offset, int sign)
3495 int size = (getDataSize (result) - offset);
3500 emitcode ("rlc", "a");
3501 emitcode ("subb", "a,acc");
3503 aopPut (AOP (result), "a", offset++);
3507 aopPut (AOP (result), zero, offset++);
3511 /*-----------------------------------------------------------------*/
3512 /* genMinusBits - generates code for subtraction of two bits */
3513 /*-----------------------------------------------------------------*/
3515 genMinusBits (iCode * ic)
3517 symbol *lbl = newiTempLabel (NULL);
3519 D (emitcode (";", "genMinusBits ");
3522 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3524 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3525 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3526 emitcode ("cpl", "c");
3527 emitcode ("", "%05d$:", (lbl->key + 100));
3528 outBitC (IC_RESULT (ic));
3532 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3533 emitcode ("subb", "a,acc");
3534 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3535 emitcode ("inc", "a");
3536 emitcode ("", "%05d$:", (lbl->key + 100));
3537 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3538 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3542 /*-----------------------------------------------------------------*/
3543 /* genMinus - generates code for subtraction */
3544 /*-----------------------------------------------------------------*/
3546 genMinus (iCode * ic)
3548 int size, offset = 0;
3550 unsigned long lit = 0L;
3551 bool pushResult = FALSE;
3553 D (emitcode (";", "genMinus ");
3556 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3557 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3558 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3559 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3565 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3567 /* special cases :- */
3568 /* if both left & right are in bit space */
3569 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3570 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3576 /* if I can do an decrement instead
3577 of subtract then GOOD for ME */
3578 if (genMinusDec (ic) == TRUE)
3583 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3585 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3591 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3596 /* if literal, add a,#-lit, else normal subb */
3597 _startLazyDPSEvaluation ();
3600 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3601 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3602 emitcode ("subb", "a,%s",
3603 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3606 /* first add without previous c */
3608 emitcode ("add", "a,#0x%02x",
3609 (unsigned int) (lit & 0x0FFL));
3611 emitcode ("addc", "a,#0x%02x",
3612 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3617 emitcode ("push", "acc");
3621 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3625 _endLazyDPSEvaluation ();
3629 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3631 size = getDataSize (IC_LEFT (ic));
3632 rSize = getDataSize (IC_RESULT (ic));
3634 /* If the pushed data is bigger than the result,
3635 * simply discard unused bytes. Icky, but works.
3637 * Should we throw a warning here? We're losing data...
3639 while (size > getDataSize (IC_RESULT (ic)))
3641 emitcode (";", "discarding unused result byte.");
3642 emitcode ("pop", "acc");
3648 emitcode ("clr", "a");
3649 /* Conversly, we haven't pushed enough here.
3650 * just zero-pad, and all is well.
3652 while (size < rSize)
3654 emitcode ("push", "acc");
3662 emitcode ("pop", "acc");
3663 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3667 adjustArithmeticResult (ic);
3670 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3671 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3672 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3676 /*-----------------------------------------------------------------*/
3677 /* genMultbits :- multiplication of bits */
3678 /*-----------------------------------------------------------------*/
3680 genMultbits (operand * left,
3684 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3685 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3690 /*-----------------------------------------------------------------*/
3691 /* genMultOneByte : 8 bit multiplication & division */
3692 /*-----------------------------------------------------------------*/
3694 genMultOneByte (operand * left,
3698 sym_link *opetype = operandType (result);
3703 /* (if two literals, the value is computed before) */
3704 /* if one literal, literal on the right */
3705 if (AOP_TYPE (left) == AOP_LIT)
3712 size = AOP_SIZE (result);
3713 /* signed or unsigned */
3714 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3715 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3717 emitcode ("mul", "ab");
3718 /* if result size = 1, mul signed = mul unsigned */
3719 aopPut (AOP (result), "a", 0);
3722 if (SPEC_USIGN (opetype))
3724 aopPut (AOP (result), "b", 1);
3726 /* for filling the MSBs */
3727 emitcode ("clr", "a");
3731 emitcode ("mov", "a,b");
3733 /* adjust the MSB if left or right neg */
3735 /* if one literal */
3736 if (AOP_TYPE (right) == AOP_LIT)
3738 /* AND literal negative */
3739 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3741 /* adjust MSB (c==0 after mul) */
3742 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3747 lbl = newiTempLabel (NULL);
3748 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3749 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3750 emitcode ("", "%05d$:", (lbl->key + 100));
3751 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3752 lbl = newiTempLabel (NULL);
3753 emitcode ("jc", "%05d$", (lbl->key + 100));
3754 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3755 emitcode ("", "%05d$:", (lbl->key + 100));
3758 lbl = newiTempLabel (NULL);
3759 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3760 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3761 emitcode ("", "%05d$:", (lbl->key + 100));
3762 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3763 lbl = newiTempLabel (NULL);
3764 emitcode ("jc", "%05d$", (lbl->key + 100));
3765 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3766 emitcode ("", "%05d$:", (lbl->key + 100));
3768 aopPut (AOP (result), "a", 1);
3772 emitcode ("rlc", "a");
3773 emitcode ("subb", "a,acc");
3780 aopPut (AOP (result), "a", offset++);
3784 /*-----------------------------------------------------------------*/
3785 /* genMult - generates code for multiplication */
3786 /*-----------------------------------------------------------------*/
3788 genMult (iCode * ic)
3790 operand *left = IC_LEFT (ic);
3791 operand *right = IC_RIGHT (ic);
3792 operand *result = IC_RESULT (ic);
3794 D (emitcode (";", "genMult ");
3797 /* assign the amsops */
3800 /* special cases first */
3802 if (AOP_TYPE (left) == AOP_CRY &&
3803 AOP_TYPE (right) == AOP_CRY)
3805 genMultbits (left, right, result);
3809 /* if both are of size == 1 */
3810 if (AOP_SIZE (left) == 1 &&
3811 AOP_SIZE (right) == 1)
3813 genMultOneByte (left, right, result);
3817 /* should have been converted to function call */
3821 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3822 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3823 freeAsmop (result, NULL, ic, TRUE);
3826 /*-----------------------------------------------------------------*/
3827 /* genDivbits :- division of bits */
3828 /*-----------------------------------------------------------------*/
3830 genDivbits (operand * left,
3837 /* the result must be bit */
3838 LOAD_AB_FOR_DIV (left, right, l);
3839 emitcode ("div", "ab");
3840 emitcode ("rrc", "a");
3841 aopPut (AOP (result), "c", 0);
3844 /*-----------------------------------------------------------------*/
3845 /* genDivOneByte : 8 bit division */
3846 /*-----------------------------------------------------------------*/
3848 genDivOneByte (operand * left,
3852 sym_link *opetype = operandType (result);
3857 size = AOP_SIZE (result) - 1;
3859 /* signed or unsigned */
3860 if (SPEC_USIGN (opetype))
3862 /* unsigned is easy */
3863 LOAD_AB_FOR_DIV (left, right, l);
3864 emitcode ("div", "ab");
3865 aopPut (AOP (result), "a", 0);
3867 aopPut (AOP (result), zero, offset++);
3871 /* signed is a little bit more difficult */
3873 /* save the signs of the operands */
3874 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3876 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3877 emitcode ("push", "acc"); /* save it on the stack */
3879 /* now sign adjust for both left & right */
3880 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3882 lbl = newiTempLabel (NULL);
3883 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3884 emitcode ("cpl", "a");
3885 emitcode ("inc", "a");
3886 emitcode ("", "%05d$:", (lbl->key + 100));
3887 emitcode ("mov", "b,a");
3889 /* sign adjust left side */
3890 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3893 lbl = newiTempLabel (NULL);
3894 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3895 emitcode ("cpl", "a");
3896 emitcode ("inc", "a");
3897 emitcode ("", "%05d$:", (lbl->key + 100));
3899 /* now the division */
3900 emitcode ("nop", "; workaround for DS80C390 div bug.");
3901 emitcode ("div", "ab");
3902 /* we are interested in the lower order
3904 emitcode ("mov", "b,a");
3905 lbl = newiTempLabel (NULL);
3906 emitcode ("pop", "acc");
3907 /* if there was an over flow we don't
3908 adjust the sign of the result */
3909 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3910 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3912 emitcode ("clr", "a");
3913 emitcode ("subb", "a,b");
3914 emitcode ("mov", "b,a");
3915 emitcode ("", "%05d$:", (lbl->key + 100));
3917 /* now we are done */
3918 aopPut (AOP (result), "b", 0);
3921 emitcode ("mov", "c,b.7");
3922 emitcode ("subb", "a,acc");
3925 aopPut (AOP (result), "a", offset++);
3929 /*-----------------------------------------------------------------*/
3930 /* genDiv - generates code for division */
3931 /*-----------------------------------------------------------------*/
3935 operand *left = IC_LEFT (ic);
3936 operand *right = IC_RIGHT (ic);
3937 operand *result = IC_RESULT (ic);
3939 D (emitcode (";", "genDiv ");
3942 /* assign the amsops */
3945 /* special cases first */
3947 if (AOP_TYPE (left) == AOP_CRY &&
3948 AOP_TYPE (right) == AOP_CRY)
3950 genDivbits (left, right, result);
3954 /* if both are of size == 1 */
3955 if (AOP_SIZE (left) == 1 &&
3956 AOP_SIZE (right) == 1)
3958 genDivOneByte (left, right, result);
3962 /* should have been converted to function call */
3965 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3966 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3967 freeAsmop (result, NULL, ic, TRUE);
3970 /*-----------------------------------------------------------------*/
3971 /* genModbits :- modulus of bits */
3972 /*-----------------------------------------------------------------*/
3974 genModbits (operand * left,
3981 /* the result must be bit */
3982 LOAD_AB_FOR_DIV (left, right, l);
3983 emitcode ("div", "ab");
3984 emitcode ("mov", "a,b");
3985 emitcode ("rrc", "a");
3986 aopPut (AOP (result), "c", 0);
3989 /*-----------------------------------------------------------------*/
3990 /* genModOneByte : 8 bit modulus */
3991 /*-----------------------------------------------------------------*/
3993 genModOneByte (operand * left,
3997 sym_link *opetype = operandType (result);
4001 /* signed or unsigned */
4002 if (SPEC_USIGN (opetype))
4004 /* unsigned is easy */
4005 LOAD_AB_FOR_DIV (left, right, l);
4006 emitcode ("div", "ab");
4007 aopPut (AOP (result), "b", 0);
4011 /* signed is a little bit more difficult */
4013 /* save the signs of the operands */
4014 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4017 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4018 emitcode ("push", "acc"); /* save it on the stack */
4020 /* now sign adjust for both left & right */
4021 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4024 lbl = newiTempLabel (NULL);
4025 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4026 emitcode ("cpl", "a");
4027 emitcode ("inc", "a");
4028 emitcode ("", "%05d$:", (lbl->key + 100));
4029 emitcode ("mov", "b,a");
4031 /* sign adjust left side */
4032 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4035 lbl = newiTempLabel (NULL);
4036 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4037 emitcode ("cpl", "a");
4038 emitcode ("inc", "a");
4039 emitcode ("", "%05d$:", (lbl->key + 100));
4041 /* now the multiplication */
4042 emitcode ("nop", "; workaround for DS80C390 div bug.");
4043 emitcode ("div", "ab");
4044 /* we are interested in the lower order
4046 lbl = newiTempLabel (NULL);
4047 emitcode ("pop", "acc");
4048 /* if there was an over flow we don't
4049 adjust the sign of the result */
4050 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4051 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4053 emitcode ("clr", "a");
4054 emitcode ("subb", "a,b");
4055 emitcode ("mov", "b,a");
4056 emitcode ("", "%05d$:", (lbl->key + 100));
4058 /* now we are done */
4059 aopPut (AOP (result), "b", 0);
4063 /*-----------------------------------------------------------------*/
4064 /* genMod - generates code for division */
4065 /*-----------------------------------------------------------------*/
4069 operand *left = IC_LEFT (ic);
4070 operand *right = IC_RIGHT (ic);
4071 operand *result = IC_RESULT (ic);
4073 D (emitcode (";", "genMod ");
4076 /* assign the amsops */
4079 /* special cases first */
4081 if (AOP_TYPE (left) == AOP_CRY &&
4082 AOP_TYPE (right) == AOP_CRY)
4084 genModbits (left, right, result);
4088 /* if both are of size == 1 */
4089 if (AOP_SIZE (left) == 1 &&
4090 AOP_SIZE (right) == 1)
4092 genModOneByte (left, right, result);
4096 /* should have been converted to function call */
4100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (result, NULL, ic, TRUE);
4105 /*-----------------------------------------------------------------*/
4106 /* genIfxJump :- will create a jump depending on the ifx */
4107 /*-----------------------------------------------------------------*/
4109 genIfxJump (iCode * ic, char *jval)
4112 symbol *tlbl = newiTempLabel (NULL);
4115 D (emitcode (";", "genIfxJump ");
4118 /* if true label then we jump if condition
4122 jlbl = IC_TRUE (ic);
4123 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4124 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4128 /* false label is present */
4129 jlbl = IC_FALSE (ic);
4130 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4131 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4133 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4134 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4136 emitcode (inst, "%05d$", tlbl->key + 100);
4137 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4138 emitcode ("", "%05d$:", tlbl->key + 100);
4140 /* mark the icode as generated */
4144 /*-----------------------------------------------------------------*/
4145 /* genCmp :- greater or less than comparison */
4146 /*-----------------------------------------------------------------*/
4148 genCmp (operand * left, operand * right,
4149 iCode * ic, iCode * ifx, int sign)
4151 int size, offset = 0;
4152 unsigned long lit = 0L;
4155 D (emitcode (";", "genCmp");
4158 result = IC_RESULT (ic);
4160 /* if left & right are bit variables */
4161 if (AOP_TYPE (left) == AOP_CRY &&
4162 AOP_TYPE (right) == AOP_CRY)
4164 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4165 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4169 /* subtract right from left if at the
4170 end the carry flag is set then we know that
4171 left is greater than right */
4172 size = max (AOP_SIZE (left), AOP_SIZE (right));
4174 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4175 if ((size == 1) && !sign &&
4176 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4178 symbol *lbl = newiTempLabel (NULL);
4179 emitcode ("cjne", "%s,%s,%05d$",
4180 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4181 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4183 emitcode ("", "%05d$:", lbl->key + 100);
4187 if (AOP_TYPE (right) == AOP_LIT)
4189 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4190 /* optimize if(x < 0) or if(x >= 0) */
4199 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4201 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4202 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4204 aopOp (result, ic, FALSE, FALSE);
4206 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4208 freeAsmop (result, NULL, ic, TRUE);
4209 genIfxJump (ifx, "acc.7");
4214 emitcode ("rlc", "a");
4216 goto release_freedLR;
4224 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4225 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4226 emitcode (";", "genCmp #2");
4227 if (sign && (size == 0))
4229 emitcode (";", "genCmp #3");
4230 emitcode ("xrl", "a,#0x80");
4231 if (AOP_TYPE (right) == AOP_LIT)
4233 unsigned long lit = (unsigned long)
4234 floatFromVal (AOP (right)->aopu.aop_lit);
4235 emitcode (";", "genCmp #3.1");
4236 emitcode ("subb", "a,#0x%02x",
4237 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4241 emitcode (";", "genCmp #3.2");
4242 if (AOP_NEEDSACC (right))
4244 emitcode ("push", "acc");
4246 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4247 FALSE, FALSE, FALSE));
4248 emitcode ("xrl", "b,#0x80");
4249 if (AOP_NEEDSACC (right))
4251 emitcode ("pop", "acc");
4253 emitcode ("subb", "a,b");
4260 emitcode (";", "genCmp #4");
4261 if (AOP_NEEDSACC (right))
4264 emitcode (";", "genCmp #4.1");
4265 emitcode ("xch", "a, b");
4266 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4267 emitcode ("xch", "a, b");
4272 emitcode (";", "genCmp #4.2");
4273 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4276 emitcode ("subb", "a,%s", s);
4283 /* Don't need the left & right operands any more; do need the result. */
4284 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4285 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4287 aopOp (result, ic, FALSE, FALSE);
4291 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4297 /* if the result is used in the next
4298 ifx conditional branch then generate
4299 code a little differently */
4302 genIfxJump (ifx, "c");
4308 /* leave the result in acc */
4310 freeAsmop (result, NULL, ic, TRUE);
4313 /*-----------------------------------------------------------------*/
4314 /* genCmpGt :- greater than comparison */
4315 /*-----------------------------------------------------------------*/
4317 genCmpGt (iCode * ic, iCode * ifx)
4319 operand *left, *right;
4320 sym_link *letype, *retype;
4323 D (emitcode (";", "genCmpGt ");
4326 left = IC_LEFT (ic);
4327 right = IC_RIGHT (ic);
4329 letype = getSpec (operandType (left));
4330 retype = getSpec (operandType (right));
4331 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4333 /* assign the left & right amsops */
4336 genCmp (right, left, ic, ifx, sign);
4339 /*-----------------------------------------------------------------*/
4340 /* genCmpLt - less than comparisons */
4341 /*-----------------------------------------------------------------*/
4343 genCmpLt (iCode * ic, iCode * ifx)
4345 operand *left, *right;
4346 sym_link *letype, *retype;
4349 D (emitcode (";", "genCmpLt ");
4352 left = IC_LEFT (ic);
4353 right = IC_RIGHT (ic);
4355 letype = getSpec (operandType (left));
4356 retype = getSpec (operandType (right));
4357 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4359 /* assign the left & right amsops */
4362 genCmp (left, right, ic, ifx, sign);
4365 /*-----------------------------------------------------------------*/
4366 /* gencjneshort - compare and jump if not equal */
4367 /*-----------------------------------------------------------------*/
4369 gencjneshort (operand * left, operand * right, symbol * lbl)
4371 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4373 unsigned long lit = 0L;
4375 D (emitcode (";", "gencjneshort");
4378 /* if the left side is a literal or
4379 if the right is in a pointer register and left
4381 if ((AOP_TYPE (left) == AOP_LIT) ||
4382 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4389 if (AOP_TYPE (right) == AOP_LIT)
4390 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4392 if (opIsGptr (left) || opIsGptr (right))
4394 /* We are comparing a generic pointer to something.
4395 * Exclude the generic type byte from the comparison.
4398 D (emitcode (";", "cjneshort: generic ptr special case.");
4403 /* if the right side is a literal then anything goes */
4404 if (AOP_TYPE (right) == AOP_LIT &&
4405 AOP_TYPE (left) != AOP_DIR)
4409 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4411 emitcode ("cjne", "a,%s,%05d$",
4412 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4418 /* if the right side is in a register or in direct space or
4419 if the left is a pointer register & right is not */
4420 else if (AOP_TYPE (right) == AOP_REG ||
4421 AOP_TYPE (right) == AOP_DIR ||
4422 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4423 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4427 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4428 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4429 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4430 emitcode ("jnz", "%05d$", lbl->key + 100);
4432 emitcode ("cjne", "a,%s,%05d$",
4433 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4440 /* right is a pointer reg need both a & b */
4443 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4444 if (strcmp (l, "b"))
4445 emitcode ("mov", "b,%s", l);
4446 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4447 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4453 /*-----------------------------------------------------------------*/
4454 /* gencjne - compare and jump if not equal */
4455 /*-----------------------------------------------------------------*/
4457 gencjne (operand * left, operand * right, symbol * lbl)
4459 symbol *tlbl = newiTempLabel (NULL);
4461 D (emitcode (";", "gencjne");
4464 gencjneshort (left, right, lbl);
4466 emitcode ("mov", "a,%s", one);
4467 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4468 emitcode ("", "%05d$:", lbl->key + 100);
4469 emitcode ("clr", "a");
4470 emitcode ("", "%05d$:", tlbl->key + 100);
4473 /*-----------------------------------------------------------------*/
4474 /* genCmpEq - generates code for equal to */
4475 /*-----------------------------------------------------------------*/
4477 genCmpEq (iCode * ic, iCode * ifx)
4479 operand *left, *right, *result;
4481 D (emitcode (";", "genCmpEq ");
4485 AOP_SET_LOCALS (ic);
4487 /* if literal, literal on the right or
4488 if the right is in a pointer register and left
4490 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4491 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4493 operand *t = IC_RIGHT (ic);
4494 IC_RIGHT (ic) = IC_LEFT (ic);
4498 if (ifx && /* !AOP_SIZE(result) */
4499 OP_SYMBOL (result) &&
4500 OP_SYMBOL (result)->regType == REG_CND)
4503 /* if they are both bit variables */
4504 if (AOP_TYPE (left) == AOP_CRY &&
4505 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4507 if (AOP_TYPE (right) == AOP_LIT)
4509 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513 emitcode ("cpl", "c");
4517 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4521 emitcode ("clr", "c");
4523 /* AOP_TYPE(right) == AOP_CRY */
4527 symbol *lbl = newiTempLabel (NULL);
4528 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4529 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4530 emitcode ("cpl", "c");
4531 emitcode ("", "%05d$:", (lbl->key + 100));
4533 /* if true label then we jump if condition
4535 tlbl = newiTempLabel (NULL);
4538 emitcode ("jnc", "%05d$", tlbl->key + 100);
4539 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4543 emitcode ("jc", "%05d$", tlbl->key + 100);
4544 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4546 emitcode ("", "%05d$:", tlbl->key + 100);
4550 tlbl = newiTempLabel (NULL);
4551 gencjneshort (left, right, tlbl);
4554 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4555 emitcode ("", "%05d$:", tlbl->key + 100);
4559 symbol *lbl = newiTempLabel (NULL);
4560 emitcode ("sjmp", "%05d$", lbl->key + 100);
4561 emitcode ("", "%05d$:", tlbl->key + 100);
4562 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4563 emitcode ("", "%05d$:", lbl->key + 100);
4566 /* mark the icode as generated */
4569 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4570 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4574 /* if they are both bit variables */
4575 if (AOP_TYPE (left) == AOP_CRY &&
4576 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4578 if (AOP_TYPE (right) == AOP_LIT)
4580 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4583 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4584 emitcode ("cpl", "c");
4588 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4592 emitcode ("clr", "c");
4594 /* AOP_TYPE(right) == AOP_CRY */
4598 symbol *lbl = newiTempLabel (NULL);
4599 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4600 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4601 emitcode ("cpl", "c");
4602 emitcode ("", "%05d$:", (lbl->key + 100));
4605 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4606 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4608 aopOp (result, ic, TRUE, FALSE);
4611 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4618 genIfxJump (ifx, "c");
4621 /* if the result is used in an arithmetic operation
4622 then put the result in place */
4627 gencjne (left, right, newiTempLabel (NULL));
4629 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4630 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4632 aopOp (result, ic, TRUE, FALSE);
4634 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4636 aopPut (AOP (result), "a", 0);
4641 genIfxJump (ifx, "a");
4644 /* if the result is used in an arithmetic operation
4645 then put the result in place */
4646 if (AOP_TYPE (result) != AOP_CRY)
4648 /* leave the result in acc */
4652 freeAsmop (result, NULL, ic, TRUE);
4655 /*-----------------------------------------------------------------*/
4656 /* ifxForOp - returns the icode containing the ifx for operand */
4657 /*-----------------------------------------------------------------*/
4659 ifxForOp (operand * op, iCode * ic)
4661 /* if true symbol then needs to be assigned */
4662 if (IS_TRUE_SYMOP (op))
4665 /* if this has register type condition and
4666 the next instruction is ifx with the same operand
4667 and live to of the operand is upto the ifx only then */
4669 ic->next->op == IFX &&
4670 IC_COND (ic->next)->key == op->key &&
4671 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4676 /*-----------------------------------------------------------------*/
4677 /* genAndOp - for && operation */
4678 /*-----------------------------------------------------------------*/
4680 genAndOp (iCode * ic)
4682 operand *left, *right, *result;
4685 D (emitcode (";", "genAndOp ");
4688 /* note here that && operations that are in an
4689 if statement are taken away by backPatchLabels
4690 only those used in arthmetic operations remain */
4692 AOP_SET_LOCALS (ic);
4694 /* if both are bit variables */
4695 if (AOP_TYPE (left) == AOP_CRY &&
4696 AOP_TYPE (right) == AOP_CRY)
4698 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4699 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4704 tlbl = newiTempLabel (NULL);
4706 emitcode ("jz", "%05d$", tlbl->key + 100);
4708 emitcode ("", "%05d$:", tlbl->key + 100);
4712 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4713 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714 freeAsmop (result, NULL, ic, TRUE);
4718 /*-----------------------------------------------------------------*/
4719 /* genOrOp - for || operation */
4720 /*-----------------------------------------------------------------*/
4722 genOrOp (iCode * ic)
4724 operand *left, *right, *result;
4727 D (emitcode (";", "genOrOp ");
4730 /* note here that || operations that are in an
4731 if statement are taken away by backPatchLabels
4732 only those used in arthmetic operations remain */
4734 AOP_SET_LOCALS (ic);
4736 /* if both are bit variables */
4737 if (AOP_TYPE (left) == AOP_CRY &&
4738 AOP_TYPE (right) == AOP_CRY)
4740 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4741 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4746 tlbl = newiTempLabel (NULL);
4748 emitcode ("jnz", "%05d$", tlbl->key + 100);
4750 emitcode ("", "%05d$:", tlbl->key + 100);
4754 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4755 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756 freeAsmop (result, NULL, ic, TRUE);
4759 /*-----------------------------------------------------------------*/
4760 /* isLiteralBit - test if lit == 2^n */
4761 /*-----------------------------------------------------------------*/
4763 isLiteralBit (unsigned long lit)
4765 unsigned long pw[32] =
4766 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4767 0x100L, 0x200L, 0x400L, 0x800L,
4768 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4769 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4770 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4771 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4772 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4775 for (idx = 0; idx < 32; idx++)
4781 /*-----------------------------------------------------------------*/
4782 /* continueIfTrue - */
4783 /*-----------------------------------------------------------------*/
4785 continueIfTrue (iCode * ic)
4788 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4792 /*-----------------------------------------------------------------*/
4794 /*-----------------------------------------------------------------*/
4796 jumpIfTrue (iCode * ic)
4799 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4803 /*-----------------------------------------------------------------*/
4804 /* jmpTrueOrFalse - */
4805 /*-----------------------------------------------------------------*/
4807 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4809 // ugly but optimized by peephole
4812 symbol *nlbl = newiTempLabel (NULL);
4813 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4814 emitcode ("", "%05d$:", tlbl->key + 100);
4815 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4816 emitcode ("", "%05d$:", nlbl->key + 100);
4820 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4821 emitcode ("", "%05d$:", tlbl->key + 100);
4826 /*-----------------------------------------------------------------*/
4827 /* genAnd - code for and */
4828 /*-----------------------------------------------------------------*/
4830 genAnd (iCode * ic, iCode * ifx)
4832 operand *left, *right, *result;
4833 int size, offset = 0;
4834 unsigned long lit = 0L;
4838 D (emitcode (";", "genAnd ");
4842 AOP_SET_LOCALS (ic);
4845 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4847 AOP_TYPE (left), AOP_TYPE (right));
4848 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4850 AOP_SIZE (left), AOP_SIZE (right));
4853 /* if left is a literal & right is not then exchange them */
4854 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4855 AOP_NEEDSACC (left))
4857 operand *tmp = right;
4862 /* if result = right then exchange them */
4863 if (sameRegs (AOP (result), AOP (right)))
4865 operand *tmp = right;
4870 /* if right is bit then exchange them */
4871 if (AOP_TYPE (right) == AOP_CRY &&
4872 AOP_TYPE (left) != AOP_CRY)
4874 operand *tmp = right;
4878 if (AOP_TYPE (right) == AOP_LIT)
4879 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4881 size = AOP_SIZE (result);
4884 // result = bit & yy;
4885 if (AOP_TYPE (left) == AOP_CRY)
4887 // c = bit & literal;
4888 if (AOP_TYPE (right) == AOP_LIT)
4892 if (size && sameRegs (AOP (result), AOP (left)))
4895 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4900 if (size && (AOP_TYPE (result) == AOP_CRY))
4902 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4905 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4910 emitcode ("clr", "c");
4915 if (AOP_TYPE (right) == AOP_CRY)
4918 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4919 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4924 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4926 emitcode ("rrc", "a");
4927 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4935 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4936 genIfxJump (ifx, "c");
4940 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4941 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4942 if ((AOP_TYPE (right) == AOP_LIT) &&
4943 (AOP_TYPE (result) == AOP_CRY) &&
4944 (AOP_TYPE (left) != AOP_CRY))
4946 int posbit = isLiteralBit (lit);
4951 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4954 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4960 sprintf (buffer, "acc.%d", posbit & 0x07);
4961 genIfxJump (ifx, buffer);
4968 symbol *tlbl = newiTempLabel (NULL);
4969 int sizel = AOP_SIZE (left);
4971 emitcode ("setb", "c");
4974 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4976 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4978 if ((posbit = isLiteralBit (bytelit)) != 0)
4979 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4982 if (bytelit != 0x0FFL)
4983 emitcode ("anl", "a,%s",
4984 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4985 emitcode ("jnz", "%05d$", tlbl->key + 100);
4990 // bit = left & literal
4993 emitcode ("clr", "c");
4994 emitcode ("", "%05d$:", tlbl->key + 100);
4996 // if(left & literal)
5000 jmpTrueOrFalse (ifx, tlbl);
5008 /* if left is same as result */
5009 if (sameRegs (AOP (result), AOP (left)))
5011 for (; size--; offset++)
5013 if (AOP_TYPE (right) == AOP_LIT)
5015 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5017 else if (bytelit == 0)
5018 aopPut (AOP (result), zero, offset);
5019 else if (IS_AOP_PREG (result))
5021 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5022 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5023 aopPut (AOP (result), "a", offset);
5026 emitcode ("anl", "%s,%s",
5027 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5028 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5032 if (AOP_TYPE (left) == AOP_ACC)
5033 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5036 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5037 if (IS_AOP_PREG (result))
5039 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5040 aopPut (AOP (result), "a", offset);
5044 emitcode ("anl", "%s,a",
5045 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5052 // left & result in different registers
5053 if (AOP_TYPE (result) == AOP_CRY)
5056 // if(size), result in bit
5057 // if(!size && ifx), conditional oper: if(left & right)
5058 symbol *tlbl = newiTempLabel (NULL);
5059 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5061 emitcode ("setb", "c");
5064 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5065 emitcode ("anl", "a,%s",
5066 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5067 emitcode ("jnz", "%05d$", tlbl->key + 100);
5073 emitcode ("", "%05d$:", tlbl->key + 100);
5077 jmpTrueOrFalse (ifx, tlbl);
5081 for (; (size--); offset++)
5084 // result = left & right
5085 if (AOP_TYPE (right) == AOP_LIT)
5087 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5089 aopPut (AOP (result),
5090 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5094 else if (bytelit == 0)
5096 aopPut (AOP (result), zero, offset);
5099 D (emitcode (";", "better literal AND.");
5101 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5102 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5103 FALSE, FALSE, FALSE));
5108 // faster than result <- left, anl result,right
5109 // and better if result is SFR
5110 if (AOP_TYPE (left) == AOP_ACC)
5112 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5113 FALSE, FALSE, FALSE));
5117 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5118 emitcode ("anl", "a,%s",
5119 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5122 aopPut (AOP (result), "a", offset);
5128 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5130 freeAsmop (result, NULL, ic, TRUE);
5133 /*-----------------------------------------------------------------*/
5134 /* genOr - code for or */
5135 /*-----------------------------------------------------------------*/
5137 genOr (iCode * ic, iCode * ifx)
5139 operand *left, *right, *result;
5140 int size, offset = 0;
5141 unsigned long lit = 0L;
5143 D (emitcode (";", "genOr ");
5147 AOP_SET_LOCALS (ic);
5150 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5152 AOP_TYPE (left), AOP_TYPE (right));
5153 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5155 AOP_SIZE (left), AOP_SIZE (right));
5158 /* if left is a literal & right is not then exchange them */
5159 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5160 AOP_NEEDSACC (left))
5162 operand *tmp = right;
5167 /* if result = right then exchange them */
5168 if (sameRegs (AOP (result), AOP (right)))
5170 operand *tmp = right;
5175 /* if right is bit then exchange them */
5176 if (AOP_TYPE (right) == AOP_CRY &&
5177 AOP_TYPE (left) != AOP_CRY)
5179 operand *tmp = right;
5183 if (AOP_TYPE (right) == AOP_LIT)
5184 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5186 size = AOP_SIZE (result);
5190 if (AOP_TYPE (left) == AOP_CRY)
5192 if (AOP_TYPE (right) == AOP_LIT)
5194 // c = bit & literal;
5197 // lit != 0 => result = 1
5198 if (AOP_TYPE (result) == AOP_CRY)
5201 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5203 continueIfTrue (ifx);
5206 emitcode ("setb", "c");
5210 // lit == 0 => result = left
5211 if (size && sameRegs (AOP (result), AOP (left)))
5213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5218 if (AOP_TYPE (right) == AOP_CRY)
5221 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5222 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5227 symbol *tlbl = newiTempLabel (NULL);
5228 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5229 emitcode ("setb", "c");
5230 emitcode ("jb", "%s,%05d$",
5231 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5233 emitcode ("jnz", "%05d$", tlbl->key + 100);
5234 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5236 jmpTrueOrFalse (ifx, tlbl);
5242 emitcode ("", "%05d$:", tlbl->key + 100);
5251 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5252 genIfxJump (ifx, "c");
5256 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5257 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5258 if ((AOP_TYPE (right) == AOP_LIT) &&
5259 (AOP_TYPE (result) == AOP_CRY) &&
5260 (AOP_TYPE (left) != AOP_CRY))
5266 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5268 continueIfTrue (ifx);
5273 // lit = 0, result = boolean(left)
5275 emitcode ("setb", "c");
5279 symbol *tlbl = newiTempLabel (NULL);
5280 emitcode ("jnz", "%05d$", tlbl->key + 100);
5282 emitcode ("", "%05d$:", tlbl->key + 100);
5286 genIfxJump (ifx, "a");
5294 /* if left is same as result */
5295 if (sameRegs (AOP (result), AOP (left)))
5297 for (; size--; offset++)
5299 if (AOP_TYPE (right) == AOP_LIT)
5301 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5307 if (IS_AOP_PREG (left))
5309 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5310 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5311 aopPut (AOP (result), "a", offset);
5315 emitcode ("orl", "%s,%s",
5316 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5317 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5323 if (AOP_TYPE (left) == AOP_ACC)
5325 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5329 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5330 if (IS_AOP_PREG (left))
5332 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5333 aopPut (AOP (result), "a", offset);
5337 emitcode ("orl", "%s,a",
5338 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5346 // left & result in different registers
5347 if (AOP_TYPE (result) == AOP_CRY)
5350 // if(size), result in bit
5351 // if(!size && ifx), conditional oper: if(left | right)
5352 symbol *tlbl = newiTempLabel (NULL);
5353 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5355 emitcode ("setb", "c");
5358 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5359 emitcode ("orl", "a,%s",
5360 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5361 emitcode ("jnz", "%05d$", tlbl->key + 100);
5367 emitcode ("", "%05d$:", tlbl->key + 100);
5371 jmpTrueOrFalse (ifx, tlbl);
5375 for (; (size--); offset++)
5378 // result = left & right
5379 if (AOP_TYPE (right) == AOP_LIT)
5381 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5383 aopPut (AOP (result),
5384 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5388 D (emitcode (";", "better literal OR.");
5390 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5391 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5392 FALSE, FALSE, FALSE));
5397 // faster than result <- left, anl result,right
5398 // and better if result is SFR
5399 if (AOP_TYPE (left) == AOP_ACC)
5401 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5402 FALSE, FALSE, FALSE));
5406 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5407 emitcode ("orl", "a,%s",
5408 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5411 aopPut (AOP (result), "a", offset);
5417 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (result, NULL, ic, TRUE);
5422 /*-----------------------------------------------------------------*/
5423 /* genXor - code for xclusive or */
5424 /*-----------------------------------------------------------------*/
5426 genXor (iCode * ic, iCode * ifx)
5428 operand *left, *right, *result;
5429 int size, offset = 0;
5430 unsigned long lit = 0L;
5432 D (emitcode (";", "genXor ");
5436 AOP_SET_LOCALS (ic);
5439 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5441 AOP_TYPE (left), AOP_TYPE (right));
5442 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5444 AOP_SIZE (left), AOP_SIZE (right));
5447 /* if left is a literal & right is not ||
5448 if left needs acc & right does not */
5449 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5450 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5452 operand *tmp = right;
5457 /* if result = right then exchange them */
5458 if (sameRegs (AOP (result), AOP (right)))
5460 operand *tmp = right;
5465 /* if right is bit then exchange them */
5466 if (AOP_TYPE (right) == AOP_CRY &&
5467 AOP_TYPE (left) != AOP_CRY)
5469 operand *tmp = right;
5473 if (AOP_TYPE (right) == AOP_LIT)
5474 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5476 size = AOP_SIZE (result);
5480 if (AOP_TYPE (left) == AOP_CRY)
5482 if (AOP_TYPE (right) == AOP_LIT)
5484 // c = bit & literal;
5487 // lit>>1 != 0 => result = 1
5488 if (AOP_TYPE (result) == AOP_CRY)
5491 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5493 continueIfTrue (ifx);
5496 emitcode ("setb", "c");
5503 // lit == 0, result = left
5504 if (size && sameRegs (AOP (result), AOP (left)))
5506 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5510 // lit == 1, result = not(left)
5511 if (size && sameRegs (AOP (result), AOP (left)))
5513 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5519 emitcode ("cpl", "c");
5528 symbol *tlbl = newiTempLabel (NULL);
5529 if (AOP_TYPE (right) == AOP_CRY)
5532 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5536 int sizer = AOP_SIZE (right);
5538 // if val>>1 != 0, result = 1
5539 emitcode ("setb", "c");
5542 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5544 // test the msb of the lsb
5545 emitcode ("anl", "a,#0xfe");
5546 emitcode ("jnz", "%05d$", tlbl->key + 100);
5550 emitcode ("rrc", "a");
5552 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5553 emitcode ("cpl", "c");
5554 emitcode ("", "%05d$:", (tlbl->key + 100));
5561 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5562 genIfxJump (ifx, "c");
5566 if (sameRegs (AOP (result), AOP (left)))
5568 /* if left is same as result */
5569 for (; size--; offset++)
5571 if (AOP_TYPE (right) == AOP_LIT)
5573 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5575 else if (IS_AOP_PREG (left))
5577 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5578 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5579 aopPut (AOP (result), "a", offset);
5582 emitcode ("xrl", "%s,%s",
5583 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5584 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5588 if (AOP_TYPE (left) == AOP_ACC)
5589 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5592 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5593 if (IS_AOP_PREG (left))
5595 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5596 aopPut (AOP (result), "a", offset);
5599 emitcode ("xrl", "%s,a",
5600 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5607 // left & result in different registers
5608 if (AOP_TYPE (result) == AOP_CRY)
5611 // if(size), result in bit
5612 // if(!size && ifx), conditional oper: if(left ^ right)
5613 symbol *tlbl = newiTempLabel (NULL);
5614 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5616 emitcode ("setb", "c");
5619 if ((AOP_TYPE (right) == AOP_LIT) &&
5620 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5622 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5626 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5627 emitcode ("xrl", "a,%s",
5628 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5630 emitcode ("jnz", "%05d$", tlbl->key + 100);
5636 emitcode ("", "%05d$:", tlbl->key + 100);
5640 jmpTrueOrFalse (ifx, tlbl);
5643 for (; (size--); offset++)
5646 // result = left & right
5647 if (AOP_TYPE (right) == AOP_LIT)
5649 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5651 aopPut (AOP (result),
5652 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5656 D (emitcode (";", "better literal XOR.");
5658 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5659 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5660 FALSE, FALSE, FALSE));
5664 // faster than result <- left, anl result,right
5665 // and better if result is SFR
5666 if (AOP_TYPE (left) == AOP_ACC)
5668 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5669 FALSE, FALSE, FALSE));
5673 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5674 emitcode ("xrl", "a,%s",
5675 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5678 aopPut (AOP (result), "a", offset);
5683 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5684 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5685 freeAsmop (result, NULL, ic, TRUE);
5688 /*-----------------------------------------------------------------*/
5689 /* genInline - write the inline code out */
5690 /*-----------------------------------------------------------------*/
5692 genInline (iCode * ic)
5694 char buffer[MAX_INLINEASM];
5698 D (emitcode (";", "genInline ");
5701 _G.inLine += (!options.asmpeep);
5702 strcpy (buffer, IC_INLINE (ic));
5704 /* emit each line as a code */
5729 /* emitcode("",buffer); */
5730 _G.inLine -= (!options.asmpeep);
5733 /*-----------------------------------------------------------------*/
5734 /* genRRC - rotate right with carry */
5735 /*-----------------------------------------------------------------*/
5739 operand *left, *result;
5740 int size, offset = 0;
5743 D (emitcode (";", "genRRC ");
5746 /* rotate right with carry */
5747 left = IC_LEFT (ic);
5748 result = IC_RESULT (ic);
5749 aopOp (left, ic, FALSE, FALSE);
5750 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5752 /* move it to the result */
5753 size = AOP_SIZE (result);
5757 _startLazyDPSEvaluation ();
5760 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5762 emitcode ("rrc", "a");
5763 if (AOP_SIZE (result) > 1)
5764 aopPut (AOP (result), "a", offset--);
5766 _endLazyDPSEvaluation ();
5768 /* now we need to put the carry into the
5769 highest order byte of the result */
5770 if (AOP_SIZE (result) > 1)
5772 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5775 emitcode ("mov", "acc.7,c");
5776 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5777 freeAsmop (left, NULL, ic, TRUE);
5778 freeAsmop (result, NULL, ic, TRUE);
5781 /*-----------------------------------------------------------------*/
5782 /* genRLC - generate code for rotate left with carry */
5783 /*-----------------------------------------------------------------*/
5787 operand *left, *result;
5788 int size, offset = 0;
5791 D (emitcode (";", "genRLC ");
5794 /* rotate right with carry */
5795 left = IC_LEFT (ic);
5796 result = IC_RESULT (ic);
5797 aopOp (left, ic, FALSE, FALSE);
5798 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5800 /* move it to the result */
5801 size = AOP_SIZE (result);
5805 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5807 emitcode ("add", "a,acc");
5808 if (AOP_SIZE (result) > 1)
5810 aopPut (AOP (result), "a", offset++);
5813 _startLazyDPSEvaluation ();
5816 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5818 emitcode ("rlc", "a");
5819 if (AOP_SIZE (result) > 1)
5820 aopPut (AOP (result), "a", offset++);
5822 _endLazyDPSEvaluation ();
5824 /* now we need to put the carry into the
5825 highest order byte of the result */
5826 if (AOP_SIZE (result) > 1)
5828 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5831 emitcode ("mov", "acc.0,c");
5832 aopPut (AOP (result), "a", 0);
5833 freeAsmop (left, NULL, ic, TRUE);
5834 freeAsmop (result, NULL, ic, TRUE);
5837 /*-----------------------------------------------------------------*/
5838 /* genGetHbit - generates code get highest order bit */
5839 /*-----------------------------------------------------------------*/
5841 genGetHbit (iCode * ic)
5843 operand *left, *result;
5844 left = IC_LEFT (ic);
5845 result = IC_RESULT (ic);
5846 aopOp (left, ic, FALSE, FALSE);
5847 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5849 D (emitcode (";", "genGetHbit ");
5852 /* get the highest order byte into a */
5853 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5854 if (AOP_TYPE (result) == AOP_CRY)
5856 emitcode ("rlc", "a");
5861 emitcode ("rl", "a");
5862 emitcode ("anl", "a,#0x01");
5867 freeAsmop (left, NULL, ic, TRUE);
5868 freeAsmop (result, NULL, ic, TRUE);
5871 /*-----------------------------------------------------------------*/
5872 /* AccRol - rotate left accumulator by known count */
5873 /*-----------------------------------------------------------------*/
5875 AccRol (int shCount)
5877 shCount &= 0x0007; // shCount : 0..7
5884 emitcode ("rl", "a");
5887 emitcode ("rl", "a");
5888 emitcode ("rl", "a");
5891 emitcode ("swap", "a");
5892 emitcode ("rr", "a");
5895 emitcode ("swap", "a");
5898 emitcode ("swap", "a");
5899 emitcode ("rl", "a");
5902 emitcode ("rr", "a");
5903 emitcode ("rr", "a");
5906 emitcode ("rr", "a");
5911 /*-----------------------------------------------------------------*/
5912 /* AccLsh - left shift accumulator by known count */
5913 /*-----------------------------------------------------------------*/
5915 AccLsh (int shCount)
5920 emitcode ("add", "a,acc");
5921 else if (shCount == 2)
5923 emitcode ("add", "a,acc");
5924 emitcode ("add", "a,acc");
5928 /* rotate left accumulator */
5930 /* and kill the lower order bits */
5931 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5936 /*-----------------------------------------------------------------*/
5937 /* AccRsh - right shift accumulator by known count */
5938 /*-----------------------------------------------------------------*/
5940 AccRsh (int shCount)
5947 emitcode ("rrc", "a");
5951 /* rotate right accumulator */
5952 AccRol (8 - shCount);
5953 /* and kill the higher order bits */
5954 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5961 /*-----------------------------------------------------------------*/
5962 /* AccSRsh - signed right shift accumulator by known count */
5963 /*-----------------------------------------------------------------*/
5965 AccSRsh (int shCount)
5972 emitcode ("mov", "c,acc.7");
5973 emitcode ("rrc", "a");
5975 else if (shCount == 2)
5977 emitcode ("mov", "c,acc.7");
5978 emitcode ("rrc", "a");
5979 emitcode ("mov", "c,acc.7");
5980 emitcode ("rrc", "a");
5984 tlbl = newiTempLabel (NULL);
5985 /* rotate right accumulator */
5986 AccRol (8 - shCount);
5987 /* and kill the higher order bits */
5988 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5989 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5990 emitcode ("orl", "a,#0x%02x",
5991 (unsigned char) ~SRMask[shCount]);
5992 emitcode ("", "%05d$:", tlbl->key + 100);
6000 /*-----------------------------------------------------------------*/
6001 /* shiftR1Left2Result - shift right one byte from left to result */
6002 /*-----------------------------------------------------------------*/
6004 shiftR1Left2Result (operand * left, int offl,
6005 operand * result, int offr,
6006 int shCount, int sign)
6008 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6009 /* shift right accumulator */
6014 aopPut (AOP (result), "a", offr);
6020 /*-----------------------------------------------------------------*/
6021 /* shiftL1Left2Result - shift left one byte from left to result */
6022 /*-----------------------------------------------------------------*/
6024 shiftL1Left2Result (operand * left, int offl,
6025 operand * result, int offr, int shCount)
6028 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6030 /* shift left accumulator */
6032 aopPut (AOP (result), "a", offr);
6038 /*-----------------------------------------------------------------*/
6039 /* movLeft2Result - move byte from left to result */
6040 /*-----------------------------------------------------------------*/
6042 movLeft2Result (operand * left, int offl,
6043 operand * result, int offr, int sign)
6046 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6048 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6050 if (*l == '@' && (IS_AOP_PREG (result)))
6052 emitcode ("mov", "a,%s", l);
6053 aopPut (AOP (result), "a", offr);
6058 aopPut (AOP (result), l, offr);
6061 /* MSB sign in acc.7 ! */
6062 if (getDataSize (left) == offl + 1)
6064 emitcode ("mov", "a,%s", l);
6065 aopPut (AOP (result), "a", offr);
6075 /*-----------------------------------------------------------------*/
6076 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6077 /*-----------------------------------------------------------------*/
6081 emitcode ("rrc", "a");
6082 emitcode ("xch", "a,%s", x);
6083 emitcode ("rrc", "a");
6084 emitcode ("xch", "a,%s", x);
6090 /*-----------------------------------------------------------------*/
6091 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6092 /*-----------------------------------------------------------------*/
6096 emitcode ("xch", "a,%s", x);
6097 emitcode ("rlc", "a");
6098 emitcode ("xch", "a,%s", x);
6099 emitcode ("rlc", "a");
6105 /*-----------------------------------------------------------------*/
6106 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6107 /*-----------------------------------------------------------------*/
6111 emitcode ("xch", "a,%s", x);
6112 emitcode ("add", "a,acc");
6113 emitcode ("xch", "a,%s", x);
6114 emitcode ("rlc", "a");
6120 /*-----------------------------------------------------------------*/
6121 /* AccAXLsh - left shift a:x by known count (0..7) */
6122 /*-----------------------------------------------------------------*/
6124 AccAXLsh (char *x, int shCount)
6139 case 5: // AAAAABBB:CCCCCDDD
6141 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6143 emitcode ("anl", "a,#0x%02x",
6144 SLMask[shCount]); // BBB00000:CCCCCDDD
6146 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6148 AccRol (shCount); // DDDCCCCC:BBB00000
6150 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6152 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6154 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6156 emitcode ("anl", "a,#0x%02x",
6157 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6159 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6161 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6164 case 6: // AAAAAABB:CCCCCCDD
6166 emitcode ("anl", "a,#0x%02x",
6167 SRMask[shCount]); // 000000BB:CCCCCCDD
6169 emitcode ("mov", "c,acc.0"); // c = B
6171 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6173 AccAXRrl1 (x); // BCCCCCCD:D000000B
6175 AccAXRrl1 (x); // BBCCCCCC:DD000000
6178 case 7: // a:x <<= 7
6180 emitcode ("anl", "a,#0x%02x",
6181 SRMask[shCount]); // 0000000B:CCCCCCCD
6183 emitcode ("mov", "c,acc.0"); // c = B
6185 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6187 AccAXRrl1 (x); // BCCCCCCC:D0000000
6198 /*-----------------------------------------------------------------*/
6199 /* AccAXRsh - right shift a:x known count (0..7) */
6200 /*-----------------------------------------------------------------*/
6202 AccAXRsh (char *x, int shCount)
6210 AccAXRrl1 (x); // 0->a:x
6215 AccAXRrl1 (x); // 0->a:x
6218 AccAXRrl1 (x); // 0->a:x
6223 case 5: // AAAAABBB:CCCCCDDD = a:x
6225 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6227 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6229 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6231 emitcode ("anl", "a,#0x%02x",
6232 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6234 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6236 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6238 emitcode ("anl", "a,#0x%02x",
6239 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6241 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6243 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6245 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6248 case 6: // AABBBBBB:CCDDDDDD
6250 emitcode ("mov", "c,acc.7");
6251 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6253 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6255 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6257 emitcode ("anl", "a,#0x%02x",
6258 SRMask[shCount]); // 000000AA:BBBBBBCC
6261 case 7: // ABBBBBBB:CDDDDDDD
6263 emitcode ("mov", "c,acc.7"); // c = A
6265 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6267 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6269 emitcode ("anl", "a,#0x%02x",
6270 SRMask[shCount]); // 0000000A:BBBBBBBC
6281 /*-----------------------------------------------------------------*/
6282 /* AccAXRshS - right shift signed a:x known count (0..7) */
6283 /*-----------------------------------------------------------------*/
6285 AccAXRshS (char *x, int shCount)
6293 emitcode ("mov", "c,acc.7");
6294 AccAXRrl1 (x); // s->a:x
6298 emitcode ("mov", "c,acc.7");
6299 AccAXRrl1 (x); // s->a:x
6301 emitcode ("mov", "c,acc.7");
6302 AccAXRrl1 (x); // s->a:x
6307 case 5: // AAAAABBB:CCCCCDDD = a:x
6309 tlbl = newiTempLabel (NULL);
6310 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6312 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6314 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6316 emitcode ("anl", "a,#0x%02x",
6317 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6319 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6321 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6323 emitcode ("anl", "a,#0x%02x",
6324 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6326 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6328 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6330 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6332 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6333 emitcode ("orl", "a,#0x%02x",
6334 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6336 emitcode ("", "%05d$:", tlbl->key + 100);
6337 break; // SSSSAAAA:BBBCCCCC
6339 case 6: // AABBBBBB:CCDDDDDD
6341 tlbl = newiTempLabel (NULL);
6342 emitcode ("mov", "c,acc.7");
6343 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6345 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6347 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6349 emitcode ("anl", "a,#0x%02x",
6350 SRMask[shCount]); // 000000AA:BBBBBBCC
6352 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6353 emitcode ("orl", "a,#0x%02x",
6354 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6356 emitcode ("", "%05d$:", tlbl->key + 100);
6358 case 7: // ABBBBBBB:CDDDDDDD
6360 tlbl = newiTempLabel (NULL);
6361 emitcode ("mov", "c,acc.7"); // c = A
6363 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6365 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6367 emitcode ("anl", "a,#0x%02x",
6368 SRMask[shCount]); // 0000000A:BBBBBBBC
6370 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6371 emitcode ("orl", "a,#0x%02x",
6372 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6374 emitcode ("", "%05d$:", tlbl->key + 100);
6384 /*-----------------------------------------------------------------*/
6385 /* shiftL2Left2Result - shift left two bytes from left to result */
6386 /*-----------------------------------------------------------------*/
6388 shiftL2Left2Result (operand * left, int offl,
6389 operand * result, int offr, int shCount)
6391 if (sameRegs (AOP (result), AOP (left)) &&
6392 ((offl + MSB16) == offr))
6394 /* don't crash result[offr] */
6395 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6396 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6400 movLeft2Result (left, offl, result, offr, 0);
6401 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6403 /* ax << shCount (x = lsb(result)) */
6404 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6405 aopPut (AOP (result), "a", offr + MSB16);
6411 /*-----------------------------------------------------------------*/
6412 /* shiftR2Left2Result - shift right two bytes from left to result */
6413 /*-----------------------------------------------------------------*/
6415 shiftR2Left2Result (operand * left, int offl,
6416 operand * result, int offr,
6417 int shCount, int sign)
6419 if (sameRegs (AOP (result), AOP (left)) &&
6420 ((offl + MSB16) == offr))
6422 /* don't crash result[offr] */
6423 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6424 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6428 movLeft2Result (left, offl, result, offr, 0);
6429 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6431 /* a:x >> shCount (x = lsb(result)) */
6433 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6435 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6436 if (getDataSize (result) > 1)
6437 aopPut (AOP (result), "a", offr + MSB16);
6443 /*-----------------------------------------------------------------*/
6444 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6445 /*-----------------------------------------------------------------*/
6447 shiftLLeftOrResult (operand * left, int offl,
6448 operand * result, int offr, int shCount)
6450 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6451 /* shift left accumulator */
6453 /* or with result */
6454 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6455 /* back to result */
6456 aopPut (AOP (result), "a", offr);
6462 /*-----------------------------------------------------------------*/
6463 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6464 /*-----------------------------------------------------------------*/
6466 shiftRLeftOrResult (operand * left, int offl,
6467 operand * result, int offr, int shCount)
6469 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6470 /* shift right accumulator */
6472 /* or with result */
6473 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6474 /* back to result */
6475 aopPut (AOP (result), "a", offr);
6481 /*-----------------------------------------------------------------*/
6482 /* genlshOne - left shift a one byte quantity by known count */
6483 /*-----------------------------------------------------------------*/
6485 genlshOne (operand * result, operand * left, int shCount)
6487 D (emitcode (";", "genlshOne ");
6489 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6495 /*-----------------------------------------------------------------*/
6496 /* genlshTwo - left shift two bytes by known amount != 0 */
6497 /*-----------------------------------------------------------------*/
6499 genlshTwo (operand * result, operand * left, int shCount)
6503 D (emitcode (";", "genlshTwo ");
6506 size = getDataSize (result);
6508 /* if shCount >= 8 */
6516 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6518 movLeft2Result (left, LSB, result, MSB16, 0);
6520 aopPut (AOP (result), zero, LSB);
6523 /* 1 <= shCount <= 7 */
6527 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6529 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6536 /*-----------------------------------------------------------------*/
6537 /* shiftLLong - shift left one long from left to result */
6538 /* offl = LSB or MSB16 */
6539 /*-----------------------------------------------------------------*/
6541 shiftLLong (operand * left, operand * result, int offr)
6544 int size = AOP_SIZE (result);
6546 if (size >= LSB + offr)
6548 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6550 emitcode ("add", "a,acc");
6551 if (sameRegs (AOP (left), AOP (result)) &&
6552 size >= MSB16 + offr && offr != LSB)
6553 emitcode ("xch", "a,%s",
6554 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6556 aopPut (AOP (result), "a", LSB + offr);
6559 if (size >= MSB16 + offr)
6561 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6563 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6566 emitcode ("rlc", "a");
6567 if (sameRegs (AOP (left), AOP (result)) &&
6568 size >= MSB24 + offr && offr != LSB)
6569 emitcode ("xch", "a,%s",
6570 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6572 aopPut (AOP (result), "a", MSB16 + offr);
6575 if (size >= MSB24 + offr)
6577 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6579 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6582 emitcode ("rlc", "a");
6583 if (sameRegs (AOP (left), AOP (result)) &&
6584 size >= MSB32 + offr && offr != LSB)
6585 emitcode ("xch", "a,%s",
6586 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6588 aopPut (AOP (result), "a", MSB24 + offr);
6591 if (size > MSB32 + offr)
6593 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6595 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6598 emitcode ("rlc", "a");
6599 aopPut (AOP (result), "a", MSB32 + offr);
6602 aopPut (AOP (result), zero, LSB);
6608 /*-----------------------------------------------------------------*/
6609 /* genlshFour - shift four byte by a known amount != 0 */
6610 /*-----------------------------------------------------------------*/
6612 genlshFour (operand * result, operand * left, int shCount)
6616 D (emitcode (";", "genlshFour ");
6619 size = AOP_SIZE (result);
6621 /* if shifting more that 3 bytes */
6626 /* lowest order of left goes to the highest
6627 order of the destination */
6628 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6630 movLeft2Result (left, LSB, result, MSB32, 0);
6631 aopPut (AOP (result), zero, LSB);
6632 aopPut (AOP (result), zero, MSB16);
6633 aopPut (AOP (result), zero, MSB32);
6637 /* more than two bytes */
6638 else if (shCount >= 16)
6640 /* lower order two bytes goes to higher order two bytes */
6642 /* if some more remaining */
6644 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6647 movLeft2Result (left, MSB16, result, MSB32, 0);
6648 movLeft2Result (left, LSB, result, MSB24, 0);
6650 aopPut (AOP (result), zero, MSB16);
6651 aopPut (AOP (result), zero, LSB);
6655 /* if more than 1 byte */
6656 else if (shCount >= 8)
6658 /* lower order three bytes goes to higher order three bytes */
6663 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6665 movLeft2Result (left, LSB, result, MSB16, 0);
6671 movLeft2Result (left, MSB24, result, MSB32, 0);
6672 movLeft2Result (left, MSB16, result, MSB24, 0);
6673 movLeft2Result (left, LSB, result, MSB16, 0);
6674 aopPut (AOP (result), zero, LSB);
6676 else if (shCount == 1)
6677 shiftLLong (left, result, MSB16);
6680 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6681 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6682 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6683 aopPut (AOP (result), zero, LSB);
6688 /* 1 <= shCount <= 7 */
6689 else if (shCount <= 2)
6691 shiftLLong (left, result, LSB);
6693 shiftLLong (result, result, LSB);
6695 /* 3 <= shCount <= 7, optimize */
6698 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6699 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6700 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6707 /*-----------------------------------------------------------------*/
6708 /* genLeftShiftLiteral - left shifting by known count */
6709 /*-----------------------------------------------------------------*/
6711 genLeftShiftLiteral (operand * left,
6716 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6719 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6722 freeAsmop (right, NULL, ic, TRUE);
6724 aopOp (left, ic, FALSE, FALSE);
6725 aopOp (result, ic, FALSE, TRUE);
6727 size = getSize (operandType (result));
6730 emitcode ("; shift left ", "result %d, left %d", size,
6734 /* I suppose that the left size >= result size */
6739 movLeft2Result (left, size, result, size, 0);
6743 else if (shCount >= (size * 8))
6745 aopPut (AOP (result), zero, size);
6751 genlshOne (result, left, shCount);
6755 case 3: /* bug: this is for generic pointers, I bet. */
6756 genlshTwo (result, left, shCount);
6760 genlshFour (result, left, shCount);
6764 freeAsmop (left, NULL, ic, TRUE);
6765 freeAsmop (result, NULL, ic, TRUE);
6769 /*-----------------------------------------------------------------*/
6770 /* genLeftShift - generates code for left shifting */
6771 /*-----------------------------------------------------------------*/
6773 genLeftShift (iCode * ic)
6775 operand *left, *right, *result;
6778 symbol *tlbl, *tlbl1;
6780 D (emitcode (";", "genLeftShift ");
6783 right = IC_RIGHT (ic);
6784 left = IC_LEFT (ic);
6785 result = IC_RESULT (ic);
6787 aopOp (right, ic, FALSE, FALSE);
6790 /* if the shift count is known then do it
6791 as efficiently as possible */
6792 if (AOP_TYPE (right) == AOP_LIT)
6794 genLeftShiftLiteral (left, right, result, ic);
6799 /* shift count is unknown then we have to form
6800 a loop get the loop count in B : Note: we take
6801 only the lower order byte since shifting
6802 more that 32 bits make no sense anyway, ( the
6803 largest size of an object can be only 32 bits ) */
6805 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6806 emitcode ("inc", "b");
6807 freeAsmop (right, NULL, ic, TRUE);
6808 aopOp (left, ic, FALSE, FALSE);
6809 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6811 /* now move the left to the result if they are not the
6813 if (!sameRegs (AOP (left), AOP (result)) &&
6814 AOP_SIZE (result) > 1)
6817 size = AOP_SIZE (result);
6819 _startLazyDPSEvaluation ();
6822 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6823 if (*l == '@' && (IS_AOP_PREG (result)))
6826 emitcode ("mov", "a,%s", l);
6827 aopPut (AOP (result), "a", offset);
6830 aopPut (AOP (result), l, offset);
6833 _endLazyDPSEvaluation ();
6836 tlbl = newiTempLabel (NULL);
6837 size = AOP_SIZE (result);
6839 tlbl1 = newiTempLabel (NULL);
6841 /* if it is only one byte then */
6844 symbol *tlbl1 = newiTempLabel (NULL);
6846 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6848 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6849 emitcode ("", "%05d$:", tlbl->key + 100);
6850 emitcode ("add", "a,acc");
6851 emitcode ("", "%05d$:", tlbl1->key + 100);
6852 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6853 aopPut (AOP (result), "a", 0);
6857 reAdjustPreg (AOP (result));
6859 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6860 emitcode ("", "%05d$:", tlbl->key + 100);
6861 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6863 emitcode ("add", "a,acc");
6864 aopPut (AOP (result), "a", offset++);
6865 _startLazyDPSEvaluation ();
6868 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6870 emitcode ("rlc", "a");
6871 aopPut (AOP (result), "a", offset++);
6873 _endLazyDPSEvaluation ();
6874 reAdjustPreg (AOP (result));
6876 emitcode ("", "%05d$:", tlbl1->key + 100);
6877 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6879 freeAsmop (left, NULL, ic, TRUE);
6880 freeAsmop (result, NULL, ic, TRUE);
6885 /*-----------------------------------------------------------------*/
6886 /* genrshOne - right shift a one byte quantity by known count */
6887 /*-----------------------------------------------------------------*/
6889 genrshOne (operand * result, operand * left,
6890 int shCount, int sign)
6892 D (emitcode (";", "genrshOne");
6894 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6900 /*-----------------------------------------------------------------*/
6901 /* genrshTwo - right shift two bytes by known amount != 0 */
6902 /*-----------------------------------------------------------------*/
6904 genrshTwo (operand * result, operand * left,
6905 int shCount, int sign)
6907 D (emitcode (";", "genrshTwo");
6910 /* if shCount >= 8 */
6915 shiftR1Left2Result (left, MSB16, result, LSB,
6918 movLeft2Result (left, MSB16, result, LSB, sign);
6919 addSign (result, MSB16, sign);
6922 /* 1 <= shCount <= 7 */
6924 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6930 /*-----------------------------------------------------------------*/
6931 /* shiftRLong - shift right one long from left to result */
6932 /* offl = LSB or MSB16 */
6933 /*-----------------------------------------------------------------*/
6935 shiftRLong (operand * left, int offl,
6936 operand * result, int sign)
6939 emitcode ("clr", "c");
6940 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6942 emitcode ("mov", "c,acc.7");
6943 emitcode ("rrc", "a");
6944 aopPut (AOP (result), "a", MSB32 - offl);
6946 /* add sign of "a" */
6947 addSign (result, MSB32, sign);
6949 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6950 emitcode ("rrc", "a");
6951 aopPut (AOP (result), "a", MSB24 - offl);
6953 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6954 emitcode ("rrc", "a");
6955 aopPut (AOP (result), "a", MSB16 - offl);
6959 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6960 emitcode ("rrc", "a");
6961 aopPut (AOP (result), "a", LSB);
6968 /*-----------------------------------------------------------------*/
6969 /* genrshFour - shift four byte by a known amount != 0 */
6970 /*-----------------------------------------------------------------*/
6972 genrshFour (operand * result, operand * left,
6973 int shCount, int sign)
6975 D (emitcode (";", "genrshFour");
6978 /* if shifting more that 3 bytes */
6983 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6985 movLeft2Result (left, MSB32, result, LSB, sign);
6986 addSign (result, MSB16, sign);
6988 else if (shCount >= 16)
6992 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6995 movLeft2Result (left, MSB24, result, LSB, 0);
6996 movLeft2Result (left, MSB32, result, MSB16, sign);
6998 addSign (result, MSB24, sign);
7000 else if (shCount >= 8)
7004 shiftRLong (left, MSB16, result, sign);
7005 else if (shCount == 0)
7007 movLeft2Result (left, MSB16, result, LSB, 0);
7008 movLeft2Result (left, MSB24, result, MSB16, 0);
7009 movLeft2Result (left, MSB32, result, MSB24, sign);
7010 addSign (result, MSB32, sign);
7014 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7015 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7016 /* the last shift is signed */
7017 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7018 addSign (result, MSB32, sign);
7022 { /* 1 <= shCount <= 7 */
7025 shiftRLong (left, LSB, result, sign);
7027 shiftRLong (result, LSB, result, sign);
7031 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7032 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7033 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7041 /*-----------------------------------------------------------------*/
7042 /* genRightShiftLiteral - right shifting by known count */
7043 /*-----------------------------------------------------------------*/
7045 genRightShiftLiteral (operand * left,
7051 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7054 D (emitcode (";", "genRightShiftLiteral");
7057 freeAsmop (right, NULL, ic, TRUE);
7059 aopOp (left, ic, FALSE, FALSE);
7060 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7063 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7067 size = getDataSize (left);
7068 /* test the LEFT size !!! */
7070 /* I suppose that the left size >= result size */
7073 size = getDataSize (result);
7075 movLeft2Result (left, size, result, size, 0);
7078 else if (shCount >= (size * 8))
7081 /* get sign in acc.7 */
7082 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7083 addSign (result, LSB, sign);
7090 genrshOne (result, left, shCount, sign);
7094 genrshTwo (result, left, shCount, sign);
7098 genrshFour (result, left, shCount, sign);
7104 freeAsmop (left, NULL, ic, TRUE);
7105 freeAsmop (result, NULL, ic, TRUE);
7110 /*-----------------------------------------------------------------*/
7111 /* genSignedRightShift - right shift of signed number */
7112 /*-----------------------------------------------------------------*/
7114 genSignedRightShift (iCode * ic)
7116 operand *right, *left, *result;
7119 symbol *tlbl, *tlbl1;
7121 D (emitcode (";", "genSignedRightShift ");
7124 /* we do it the hard way put the shift count in b
7125 and loop thru preserving the sign */
7127 right = IC_RIGHT (ic);
7128 left = IC_LEFT (ic);
7129 result = IC_RESULT (ic);
7131 aopOp (right, ic, FALSE, FALSE);
7134 if (AOP_TYPE (right) == AOP_LIT)
7136 genRightShiftLiteral (left, right, result, ic, 1);
7140 /* shift count is unknown then we have to form
7141 a loop get the loop count in B : Note: we take
7142 only the lower order byte since shifting
7143 more that 32 bits make no sense anyway, ( the
7144 largest size of an object can be only 32 bits ) */
7146 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7147 emitcode ("inc", "b");
7148 freeAsmop (right, NULL, ic, TRUE);
7149 aopOp (left, ic, FALSE, FALSE);
7150 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7152 /* now move the left to the result if they are not the
7154 if (!sameRegs (AOP (left), AOP (result)) &&
7155 AOP_SIZE (result) > 1)
7158 size = AOP_SIZE (result);
7160 _startLazyDPSEvaluation ();
7163 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7164 if (*l == '@' && IS_AOP_PREG (result))
7167 emitcode ("mov", "a,%s", l);
7168 aopPut (AOP (result), "a", offset);
7171 aopPut (AOP (result), l, offset);
7174 _endLazyDPSEvaluation ();
7177 /* mov the highest order bit to OVR */
7178 tlbl = newiTempLabel (NULL);
7179 tlbl1 = newiTempLabel (NULL);
7181 size = AOP_SIZE (result);
7183 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7184 emitcode ("rlc", "a");
7185 emitcode ("mov", "ov,c");
7186 /* if it is only one byte then */
7189 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7191 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7192 emitcode ("", "%05d$:", tlbl->key + 100);
7193 emitcode ("mov", "c,ov");
7194 emitcode ("rrc", "a");
7195 emitcode ("", "%05d$:", tlbl1->key + 100);
7196 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7197 aopPut (AOP (result), "a", 0);
7201 reAdjustPreg (AOP (result));
7202 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7203 emitcode ("", "%05d$:", tlbl->key + 100);
7204 emitcode ("mov", "c,ov");
7205 _startLazyDPSEvaluation ();
7208 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7210 emitcode ("rrc", "a");
7211 aopPut (AOP (result), "a", offset--);
7213 _endLazyDPSEvaluation ();
7214 reAdjustPreg (AOP (result));
7215 emitcode ("", "%05d$:", tlbl1->key + 100);
7216 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7219 freeAsmop (left, NULL, ic, TRUE);
7220 freeAsmop (result, NULL, ic, TRUE);
7223 /*-----------------------------------------------------------------*/
7224 /* genRightShift - generate code for right shifting */
7225 /*-----------------------------------------------------------------*/
7227 genRightShift (iCode * ic)
7229 operand *right, *left, *result;
7233 symbol *tlbl, *tlbl1;
7235 D (emitcode (";", "genRightShift ");
7238 /* if signed then we do it the hard way preserve the
7239 sign bit moving it inwards */
7240 retype = getSpec (operandType (IC_RESULT (ic)));
7242 if (!SPEC_USIGN (retype))
7244 genSignedRightShift (ic);
7248 /* signed & unsigned types are treated the same : i.e. the
7249 signed is NOT propagated inwards : quoting from the
7250 ANSI - standard : "for E1 >> E2, is equivalent to division
7251 by 2**E2 if unsigned or if it has a non-negative value,
7252 otherwise the result is implementation defined ", MY definition
7253 is that the sign does not get propagated */
7255 right = IC_RIGHT (ic);
7256 left = IC_LEFT (ic);
7257 result = IC_RESULT (ic);
7259 aopOp (right, ic, FALSE, FALSE);
7262 /* if the shift count is known then do it
7263 as efficiently as possible */
7264 if (AOP_TYPE (right) == AOP_LIT)
7266 genRightShiftLiteral (left, right, result, ic, 0);
7271 /* shift count is unknown then we have to form
7272 a loop get the loop count in B : Note: we take
7273 only the lower order byte since shifting
7274 more that 32 bits make no sense anyway, ( the
7275 largest size of an object can be only 32 bits ) */
7277 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7278 emitcode ("inc", "b");
7279 freeAsmop (right, NULL, ic, TRUE);
7280 aopOp (left, ic, FALSE, FALSE);
7281 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7283 /* now move the left to the result if they are not the
7285 if (!sameRegs (AOP (left), AOP (result)) &&
7286 AOP_SIZE (result) > 1)
7289 size = AOP_SIZE (result);
7291 _startLazyDPSEvaluation ();
7294 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7295 if (*l == '@' && IS_AOP_PREG (result))
7298 emitcode ("mov", "a,%s", l);
7299 aopPut (AOP (result), "a", offset);
7302 aopPut (AOP (result), l, offset);
7305 _endLazyDPSEvaluation ();
7308 tlbl = newiTempLabel (NULL);
7309 tlbl1 = newiTempLabel (NULL);
7310 size = AOP_SIZE (result);
7313 /* if it is only one byte then */
7316 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7318 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7319 emitcode ("", "%05d$:", tlbl->key + 100);
7321 emitcode ("rrc", "a");
7322 emitcode ("", "%05d$:", tlbl1->key + 100);
7323 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7324 aopPut (AOP (result), "a", 0);
7328 reAdjustPreg (AOP (result));
7329 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7330 emitcode ("", "%05d$:", tlbl->key + 100);
7332 _startLazyDPSEvaluation ();
7335 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7337 emitcode ("rrc", "a");
7338 aopPut (AOP (result), "a", offset--);
7340 _endLazyDPSEvaluation ();
7341 reAdjustPreg (AOP (result));
7343 emitcode ("", "%05d$:", tlbl1->key + 100);
7344 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7347 freeAsmop (left, NULL, ic, TRUE);
7348 freeAsmop (result, NULL, ic, TRUE);
7351 /*-----------------------------------------------------------------*/
7352 /* genUnpackBits - generates code for unpacking bits */
7353 /*-----------------------------------------------------------------*/
7355 genUnpackBits (operand * result, char *rname, int ptype)
7362 D (emitcode (";", "genUnpackBits ");
7365 etype = getSpec (operandType (result));
7367 /* read the first byte */
7373 emitcode ("mov", "a,@%s", rname);
7377 emitcode ("movx", "a,@%s", rname);
7381 emitcode ("movx", "a,@dptr");
7385 emitcode ("clr", "a");
7386 emitcode ("movc", "a", "@a+dptr");
7390 emitcode ("lcall", "__gptrget");
7394 /* if we have bitdisplacement then it fits */
7395 /* into this byte completely or if length is */
7396 /* less than a byte */
7397 if ((shCnt = SPEC_BSTR (etype)) ||
7398 (SPEC_BLEN (etype) <= 8))
7401 /* shift right acc */
7404 emitcode ("anl", "a,#0x%02x",
7405 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7406 aopPut (AOP (result), "a", offset);
7410 /* bit field did not fit in a byte */
7411 rlen = SPEC_BLEN (etype) - 8;
7412 aopPut (AOP (result), "a", offset++);
7421 emitcode ("inc", "%s", rname);
7422 emitcode ("mov", "a,@%s", rname);
7426 emitcode ("inc", "%s", rname);
7427 emitcode ("movx", "a,@%s", rname);
7431 emitcode ("inc", "dptr");
7432 emitcode ("movx", "a,@dptr");
7436 emitcode ("clr", "a");
7437 emitcode ("inc", "dptr");
7438 emitcode ("movc", "a", "@a+dptr");
7442 emitcode ("inc", "dptr");
7443 emitcode ("lcall", "__gptrget");
7448 /* if we are done */
7452 aopPut (AOP (result), "a", offset++);
7458 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7459 aopPut (AOP (result), "a", offset);
7466 /*-----------------------------------------------------------------*/
7467 /* genDataPointerGet - generates code when ptr offset is known */
7468 /*-----------------------------------------------------------------*/
7470 genDataPointerGet (operand * left,
7476 int size, offset = 0;
7477 aopOp (result, ic, TRUE, FALSE);
7479 /* get the string representation of the name */
7480 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7481 size = AOP_SIZE (result);
7482 _startLazyDPSEvaluation ();
7486 sprintf (buffer, "(%s + %d)", l + 1, offset);
7488 sprintf (buffer, "%s", l + 1);
7489 aopPut (AOP (result), buffer, offset++);
7491 _endLazyDPSEvaluation ();
7493 freeAsmop (left, NULL, ic, TRUE);
7494 freeAsmop (result, NULL, ic, TRUE);
7497 /*-----------------------------------------------------------------*/
7498 /* genNearPointerGet - emitcode for near pointer fetch */
7499 /*-----------------------------------------------------------------*/
7501 genNearPointerGet (operand * left,
7508 sym_link *rtype, *retype, *letype;
7509 sym_link *ltype = operandType (left);
7512 rtype = operandType (result);
7513 retype = getSpec (rtype);
7514 letype = getSpec (ltype);
7516 aopOp (left, ic, FALSE, FALSE);
7518 /* if left is rematerialisable and
7519 result is not bit variable type and
7520 the left is pointer to data space i.e
7521 lower 128 bytes of space */
7522 if (AOP_TYPE (left) == AOP_IMMD &&
7523 !IS_BITVAR (retype) &&
7524 !IS_BITVAR (letype) &&
7525 DCL_TYPE (ltype) == POINTER)
7527 genDataPointerGet (left, result, ic);
7531 /* if the value is already in a pointer register
7532 then don't need anything more */
7533 if (!AOP_INPREG (AOP (left)))
7535 /* otherwise get a free pointer register */
7537 preg = getFreePtr (ic, &aop, FALSE);
7538 emitcode ("mov", "%s,%s",
7540 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7544 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7546 freeAsmop (left, NULL, ic, TRUE);
7547 aopOp (result, ic, FALSE, FALSE);
7549 /* if bitfield then unpack the bits */
7550 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7551 genUnpackBits (result, rname, POINTER);
7554 /* we have can just get the values */
7555 int size = AOP_SIZE (result);
7560 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7563 emitcode ("mov", "a,@%s", rname);
7564 aopPut (AOP (result), "a", offset);
7568 sprintf (buffer, "@%s", rname);
7569 aopPut (AOP (result), buffer, offset);
7573 emitcode ("inc", "%s", rname);
7577 /* now some housekeeping stuff */
7580 /* we had to allocate for this iCode */
7581 freeAsmop (NULL, aop, ic, TRUE);
7585 /* we did not allocate which means left
7586 already in a pointer register, then
7587 if size > 0 && this could be used again
7588 we have to point it back to where it
7590 if (AOP_SIZE (result) > 1 &&
7591 !OP_SYMBOL (left)->remat &&
7592 (OP_SYMBOL (left)->liveTo > ic->seq ||
7595 int size = AOP_SIZE (result) - 1;
7597 emitcode ("dec", "%s", rname);
7602 freeAsmop (result, NULL, ic, TRUE);
7606 /*-----------------------------------------------------------------*/
7607 /* genPagedPointerGet - emitcode for paged pointer fetch */
7608 /*-----------------------------------------------------------------*/
7610 genPagedPointerGet (operand * left,
7617 sym_link *rtype, *retype, *letype;
7619 rtype = operandType (result);
7620 retype = getSpec (rtype);
7621 letype = getSpec (operandType (left));
7622 aopOp (left, ic, FALSE, FALSE);
7624 /* if the value is already in a pointer register
7625 then don't need anything more */
7626 if (!AOP_INPREG (AOP (left)))
7628 /* otherwise get a free pointer register */
7630 preg = getFreePtr (ic, &aop, FALSE);
7631 emitcode ("mov", "%s,%s",
7633 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7637 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7639 freeAsmop (left, NULL, ic, TRUE);
7640 aopOp (result, ic, FALSE, FALSE);
7642 /* if bitfield then unpack the bits */
7643 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7644 genUnpackBits (result, rname, PPOINTER);
7647 /* we have can just get the values */
7648 int size = AOP_SIZE (result);
7654 emitcode ("movx", "a,@%s", rname);
7655 aopPut (AOP (result), "a", offset);
7660 emitcode ("inc", "%s", rname);
7664 /* now some housekeeping stuff */
7667 /* we had to allocate for this iCode */
7668 freeAsmop (NULL, aop, ic, TRUE);
7672 /* we did not allocate which means left
7673 already in a pointer register, then
7674 if size > 0 && this could be used again
7675 we have to point it back to where it
7677 if (AOP_SIZE (result) > 1 &&
7678 !OP_SYMBOL (left)->remat &&
7679 (OP_SYMBOL (left)->liveTo > ic->seq ||
7682 int size = AOP_SIZE (result) - 1;
7684 emitcode ("dec", "%s", rname);
7689 freeAsmop (result, NULL, ic, TRUE);
7694 /*-----------------------------------------------------------------*/
7695 /* genFarPointerGet - gget value from far space */
7696 /*-----------------------------------------------------------------*/
7698 genFarPointerGet (operand * left,
7699 operand * result, iCode * ic)
7702 sym_link *retype = getSpec (operandType (result));
7703 sym_link *letype = getSpec (operandType (left));
7704 D (emitcode (";", "genFarPointerGet");
7707 aopOp (left, ic, FALSE, FALSE);
7709 /* if the operand is already in dptr
7710 then we do nothing else we move the value to dptr */
7711 if (AOP_TYPE (left) != AOP_STR)
7713 /* if this is remateriazable */
7714 if (AOP_TYPE (left) == AOP_IMMD)
7716 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7720 /* we need to get it byte by byte */
7721 _startLazyDPSEvaluation ();
7722 if (AOP_TYPE (left) != AOP_DPTR)
7724 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7725 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7726 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7730 /* We need to generate a load to DPTR indirect through DPTR. */
7731 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7733 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7734 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7735 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7736 emitcode ("pop", "dph");
7737 emitcode ("pop", "dpl");
7739 _endLazyDPSEvaluation ();
7742 /* so dptr know contains the address */
7743 freeAsmop (left, NULL, ic, TRUE);
7744 aopOp (result, ic, FALSE, TRUE);
7746 /* if bit then unpack */
7747 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7748 genUnpackBits (result, "dptr", FPOINTER);
7751 size = AOP_SIZE (result);
7754 _startLazyDPSEvaluation ();
7761 emitcode ("movx", "a,@dptr");
7763 emitcode ("inc", "dptr");
7765 aopPut (AOP (result), "a", offset++);
7767 _endLazyDPSEvaluation ();
7770 freeAsmop (result, NULL, ic, TRUE);
7773 /*-----------------------------------------------------------------*/
7774 /* emitcodePointerGet - gget value from code space */
7775 /*-----------------------------------------------------------------*/
7777 emitcodePointerGet (operand * left,
7778 operand * result, iCode * ic)
7781 sym_link *retype = getSpec (operandType (result));
7783 aopOp (left, ic, FALSE, FALSE);
7785 /* if the operand is already in dptr
7786 then we do nothing else we move the value to dptr */
7787 if (AOP_TYPE (left) != AOP_STR)
7789 /* if this is remateriazable */
7790 if (AOP_TYPE (left) == AOP_IMMD)
7792 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7795 { /* we need to get it byte by byte */
7796 _startLazyDPSEvaluation ();
7797 if (AOP_TYPE (left) != AOP_DPTR)
7799 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7800 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7801 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7805 /* We need to generate a load to DPTR indirect through DPTR. */
7806 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7808 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7809 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7810 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7811 emitcode ("pop", "dph");
7812 emitcode ("pop", "dpl");
7814 _endLazyDPSEvaluation ();
7817 /* so dptr know contains the address */
7818 freeAsmop (left, NULL, ic, TRUE);
7819 aopOp (result, ic, FALSE, TRUE);
7821 /* if bit then unpack */
7822 if (IS_BITVAR (retype))
7823 genUnpackBits (result, "dptr", CPOINTER);
7826 size = AOP_SIZE (result);
7829 _startLazyDPSEvaluation ();
7835 emitcode ("clr", "a");
7836 emitcode ("movc", "a,@a+dptr");
7838 emitcode ("inc", "dptr");
7839 aopPut (AOP (result), "a", offset++);
7841 _endLazyDPSEvaluation ();
7844 freeAsmop (result, NULL, ic, TRUE);
7847 /*-----------------------------------------------------------------*/
7848 /* genGenPointerGet - gget value from generic pointer space */
7849 /*-----------------------------------------------------------------*/
7851 genGenPointerGet (operand * left,
7852 operand * result, iCode * ic)
7855 sym_link *retype = getSpec (operandType (result));
7856 sym_link *letype = getSpec (operandType (left));
7858 D (emitcode (";", "genGenPointerGet "); );
7860 aopOp (left, ic, FALSE, TRUE);
7862 /* if the operand is already in dptr
7863 then we do nothing else we move the value to dptr */
7864 if (AOP_TYPE (left) != AOP_STR)
7866 /* if this is remateriazable */
7867 if (AOP_TYPE (left) == AOP_IMMD)
7869 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7870 emitcode ("mov", "b,#%d", pointerCode (retype));
7873 { /* we need to get it byte by byte */
7874 _startLazyDPSEvaluation ();
7875 if (AOP(left)->type==AOP_DPTR2) {
7877 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7880 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7881 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7884 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7885 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7888 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7889 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7891 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7892 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7893 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7894 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7896 _endLazyDPSEvaluation ();
7899 /* so dptr know contains the address */
7900 freeAsmop (left, NULL, ic, TRUE);
7901 aopOp (result, ic, FALSE, TRUE);
7903 /* if bit then unpack */
7904 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7905 genUnpackBits (result, "dptr", GPOINTER);
7908 size = AOP_SIZE (result);
7913 emitcode ("lcall", "__gptrget");
7914 aopPut (AOP (result), "a", offset++);
7916 emitcode ("inc", "dptr");
7920 freeAsmop (result, NULL, ic, TRUE);
7923 /*-----------------------------------------------------------------*/
7924 /* genPointerGet - generate code for pointer get */
7925 /*-----------------------------------------------------------------*/
7927 genPointerGet (iCode * ic)
7929 operand *left, *result;
7930 sym_link *type, *etype;
7933 D (emitcode (";", "genPointerGet ");
7936 left = IC_LEFT (ic);
7937 result = IC_RESULT (ic);
7939 /* depending on the type of pointer we need to
7940 move it to the correct pointer register */
7941 type = operandType (left);
7942 etype = getSpec (type);
7943 /* if left is of type of pointer then it is simple */
7944 if (IS_PTR (type) && !IS_FUNC (type->next))
7945 p_type = DCL_TYPE (type);
7948 /* we have to go by the storage class */
7949 p_type = PTR_TYPE (SPEC_OCLS (etype));
7952 /* now that we have the pointer type we assign
7953 the pointer values */
7959 genNearPointerGet (left, result, ic);
7963 genPagedPointerGet (left, result, ic);
7967 genFarPointerGet (left, result, ic);
7971 emitcodePointerGet (left, result, ic);
7975 genGenPointerGet (left, result, ic);
7981 /*-----------------------------------------------------------------*/
7982 /* genPackBits - generates code for packed bit storage */
7983 /*-----------------------------------------------------------------*/
7985 genPackBits (sym_link * etype,
7987 char *rname, int p_type)
7995 blen = SPEC_BLEN (etype);
7996 bstr = SPEC_BSTR (etype);
7998 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8001 /* if the bit lenth is less than or */
8002 /* it exactly fits a byte then */
8003 if (SPEC_BLEN (etype) <= 8)
8005 shCount = SPEC_BSTR (etype);
8007 /* shift left acc */
8010 if (SPEC_BLEN (etype) < 8)
8011 { /* if smaller than a byte */
8017 emitcode ("mov", "b,a");
8018 emitcode ("mov", "a,@%s", rname);
8022 emitcode ("mov", "b,a");
8023 emitcode ("movx", "a,@dptr");
8027 emitcode ("push", "b");
8028 emitcode ("push", "acc");
8029 emitcode ("lcall", "__gptrget");
8030 emitcode ("pop", "b");
8034 emitcode ("anl", "a,#0x%02x", (unsigned char)
8035 ((unsigned char) (0xFF << (blen + bstr)) |
8036 (unsigned char) (0xFF >> (8 - bstr))));
8037 emitcode ("orl", "a,b");
8038 if (p_type == GPOINTER)
8039 emitcode ("pop", "b");
8046 emitcode ("mov", "@%s,a", rname);
8050 emitcode ("movx", "@dptr,a");
8054 emitcode ("lcall", "__gptrput");
8059 if (SPEC_BLEN (etype) <= 8)
8062 emitcode ("inc", "%s", rname);
8063 rLen = SPEC_BLEN (etype);
8065 /* now generate for lengths greater than one byte */
8069 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8081 emitcode ("mov", "@%s,a", rname);
8084 emitcode ("mov", "@%s,%s", rname, l);
8089 emitcode ("movx", "@dptr,a");
8094 emitcode ("lcall", "__gptrput");
8097 emitcode ("inc", "%s", rname);
8102 /* last last was not complete */
8105 /* save the byte & read byte */
8109 emitcode ("mov", "b,a");
8110 emitcode ("mov", "a,@%s", rname);
8114 emitcode ("mov", "b,a");
8115 emitcode ("movx", "a,@dptr");
8119 emitcode ("push", "b");
8120 emitcode ("push", "acc");
8121 emitcode ("lcall", "__gptrget");
8122 emitcode ("pop", "b");
8126 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8127 emitcode ("orl", "a,b");
8130 if (p_type == GPOINTER)
8131 emitcode ("pop", "b");
8137 emitcode ("mov", "@%s,a", rname);
8141 emitcode ("movx", "@dptr,a");
8145 emitcode ("lcall", "__gptrput");
8149 /*-----------------------------------------------------------------*/
8150 /* genDataPointerSet - remat pointer to data space */
8151 /*-----------------------------------------------------------------*/
8153 genDataPointerSet (operand * right,
8157 int size, offset = 0;
8158 char *l, buffer[256];
8160 aopOp (right, ic, FALSE, FALSE);
8162 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8163 size = AOP_SIZE (right);
8167 sprintf (buffer, "(%s + %d)", l + 1, offset);
8169 sprintf (buffer, "%s", l + 1);
8170 emitcode ("mov", "%s,%s", buffer,
8171 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8174 freeAsmop (right, NULL, ic, TRUE);
8175 freeAsmop (result, NULL, ic, TRUE);
8178 /*-----------------------------------------------------------------*/
8179 /* genNearPointerSet - emitcode for near pointer put */
8180 /*-----------------------------------------------------------------*/
8182 genNearPointerSet (operand * right,
8189 sym_link *retype, *letype;
8190 sym_link *ptype = operandType (result);
8192 retype = getSpec (operandType (right));
8193 letype = getSpec (ptype);
8195 aopOp (result, ic, FALSE, FALSE);
8197 /* if the result is rematerializable &
8198 in data space & not a bit variable */
8199 if (AOP_TYPE (result) == AOP_IMMD &&
8200 DCL_TYPE (ptype) == POINTER &&
8201 !IS_BITVAR (retype) &&
8202 !IS_BITVAR (letype))
8204 genDataPointerSet (right, result, ic);
8208 /* if the value is already in a pointer register
8209 then don't need anything more */
8210 if (!AOP_INPREG (AOP (result)))
8212 /* otherwise get a free pointer register */
8214 preg = getFreePtr (ic, &aop, FALSE);
8215 emitcode ("mov", "%s,%s",
8217 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8221 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8223 freeAsmop (result, NULL, ic, TRUE);
8224 aopOp (right, ic, FALSE, FALSE);
8226 /* if bitfield then unpack the bits */
8227 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8228 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8231 /* we have can just get the values */
8232 int size = AOP_SIZE (right);
8237 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8241 emitcode ("mov", "@%s,a", rname);
8244 emitcode ("mov", "@%s,%s", rname, l);
8246 emitcode ("inc", "%s", rname);
8251 /* now some housekeeping stuff */
8254 /* we had to allocate for this iCode */
8255 freeAsmop (NULL, aop, ic, TRUE);
8259 /* we did not allocate which means left
8260 already in a pointer register, then
8261 if size > 0 && this could be used again
8262 we have to point it back to where it
8264 if (AOP_SIZE (right) > 1 &&
8265 !OP_SYMBOL (result)->remat &&
8266 (OP_SYMBOL (result)->liveTo > ic->seq ||
8269 int size = AOP_SIZE (right) - 1;
8271 emitcode ("dec", "%s", rname);
8276 freeAsmop (right, NULL, ic, TRUE);
8281 /*-----------------------------------------------------------------*/
8282 /* genPagedPointerSet - emitcode for Paged pointer put */
8283 /*-----------------------------------------------------------------*/
8285 genPagedPointerSet (operand * right,
8292 sym_link *retype, *letype;
8294 retype = getSpec (operandType (right));
8295 letype = getSpec (operandType (result));
8297 aopOp (result, ic, FALSE, FALSE);
8299 /* if the value is already in a pointer register
8300 then don't need anything more */
8301 if (!AOP_INPREG (AOP (result)))
8303 /* otherwise get a free pointer register */
8305 preg = getFreePtr (ic, &aop, FALSE);
8306 emitcode ("mov", "%s,%s",
8308 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8312 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8314 freeAsmop (result, NULL, ic, TRUE);
8315 aopOp (right, ic, FALSE, FALSE);
8317 /* if bitfield then unpack the bits */
8318 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8319 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8322 /* we have can just get the values */
8323 int size = AOP_SIZE (right);
8328 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8331 emitcode ("movx", "@%s,a", rname);
8334 emitcode ("inc", "%s", rname);
8340 /* now some housekeeping stuff */
8343 /* we had to allocate for this iCode */
8344 freeAsmop (NULL, aop, ic, TRUE);
8348 /* we did not allocate which means left
8349 already in a pointer register, then
8350 if size > 0 && this could be used again
8351 we have to point it back to where it
8353 if (AOP_SIZE (right) > 1 &&
8354 !OP_SYMBOL (result)->remat &&
8355 (OP_SYMBOL (result)->liveTo > ic->seq ||
8358 int size = AOP_SIZE (right) - 1;
8360 emitcode ("dec", "%s", rname);
8365 freeAsmop (right, NULL, ic, TRUE);
8370 /*-----------------------------------------------------------------*/
8371 /* genFarPointerSet - set value from far space */
8372 /*-----------------------------------------------------------------*/
8374 genFarPointerSet (operand * right,
8375 operand * result, iCode * ic)
8378 sym_link *retype = getSpec (operandType (right));
8379 sym_link *letype = getSpec (operandType (result));
8381 aopOp (result, ic, FALSE, FALSE);
8383 /* if the operand is already in dptr
8384 then we do nothing else we move the value to dptr */
8385 if (AOP_TYPE (result) != AOP_STR)
8387 /* if this is remateriazable */
8388 if (AOP_TYPE (result) == AOP_IMMD)
8389 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8392 /* we need to get it byte by byte */
8393 _startLazyDPSEvaluation ();
8394 if (AOP_TYPE (result) != AOP_DPTR)
8396 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8397 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8398 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8402 /* We need to generate a load to DPTR indirect through DPTR. */
8403 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8405 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8406 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8407 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8408 emitcode ("pop", "dph");
8409 emitcode ("pop", "dpl");
8411 _endLazyDPSEvaluation ();
8414 /* so dptr know contains the address */
8415 freeAsmop (result, NULL, ic, TRUE);
8416 aopOp (right, ic, FALSE, TRUE);
8418 /* if bit then unpack */
8419 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8420 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8423 size = AOP_SIZE (right);
8426 _startLazyDPSEvaluation ();
8429 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8435 emitcode ("movx", "@dptr,a");
8437 emitcode ("inc", "dptr");
8439 _endLazyDPSEvaluation ();
8442 freeAsmop (right, NULL, ic, TRUE);
8445 /*-----------------------------------------------------------------*/
8446 /* genGenPointerSet - set value from generic pointer space */
8447 /*-----------------------------------------------------------------*/
8449 genGenPointerSet (operand * right,
8450 operand * result, iCode * ic)
8453 sym_link *retype = getSpec (operandType (right));
8454 sym_link *letype = getSpec (operandType (result));
8456 aopOp (result, ic, FALSE, TRUE);
8458 /* if the operand is already in dptr
8459 then we do nothing else we move the value to dptr */
8460 if (AOP_TYPE (result) != AOP_STR)
8462 _startLazyDPSEvaluation ();
8463 /* if this is remateriazable */
8464 if (AOP_TYPE (result) == AOP_IMMD)
8466 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8467 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8470 { /* we need to get it byte by byte */
8471 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8472 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8473 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8474 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8476 _endLazyDPSEvaluation ();
8478 /* so dptr know contains the address */
8479 freeAsmop (result, NULL, ic, TRUE);
8480 aopOp (right, ic, FALSE, TRUE);
8482 /* if bit then unpack */
8483 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8484 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8487 size = AOP_SIZE (right);
8490 _startLazyDPSEvaluation ();
8493 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8499 emitcode ("lcall", "__gptrput");
8501 emitcode ("inc", "dptr");
8503 _endLazyDPSEvaluation ();
8506 freeAsmop (right, NULL, ic, TRUE);
8509 /*-----------------------------------------------------------------*/
8510 /* genPointerSet - stores the value into a pointer location */
8511 /*-----------------------------------------------------------------*/
8513 genPointerSet (iCode * ic)
8515 operand *right, *result;
8516 sym_link *type, *etype;
8519 D (emitcode (";", "genPointerSet ");
8522 right = IC_RIGHT (ic);
8523 result = IC_RESULT (ic);
8525 /* depending on the type of pointer we need to
8526 move it to the correct pointer register */
8527 type = operandType (result);
8528 etype = getSpec (type);
8529 /* if left is of type of pointer then it is simple */
8530 if (IS_PTR (type) && !IS_FUNC (type->next))
8532 p_type = DCL_TYPE (type);
8536 /* we have to go by the storage class */
8537 p_type = PTR_TYPE (SPEC_OCLS (etype));
8540 /* now that we have the pointer type we assign
8541 the pointer values */
8547 genNearPointerSet (right, result, ic);
8551 genPagedPointerSet (right, result, ic);
8555 genFarPointerSet (right, result, ic);
8559 genGenPointerSet (right, result, ic);
8565 /*-----------------------------------------------------------------*/
8566 /* genIfx - generate code for Ifx statement */
8567 /*-----------------------------------------------------------------*/
8569 genIfx (iCode * ic, iCode * popIc)
8571 operand *cond = IC_COND (ic);
8574 D (emitcode (";", "genIfx ");
8577 aopOp (cond, ic, FALSE, FALSE);
8579 /* get the value into acc */
8580 if (AOP_TYPE (cond) != AOP_CRY)
8584 /* the result is now in the accumulator */
8585 freeAsmop (cond, NULL, ic, TRUE);
8587 /* if there was something to be popped then do it */
8591 /* if the condition is a bit variable */
8592 if (isbit && IS_ITEMP (cond) &&
8594 genIfxJump (ic, SPIL_LOC (cond)->rname);
8595 else if (isbit && !IS_ITEMP (cond))
8596 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8598 genIfxJump (ic, "a");
8603 /*-----------------------------------------------------------------*/
8604 /* genAddrOf - generates code for address of */
8605 /*-----------------------------------------------------------------*/
8607 genAddrOf (iCode * ic)
8609 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8612 D (emitcode (";", "genAddrOf ");
8615 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8617 /* if the operand is on the stack then we
8618 need to get the stack offset of this
8622 /* if it has an offset then we need to compute
8626 emitcode ("mov", "a,_bp");
8627 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8628 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8632 /* we can just move _bp */
8633 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8635 /* fill the result with zero */
8636 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8639 if (options.stack10bit && size < (FPTRSIZE - 1))
8642 "*** warning: pointer to stack var truncated.\n");
8649 if (options.stack10bit && offset == 2)
8651 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8655 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8662 /* object not on stack then we need the name */
8663 size = AOP_SIZE (IC_RESULT (ic));
8668 char s[SDCC_NAME_MAX];
8670 sprintf (s, "#(%s >> %d)",
8674 sprintf (s, "#%s", sym->rname);
8675 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8679 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8683 /*-----------------------------------------------------------------*/
8684 /* genFarFarAssign - assignment when both are in far space */
8685 /*-----------------------------------------------------------------*/
8687 genFarFarAssign (operand * result, operand * right, iCode * ic)
8689 int size = AOP_SIZE (right);
8695 /* This is a net loss for size == 1, but a big gain
8698 D (emitcode (";", "genFarFarAssign (improved)");
8701 aopOp (result, ic, TRUE, TRUE);
8703 _startLazyDPSEvaluation ();
8706 aopPut (AOP (result),
8707 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8710 _endLazyDPSEvaluation ();
8711 freeAsmop (result, NULL, ic, FALSE);
8712 freeAsmop (right, NULL, ic, FALSE);
8716 D (emitcode (";", "genFarFarAssign ");
8719 /* first push the right side on to the stack */
8720 _startLazyDPSEvaluation ();
8723 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8725 emitcode ("push", "acc");
8728 freeAsmop (right, NULL, ic, FALSE);
8729 /* now assign DPTR to result */
8730 aopOp (result, ic, FALSE, FALSE);
8731 size = AOP_SIZE (result);
8734 emitcode ("pop", "acc");
8735 aopPut (AOP (result), "a", --offset);
8737 freeAsmop (result, NULL, ic, FALSE);
8738 _endLazyDPSEvaluation ();
8742 /*-----------------------------------------------------------------*/
8743 /* genAssign - generate code for assignment */
8744 /*-----------------------------------------------------------------*/
8746 genAssign (iCode * ic)
8748 operand *result, *right;
8750 unsigned long lit = 0L;
8752 D (emitcode (";", "genAssign ");
8755 result = IC_RESULT (ic);
8756 right = IC_RIGHT (ic);
8758 /* if they are the same */
8759 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8762 aopOp (right, ic, FALSE, FALSE);
8764 emitcode (";", "genAssign: resultIsFar = %s",
8765 isOperandInFarSpace (result) ?
8768 /* special case both in far space */
8769 if ((AOP_TYPE (right) == AOP_DPTR ||
8770 AOP_TYPE (right) == AOP_DPTR2) &&
8771 /* IS_TRUE_SYMOP(result) && */
8772 isOperandInFarSpace (result))
8774 genFarFarAssign (result, right, ic);
8778 aopOp (result, ic, TRUE, FALSE);
8780 /* if they are the same registers */
8781 if (sameRegs (AOP (right), AOP (result)))
8784 /* if the result is a bit */
8785 if (AOP_TYPE (result) == AOP_CRY)
8788 /* if the right size is a literal then
8789 we know what the value is */
8790 if (AOP_TYPE (right) == AOP_LIT)
8792 if (((int) operandLitValue (right)))
8793 aopPut (AOP (result), one, 0);
8795 aopPut (AOP (result), zero, 0);
8799 /* the right is also a bit variable */
8800 if (AOP_TYPE (right) == AOP_CRY)
8802 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8803 aopPut (AOP (result), "c", 0);
8809 aopPut (AOP (result), "a", 0);
8813 /* bit variables done */
8815 size = AOP_SIZE (result);
8817 if (AOP_TYPE (right) == AOP_LIT)
8818 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8821 (AOP_TYPE (result) != AOP_REG) &&
8822 (AOP_TYPE (right) == AOP_LIT) &&
8823 !IS_FLOAT (operandType (right)))
8825 D (emitcode (";", "Kevin's better literal load code");
8827 _startLazyDPSEvaluation ();
8828 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8830 aopPut (AOP (result),
8831 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8836 /* And now fill the rest with zeros. */
8839 emitcode ("clr", "a");
8843 aopPut (AOP (result), "a", offset++);
8845 _endLazyDPSEvaluation ();
8849 _startLazyDPSEvaluation ();
8852 aopPut (AOP (result),
8853 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8857 _endLazyDPSEvaluation ();
8861 freeAsmop (right, NULL, ic, FALSE);
8862 freeAsmop (result, NULL, ic, TRUE);
8865 /*-----------------------------------------------------------------*/
8866 /* genJumpTab - generates code for jump table */
8867 /*-----------------------------------------------------------------*/
8869 genJumpTab (iCode * ic)
8874 D (emitcode (";", "genJumpTab ");
8877 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8878 /* get the condition into accumulator */
8879 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8881 /* multiply by four! */
8882 emitcode ("add", "a,acc");
8883 emitcode ("add", "a,acc");
8884 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8886 jtab = newiTempLabel (NULL);
8887 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8888 emitcode ("jmp", "@a+dptr");
8889 emitcode ("", "%05d$:", jtab->key + 100);
8890 /* now generate the jump labels */
8891 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8892 jtab = setNextItem (IC_JTLABELS (ic)))
8893 emitcode ("ljmp", "%05d$", jtab->key + 100);
8897 /*-----------------------------------------------------------------*/
8898 /* genCast - gen code for casting */
8899 /*-----------------------------------------------------------------*/
8901 genCast (iCode * ic)
8903 operand *result = IC_RESULT (ic);
8904 sym_link *ctype = operandType (IC_LEFT (ic));
8905 sym_link *rtype = operandType (IC_RIGHT (ic));
8906 operand *right = IC_RIGHT (ic);
8909 D (emitcode (";", "genCast ");
8912 /* if they are equivalent then do nothing */
8913 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8916 aopOp (right, ic, FALSE, FALSE);
8917 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8919 /* if the result is a bit */
8920 if (AOP_TYPE (result) == AOP_CRY)
8922 /* if the right size is a literal then
8923 we know what the value is */
8924 if (AOP_TYPE (right) == AOP_LIT)
8926 if (((int) operandLitValue (right)))
8927 aopPut (AOP (result), one, 0);
8929 aopPut (AOP (result), zero, 0);
8934 /* the right is also a bit variable */
8935 if (AOP_TYPE (right) == AOP_CRY)
8937 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8938 aopPut (AOP (result), "c", 0);
8944 aopPut (AOP (result), "a", 0);
8948 /* if they are the same size : or less */
8949 if (AOP_SIZE (result) <= AOP_SIZE (right))
8952 /* if they are in the same place */
8953 if (sameRegs (AOP (right), AOP (result)))
8956 /* if they in different places then copy */
8957 size = AOP_SIZE (result);
8959 _startLazyDPSEvaluation ();
8962 aopPut (AOP (result),
8963 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8967 _endLazyDPSEvaluation ();
8972 /* if the result is of type pointer */
8977 sym_link *type = operandType (right);
8979 /* pointer to generic pointer */
8980 if (IS_GENPTR (ctype))
8986 p_type = DCL_TYPE (type);
8990 #if OLD_CAST_BEHAVIOR
8991 /* KV: we are converting a non-pointer type to
8992 * a generic pointer. This (ifdef'd out) code
8993 * says that the resulting generic pointer
8994 * should have the same class as the storage
8995 * location of the non-pointer variable.
8997 * For example, converting an int (which happens
8998 * to be stored in DATA space) to a pointer results
8999 * in a DATA generic pointer; if the original int
9000 * in XDATA space, so will be the resulting pointer.
9002 * I don't like that behavior, and thus this change:
9003 * all such conversions will be forced to XDATA and
9004 * throw a warning. If you want some non-XDATA
9005 * type, or you want to suppress the warning, you
9006 * must go through an intermediate cast, like so:
9008 * char _generic *gp = (char _xdata *)(intVar);
9010 sym_link *etype = getSpec (type);
9012 /* we have to go by the storage class */
9013 if (SPEC_OCLS (etype) != generic)
9015 p_type = PTR_TYPE (SPEC_OCLS (etype));
9020 /* Converting unknown class (i.e. register variable)
9021 * to generic pointer. This is not good, but
9022 * we'll make a guess (and throw a warning).
9025 werror (W_INT_TO_GEN_PTR_CAST);
9029 /* the first two bytes are known */
9030 size = GPTRSIZE - 1;
9032 _startLazyDPSEvaluation ();
9035 aopPut (AOP (result),
9036 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9040 _endLazyDPSEvaluation ();
9042 /* the last byte depending on type */
9060 /* this should never happen */
9061 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9062 "got unknown pointer type");
9065 aopPut (AOP (result), l, GPTRSIZE - 1);
9069 /* just copy the pointers */
9070 size = AOP_SIZE (result);
9072 _startLazyDPSEvaluation ();
9075 aopPut (AOP (result),
9076 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9080 _endLazyDPSEvaluation ();
9084 /* so we now know that the size of destination is greater
9085 than the size of the source */
9086 /* we move to result for the size of source */
9087 size = AOP_SIZE (right);
9089 _startLazyDPSEvaluation ();
9092 aopPut (AOP (result),
9093 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9097 _endLazyDPSEvaluation ();
9099 /* now depending on the sign of the source && destination */
9100 size = AOP_SIZE (result) - AOP_SIZE (right);
9101 /* if unsigned or not an integral type */
9102 /* also, if the source is a bit, we don't need to sign extend, because
9103 * it can't possibly have set the sign bit.
9105 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9109 aopPut (AOP (result), zero, offset++);
9114 /* we need to extend the sign :{ */
9115 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9116 FALSE, FALSE, TRUE);
9118 emitcode ("rlc", "a");
9119 emitcode ("subb", "a,acc");
9121 aopPut (AOP (result), "a", offset++);
9124 /* we are done hurray !!!! */
9127 freeAsmop (right, NULL, ic, TRUE);
9128 freeAsmop (result, NULL, ic, TRUE);
9132 /*-----------------------------------------------------------------*/
9133 /* genDjnz - generate decrement & jump if not zero instrucion */
9134 /*-----------------------------------------------------------------*/
9136 genDjnz (iCode * ic, iCode * ifx)
9142 /* if the if condition has a false label
9143 then we cannot save */
9147 /* if the minus is not of the form
9149 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9150 !IS_OP_LITERAL (IC_RIGHT (ic)))
9153 if (operandLitValue (IC_RIGHT (ic)) != 1)
9156 /* if the size of this greater than one then no
9158 if (getSize (operandType (IC_RESULT (ic))) > 1)
9161 /* otherwise we can save BIG */
9162 lbl = newiTempLabel (NULL);
9163 lbl1 = newiTempLabel (NULL);
9165 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9167 if (IS_AOP_PREG (IC_RESULT (ic)))
9169 emitcode ("dec", "%s",
9170 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9171 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9172 emitcode ("jnz", "%05d$", lbl->key + 100);
9176 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9179 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9180 emitcode ("", "%05d$:", lbl->key + 100);
9181 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9182 emitcode ("", "%05d$:", lbl1->key + 100);
9184 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9189 /*-----------------------------------------------------------------*/
9190 /* genReceive - generate code for a receive iCode */
9191 /*-----------------------------------------------------------------*/
9193 genReceive (iCode * ic)
9196 D (emitcode (";", "genReceive ");
9199 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9200 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9201 IS_TRUE_SYMOP (IC_RESULT (ic))))
9203 int size = getSize (operandType (IC_RESULT (ic)));
9204 int offset = fReturnSize_390 - size;
9207 emitcode ("push", "%s", (strcmp (fReturn[fReturnSize_390 - offset - 1], "a") ?
9208 fReturn[fReturnSize_390 - offset - 1] : "acc"));
9211 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9212 size = AOP_SIZE (IC_RESULT (ic));
9216 emitcode ("pop", "acc");
9217 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9224 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9226 assignResultValue (IC_RESULT (ic));
9229 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9232 /*-----------------------------------------------------------------*/
9233 /* gen390Code - generate code for Dallas 390 based controllers */
9234 /*-----------------------------------------------------------------*/
9236 gen390Code (iCode * lic)
9241 lineHead = lineCurr = NULL;
9245 /* print the allocation information */
9247 printAllocInfo (currFunc, codeOutFile);
9249 /* if debug information required */
9250 if (options.debug && currFunc)
9252 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9254 if (IS_STATIC (currFunc->etype))
9255 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9257 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9260 /* stack pointer name */
9261 if (options.useXstack)
9267 for (ic = lic; ic; ic = ic->next)
9270 if (cln != ic->lineno)
9275 emitcode ("", "C$%s$%d$%d$%d ==.",
9276 FileBaseName (ic->filename), ic->lineno,
9277 ic->level, ic->block);
9280 emitcode (";", "%s %d", ic->filename, ic->lineno);
9283 /* if the result is marked as
9284 spilt and rematerializable or code for
9285 this has already been generated then
9287 if (resultRemat (ic) || ic->generated)
9290 /* depending on the operation */
9310 /* IPOP happens only when trying to restore a
9311 spilt live range, if there is an ifx statement
9312 following this pop then the if statement might
9313 be using some of the registers being popped which
9314 would destory the contents of the register so
9315 we need to check for this condition and handle it */
9317 ic->next->op == IFX &&
9318 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9319 genIfx (ic->next, ic);
9337 genEndFunction (ic);
9357 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9374 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9378 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9385 /* note these two are xlated by algebraic equivalence
9386 during parsing SDCC.y */
9387 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9388 "got '>=' or '<=' shouldn't have come here");
9392 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9404 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9408 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9412 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9439 case GET_VALUE_AT_ADDRESS:
9444 if (POINTER_SET (ic))
9471 addSet (&_G.sendSet, ic);
9476 /* piCode(ic,stdout); */
9482 /* now we are ready to call the
9483 peep hole optimizer */
9484 if (!options.nopeep)
9485 peepHole (&lineHead);
9487 /* now do the actual printing */
9488 printLine (lineHead, codeOutFile);