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", 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", 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 ");
1944 /* if this is not a parm push : ie. it is spill push
1945 and spill push is always done on the local stack */
1949 /* and the item is spilt then do nothing */
1950 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1953 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1954 size = AOP_SIZE (IC_LEFT (ic));
1955 /* push it on the stack */
1956 _startLazyDPSEvaluation ();
1959 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1965 emitcode ("push", "%s", l);
1967 _endLazyDPSEvaluation ();
1971 /* this is a paramter push: in this case we call
1972 the routine to find the call and save those
1973 registers that need to be saved */
1976 /* if use external stack then call the external
1977 stack pushing routine */
1978 if (options.useXstack)
1984 /* then do the push */
1985 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1987 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1988 size = AOP_SIZE (IC_LEFT (ic));
1990 _startLazyDPSEvaluation ();
1993 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1994 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1995 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1998 emitcode ("mov", "a,%s", l);
1999 emitcode ("push", "acc");
2002 emitcode ("push", "%s", l);
2004 _endLazyDPSEvaluation ();
2006 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2009 /*-----------------------------------------------------------------*/
2010 /* genIpop - recover the registers: can happen only for spilling */
2011 /*-----------------------------------------------------------------*/
2013 genIpop (iCode * ic)
2017 D (emitcode (";", "genIpop ");
2021 /* if the temp was not pushed then */
2022 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2025 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2026 size = AOP_SIZE (IC_LEFT (ic));
2027 offset = (size - 1);
2028 _startLazyDPSEvaluation ();
2031 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2032 FALSE, TRUE, TRUE));
2034 _endLazyDPSEvaluation ();
2036 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2039 /*-----------------------------------------------------------------*/
2040 /* unsaverbank - restores the resgister bank from stack */
2041 /*-----------------------------------------------------------------*/
2043 unsaverbank (int bank, iCode * ic, bool popPsw)
2051 if (options.useXstack)
2054 r = getFreePtr (ic, &aop, FALSE);
2057 emitcode ("mov", "%s,_spx", r->name);
2058 emitcode ("movx", "a,@%s", r->name);
2059 emitcode ("mov", "psw,a");
2060 emitcode ("dec", "%s", r->name);
2064 emitcode ("pop", "psw");
2067 for (i = (ds390_nRegs - 1); i >= 0; i--)
2069 if (options.useXstack)
2071 emitcode ("movx", "a,@%s", r->name);
2072 emitcode ("mov", "(%s+%d),a",
2073 regs390[i].base, 8 * bank + regs390[i].offset);
2074 emitcode ("dec", "%s", r->name);
2078 emitcode ("pop", "(%s+%d)",
2079 regs390[i].base, 8 * bank + regs390[i].offset);
2082 if (options.useXstack)
2085 emitcode ("mov", "_spx,%s", r->name);
2086 freeAsmop (NULL, aop, ic, TRUE);
2091 /*-----------------------------------------------------------------*/
2092 /* saverbank - saves an entire register bank on the stack */
2093 /*-----------------------------------------------------------------*/
2095 saverbank (int bank, iCode * ic, bool pushPsw)
2101 if (options.useXstack)
2105 r = getFreePtr (ic, &aop, FALSE);
2106 emitcode ("mov", "%s,_spx", r->name);
2110 for (i = 0; i < ds390_nRegs; i++)
2112 if (options.useXstack)
2114 emitcode ("inc", "%s", r->name);
2115 emitcode ("mov", "a,(%s+%d)",
2116 regs390[i].base, 8 * bank + regs390[i].offset);
2117 emitcode ("movx", "@%s,a", r->name);
2120 emitcode ("push", "(%s+%d)",
2121 regs390[i].base, 8 * bank + regs390[i].offset);
2126 if (options.useXstack)
2128 emitcode ("mov", "a,psw");
2129 emitcode ("movx", "@%s,a", r->name);
2130 emitcode ("inc", "%s", r->name);
2131 emitcode ("mov", "_spx,%s", r->name);
2132 freeAsmop (NULL, aop, ic, TRUE);
2136 emitcode ("push", "psw");
2138 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2144 /*-----------------------------------------------------------------*/
2145 /* genCall - generates a call statement */
2146 /*-----------------------------------------------------------------*/
2148 genCall (iCode * ic)
2152 D (emitcode (";", "genCall ");
2155 /* if caller saves & we have not saved then */
2159 /* if we are calling a function that is not using
2160 the same register bank then we need to save the
2161 destination registers on the stack */
2162 detype = getSpec (operandType (IC_LEFT (ic)));
2164 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2165 IS_ISR (currFunc->etype) &&
2168 saverbank (SPEC_BANK (detype), ic, TRUE);
2170 /* if send set is not empty the assign */
2175 for (sic = setFirstItem (_G.sendSet); sic;
2176 sic = setNextItem (_G.sendSet))
2178 int size, offset = 0;
2180 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2181 size = AOP_SIZE (IC_LEFT (sic));
2183 _startLazyDPSEvaluation ();
2186 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2187 FALSE, FALSE, TRUE);
2188 if (strcmp (l, fReturn[offset])) {
2191 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2197 _endLazyDPSEvaluation ();
2198 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2203 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2204 OP_SYMBOL (IC_LEFT (ic))->rname :
2205 OP_SYMBOL (IC_LEFT (ic))->name));
2207 /* if we need assign a result value */
2208 if ((IS_ITEMP (IC_RESULT (ic)) &&
2209 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2210 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2211 IS_TRUE_SYMOP (IC_RESULT (ic)))
2213 if (isOperandInFarSpace (IC_RESULT (ic))
2214 && getSize (operandType (IC_RESULT (ic))) <= 2)
2216 int size = getSize (operandType (IC_RESULT (ic)));
2218 /* Special case for 1 or 2 byte return in far space. */
2219 emitcode (";", "Kevin function call abuse #1");
2224 emitcode ("mov", "b,%s", fReturn[1]);
2227 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2228 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2232 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2234 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2239 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2242 assignResultValue (IC_RESULT (ic));
2244 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2248 /* adjust the stack for parameters if
2250 if (IC_LEFT (ic)->parmBytes)
2253 if (IC_LEFT (ic)->parmBytes > 3)
2255 emitcode ("mov", "a,%s", spname);
2256 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
2257 emitcode ("mov", "%s,a", spname);
2260 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
2261 emitcode ("dec", "%s", spname);
2265 /* if register bank was saved then pop them */
2267 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2269 /* if we hade saved some registers then unsave them */
2270 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2271 unsaveRegisters (ic);
2276 /*-----------------------------------------------------------------*/
2277 /* genPcall - generates a call by pointer statement */
2278 /*-----------------------------------------------------------------*/
2280 genPcall (iCode * ic)
2283 symbol *rlbl = newiTempLabel (NULL);
2285 D (emitcode (";", "genPcall ");
2289 /* if caller saves & we have not saved then */
2293 /* if we are calling a function that is not using
2294 the same register bank then we need to save the
2295 destination registers on the stack */
2296 detype = getSpec (operandType (IC_LEFT (ic)));
2298 IS_ISR (currFunc->etype) &&
2299 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2300 saverbank (SPEC_BANK (detype), ic, TRUE);
2303 /* push the return address on to the stack */
2304 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2305 emitcode ("push", "acc");
2306 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2307 emitcode ("push", "acc");
2309 if (options.model == MODEL_FLAT24)
2311 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2312 emitcode ("push", "acc");
2315 /* now push the calling address */
2316 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2318 pushSide (IC_LEFT (ic), FPTRSIZE);
2320 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2322 /* if send set is not empty the assign */
2327 for (sic = setFirstItem (_G.sendSet); sic;
2328 sic = setNextItem (_G.sendSet))
2330 int size, offset = 0;
2332 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2333 size = AOP_SIZE (IC_LEFT (sic));
2334 _startLazyDPSEvaluation ();
2337 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2338 FALSE, FALSE, TRUE);
2339 if (strcmp (l, fReturn[offset]))
2341 emitcode ("mov", "%s,%s",
2347 _endLazyDPSEvaluation ();
2348 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2353 emitcode ("ret", "");
2354 emitcode ("", "%05d$:", (rlbl->key + 100));
2357 /* if we need assign a result value */
2358 if ((IS_ITEMP (IC_RESULT (ic)) &&
2359 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2360 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2361 IS_TRUE_SYMOP (IC_RESULT (ic)))
2365 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2368 assignResultValue (IC_RESULT (ic));
2370 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2373 /* adjust the stack for parameters if
2375 if (IC_LEFT (ic)->parmBytes)
2378 if (IC_LEFT (ic)->parmBytes > 3)
2380 emitcode ("mov", "a,%s", spname);
2381 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
2382 emitcode ("mov", "%s,a", spname);
2385 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
2386 emitcode ("dec", "%s", spname);
2390 /* if register bank was saved then unsave them */
2392 (SPEC_BANK (currFunc->etype) !=
2393 SPEC_BANK (detype)))
2394 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2396 /* if we hade saved some registers then
2399 unsaveRegisters (ic);
2403 /*-----------------------------------------------------------------*/
2404 /* resultRemat - result is rematerializable */
2405 /*-----------------------------------------------------------------*/
2407 resultRemat (iCode * ic)
2409 if (SKIP_IC (ic) || ic->op == IFX)
2412 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2414 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2415 if (sym->remat && !POINTER_SET (ic))
2422 #if defined(__BORLANDC__) || defined(_MSC_VER)
2423 #define STRCASECMP stricmp
2425 #define STRCASECMP strcasecmp
2428 /*-----------------------------------------------------------------*/
2429 /* inExcludeList - return 1 if the string is in exclude Reg list */
2430 /*-----------------------------------------------------------------*/
2432 inExcludeList (char *s)
2436 if (options.excludeRegs[i] &&
2437 STRCASECMP (options.excludeRegs[i], "none") == 0)
2440 for (i = 0; options.excludeRegs[i]; i++)
2442 if (options.excludeRegs[i] &&
2443 STRCASECMP (s, options.excludeRegs[i]) == 0)
2449 /*-----------------------------------------------------------------*/
2450 /* genFunction - generated code for function entry */
2451 /*-----------------------------------------------------------------*/
2453 genFunction (iCode * ic)
2458 D (emitcode (";", "genFunction ");
2462 /* create the function header */
2463 emitcode (";", "-----------------------------------------");
2464 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2465 emitcode (";", "-----------------------------------------");
2467 emitcode ("", "%s:", sym->rname);
2468 fetype = getSpec (operandType (IC_LEFT (ic)));
2470 /* if critical function then turn interrupts off */
2471 if (SPEC_CRTCL (fetype))
2472 emitcode ("clr", "ea");
2474 /* here we need to generate the equates for the
2475 register bank if required */
2476 if (SPEC_BANK (fetype) != rbank)
2480 rbank = SPEC_BANK (fetype);
2481 for (i = 0; i < ds390_nRegs; i++)
2483 if (strcmp (regs390[i].base, "0") == 0)
2484 emitcode ("", "%s = 0x%02x",
2486 8 * rbank + regs390[i].offset);
2488 emitcode ("", "%s = %s + 0x%02x",
2491 8 * rbank + regs390[i].offset);
2495 /* if this is an interrupt service routine then
2496 save acc, b, dpl, dph */
2497 if (IS_ISR (sym->etype))
2500 if (!inExcludeList ("acc"))
2501 emitcode ("push", "acc");
2502 if (!inExcludeList ("b"))
2503 emitcode ("push", "b");
2504 if (!inExcludeList ("dpl"))
2505 emitcode ("push", "dpl");
2506 if (!inExcludeList ("dph"))
2507 emitcode ("push", "dph");
2508 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2510 emitcode ("push", "dpx");
2511 /* Make sure we're using standard DPTR */
2512 emitcode ("push", "dps");
2513 emitcode ("mov", "dps, #0x00");
2514 if (options.stack10bit)
2516 /* This ISR could conceivably use DPTR2. Better save it. */
2517 emitcode ("push", "dpl1");
2518 emitcode ("push", "dph1");
2519 emitcode ("push", "dpx1");
2520 emitcode ("push", "ap");
2523 /* if this isr has no bank i.e. is going to
2524 run with bank 0 , then we need to save more
2526 if (!SPEC_BANK (sym->etype))
2529 /* if this function does not call any other
2530 function then we can be economical and
2531 save only those registers that are used */
2536 /* if any registers used */
2539 /* save the registers used */
2540 for (i = 0; i < sym->regsUsed->size; i++)
2542 if (bitVectBitValue (sym->regsUsed, i) ||
2543 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2544 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2551 /* this function has a function call cannot
2552 determines register usage so we will have the
2554 saverbank (0, ic, FALSE);
2560 /* if callee-save to be used for this function
2561 then save the registers being used in this function */
2562 if (sym->calleeSave)
2566 /* if any registers used */
2569 /* save the registers used */
2570 for (i = 0; i < sym->regsUsed->size; i++)
2572 if (bitVectBitValue (sym->regsUsed, i) ||
2573 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2575 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2583 /* set the register bank to the desired value */
2584 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2586 emitcode ("push", "psw");
2587 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2590 if (IS_RENT (sym->etype) || options.stackAuto)
2593 if (options.useXstack)
2595 emitcode ("mov", "r0,%s", spname);
2596 emitcode ("mov", "a,_bp");
2597 emitcode ("movx", "@r0,a");
2598 emitcode ("inc", "%s", spname);
2602 /* set up the stack */
2603 emitcode ("push", "_bp"); /* save the callers stack */
2605 emitcode ("mov", "_bp,%s", spname);
2608 /* adjust the stack for the function */
2614 werror (W_STACK_OVERFLOW, sym->name);
2616 if (i > 3 && sym->recvSize < 4)
2619 emitcode ("mov", "a,sp");
2620 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2621 emitcode ("mov", "sp,a");
2626 emitcode ("inc", "sp");
2632 emitcode ("mov", "a,_spx");
2633 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2634 emitcode ("mov", "_spx,a");
2639 /*-----------------------------------------------------------------*/
2640 /* genEndFunction - generates epilogue for functions */
2641 /*-----------------------------------------------------------------*/
2643 genEndFunction (iCode * ic)
2645 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2647 D (emitcode (";", "genEndFunction ");
2650 if (IS_RENT (sym->etype) || options.stackAuto)
2652 emitcode ("mov", "%s,_bp", spname);
2655 /* if use external stack but some variables were
2656 added to the local stack then decrement the
2658 if (options.useXstack && sym->stack)
2660 emitcode ("mov", "a,sp");
2661 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2662 emitcode ("mov", "sp,a");
2666 if ((IS_RENT (sym->etype) || options.stackAuto))
2668 if (options.useXstack)
2670 emitcode ("mov", "r0,%s", spname);
2671 emitcode ("movx", "a,@r0");
2672 emitcode ("mov", "_bp,a");
2673 emitcode ("dec", "%s", spname);
2677 emitcode ("pop", "_bp");
2681 /* restore the register bank */
2682 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2683 emitcode ("pop", "psw");
2685 if (IS_ISR (sym->etype))
2688 /* now we need to restore the registers */
2689 /* if this isr has no bank i.e. is going to
2690 run with bank 0 , then we need to save more
2692 if (!SPEC_BANK (sym->etype))
2695 /* if this function does not call any other
2696 function then we can be economical and
2697 save only those registers that are used */
2702 /* if any registers used */
2705 /* save the registers used */
2706 for (i = sym->regsUsed->size; i >= 0; i--)
2708 if (bitVectBitValue (sym->regsUsed, i) ||
2709 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2710 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2717 /* this function has a function call cannot
2718 determines register usage so we will have the
2720 unsaverbank (0, ic, FALSE);
2724 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2726 if (options.stack10bit)
2728 emitcode ("pop", "ap");
2729 emitcode ("pop", "dpx1");
2730 emitcode ("pop", "dph1");
2731 emitcode ("pop", "dpl1");
2733 emitcode ("pop", "dps");
2734 emitcode ("pop", "dpx");
2736 if (!inExcludeList ("dph"))
2737 emitcode ("pop", "dph");
2738 if (!inExcludeList ("dpl"))
2739 emitcode ("pop", "dpl");
2740 if (!inExcludeList ("b"))
2741 emitcode ("pop", "b");
2742 if (!inExcludeList ("acc"))
2743 emitcode ("pop", "acc");
2745 if (SPEC_CRTCL (sym->etype))
2746 emitcode ("setb", "ea");
2748 /* if debug then send end of function */
2749 /* if (options.debug && currFunc) { */
2753 emitcode ("", "C$%s$%d$%d$%d ==.",
2754 FileBaseName (ic->filename), currFunc->lastLine,
2755 ic->level, ic->block);
2756 if (IS_STATIC (currFunc->etype))
2757 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2759 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2763 emitcode ("reti", "");
2767 if (SPEC_CRTCL (sym->etype))
2768 emitcode ("setb", "ea");
2770 if (sym->calleeSave)
2774 /* if any registers used */
2777 /* save the registers used */
2778 for (i = sym->regsUsed->size; i >= 0; i--)
2780 if (bitVectBitValue (sym->regsUsed, i) ||
2781 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2782 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2788 /* if debug then send end of function */
2792 emitcode ("", "C$%s$%d$%d$%d ==.",
2793 FileBaseName (ic->filename), currFunc->lastLine,
2794 ic->level, ic->block);
2795 if (IS_STATIC (currFunc->etype))
2796 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2798 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2802 emitcode ("ret", "");
2807 /*-----------------------------------------------------------------*/
2808 /* genRet - generate code for return statement */
2809 /*-----------------------------------------------------------------*/
2813 int size, offset = 0, pushed = 0;
2815 D (emitcode (";", "genRet ");
2818 /* if we have no return value then
2819 just generate the "ret" */
2823 /* we have something to return then
2824 move the return value into place */
2825 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2826 size = AOP_SIZE (IC_LEFT (ic));
2828 _startLazyDPSEvaluation ();
2832 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2834 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2835 FALSE, TRUE, FALSE);
2836 emitcode ("push", "%s", l);
2841 l = aopGet (AOP (IC_LEFT (ic)), offset,
2842 FALSE, FALSE, FALSE);
2843 if (strcmp (fReturn[offset], l))
2844 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2847 _endLazyDPSEvaluation ();
2854 if (strcmp (fReturn[pushed], "a"))
2855 emitcode ("pop", fReturn[pushed]);
2857 emitcode ("pop", "acc");
2860 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2863 /* generate a jump to the return label
2864 if the next is not the return statement */
2865 if (!(ic->next && ic->next->op == LABEL &&
2866 IC_LABEL (ic->next) == returnLabel))
2868 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2872 /*-----------------------------------------------------------------*/
2873 /* genLabel - generates a label */
2874 /*-----------------------------------------------------------------*/
2876 genLabel (iCode * ic)
2878 /* special case never generate */
2879 if (IC_LABEL (ic) == entryLabel)
2882 D (emitcode (";", "genLabel ");
2885 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2888 /*-----------------------------------------------------------------*/
2889 /* genGoto - generates a ljmp */
2890 /*-----------------------------------------------------------------*/
2892 genGoto (iCode * ic)
2894 D (emitcode (";", "genGoto ");
2896 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2899 /*-----------------------------------------------------------------*/
2900 /* findLabelBackwards: walks back through the iCode chain looking */
2901 /* for the given label. Returns number of iCode instructions */
2902 /* between that label and given ic. */
2903 /* Returns zero if label not found. */
2904 /*-----------------------------------------------------------------*/
2906 findLabelBackwards (iCode * ic, int key)
2915 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2917 /* printf("findLabelBackwards = %d\n", count); */
2925 /*-----------------------------------------------------------------*/
2926 /* genPlusIncr :- does addition with increment if possible */
2927 /*-----------------------------------------------------------------*/
2929 genPlusIncr (iCode * ic)
2931 unsigned int icount;
2932 unsigned int size = getDataSize (IC_RESULT (ic));
2934 /* will try to generate an increment */
2935 /* if the right side is not a literal
2937 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2940 /* if the literal value of the right hand side
2941 is greater than 4 then it is not worth it */
2942 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2945 /* if increment 16 bits in register */
2947 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2948 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2949 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2957 /* If the next instruction is a goto and the goto target
2958 * is <= 5 instructions previous to this, we can generate
2959 * jumps straight to that target.
2961 if (ic->next && ic->next->op == GOTO
2962 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2965 emitcode (";", "tail increment optimized (range %d)", labelRange);
2966 tlbl = IC_LABEL (ic->next);
2971 tlbl = newiTempLabel (NULL);
2974 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2975 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2976 IS_AOP_PREG (IC_RESULT (ic)))
2977 emitcode ("cjne", "%s,#0x00,%05d$"
2978 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2982 emitcode ("clr", "a");
2983 emitcode ("cjne", "a,%s,%05d$"
2984 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2988 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2991 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2992 IS_AOP_PREG (IC_RESULT (ic)))
2993 emitcode ("cjne", "%s,#0x00,%05d$"
2994 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2997 emitcode ("cjne", "a,%s,%05d$"
2998 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3001 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3005 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3006 IS_AOP_PREG (IC_RESULT (ic)))
3007 emitcode ("cjne", "%s,#0x00,%05d$"
3008 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3012 emitcode ("cjne", "a,%s,%05d$"
3013 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3016 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3021 emitcode ("", "%05d$:", tlbl->key + 100);
3026 /* if the sizes are greater than 1 then we cannot */
3027 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3028 AOP_SIZE (IC_LEFT (ic)) > 1)
3031 /* we can if the aops of the left & result match or
3032 if they are in registers and the registers are the
3035 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3036 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3037 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3042 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3043 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3044 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3049 _startLazyDPSEvaluation ();
3052 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3054 _endLazyDPSEvaluation ();
3063 /*-----------------------------------------------------------------*/
3064 /* outBitAcc - output a bit in acc */
3065 /*-----------------------------------------------------------------*/
3067 outBitAcc (operand * result)
3069 symbol *tlbl = newiTempLabel (NULL);
3070 /* if the result is a bit */
3071 if (AOP_TYPE (result) == AOP_CRY)
3073 aopPut (AOP (result), "a", 0);
3077 emitcode ("jz", "%05d$", tlbl->key + 100);
3078 emitcode ("mov", "a,%s", one);
3079 emitcode ("", "%05d$:", tlbl->key + 100);
3084 /*-----------------------------------------------------------------*/
3085 /* genPlusBits - generates code for addition of two bits */
3086 /*-----------------------------------------------------------------*/
3088 genPlusBits (iCode * ic)
3090 D (emitcode (";", "genPlusBits ");
3092 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3094 symbol *lbl = newiTempLabel (NULL);
3095 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3096 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3097 emitcode ("cpl", "c");
3098 emitcode ("", "%05d$:", (lbl->key + 100));
3099 outBitC (IC_RESULT (ic));
3103 emitcode ("clr", "a");
3104 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3105 emitcode ("rlc", "a");
3106 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3107 emitcode ("addc", "a,#0x00");
3108 outAcc (IC_RESULT (ic));
3113 adjustArithmeticResult (iCode * ic)
3115 if (opIsGptr (IC_RESULT (ic)) &&
3116 opIsGptr (IC_LEFT (ic)) &&
3117 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3119 aopPut (AOP (IC_RESULT (ic)),
3120 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3124 if (opIsGptr (IC_RESULT (ic)) &&
3125 opIsGptr (IC_RIGHT (ic)) &&
3126 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3128 aopPut (AOP (IC_RESULT (ic)),
3129 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3133 if (opIsGptr (IC_RESULT (ic)) &&
3134 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3135 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3137 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3140 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3141 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3145 #define AOP_OP_3(ic) \
3146 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3147 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3148 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3149 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3150 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3151 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3153 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3155 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3158 #define AOP_OP_3_NOFATAL(ic, rc) \
3159 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3160 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3161 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3162 isOperandInFarSpace(IC_RESULT(ic))) \
3164 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3169 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3170 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3172 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3173 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3175 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3177 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3181 #define AOP_OP_2(ic) \
3182 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3183 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3185 #define AOP_SET_LOCALS(ic) \
3186 left = IC_LEFT(ic); \
3187 right = IC_RIGHT(ic); \
3188 result = IC_RESULT(ic);
3190 /*-----------------------------------------------------------------*/
3191 /* genPlus - generates code for addition */
3192 /*-----------------------------------------------------------------*/
3194 genPlus (iCode * ic)
3196 int size, offset = 0;
3197 bool pushResult = FALSE;
3200 D (emitcode (";", "genPlus ");
3203 /* special cases :- */
3205 AOP_OP_3_NOFATAL (ic, pushResult);
3208 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3214 /* if literal, literal on the right or
3215 if left requires ACC or right is already
3217 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3218 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3219 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3221 operand *t = IC_RIGHT (ic);
3222 IC_RIGHT (ic) = IC_LEFT (ic);
3224 emitcode (";", "Swapped plus args.");
3227 /* if both left & right are in bit
3229 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3230 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3236 /* if left in bit space & right literal */
3237 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3238 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3240 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3241 /* if result in bit space */
3242 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3244 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3245 emitcode ("cpl", "c");
3246 outBitC (IC_RESULT (ic));
3250 size = getDataSize (IC_RESULT (ic));
3251 _startLazyDPSEvaluation ();
3254 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3255 emitcode ("addc", "a,#00");
3256 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3258 _endLazyDPSEvaluation ();
3263 /* if I can do an increment instead
3264 of add then GOOD for ME */
3265 if (genPlusIncr (ic) == TRUE)
3267 emitcode (";", "did genPlusIncr");
3272 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3274 _startLazyDPSEvaluation ();
3277 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3279 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3281 emitcode ("add", "a,%s",
3282 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3284 emitcode ("addc", "a,%s",
3285 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3289 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3291 emitcode ("add", "a,%s",
3292 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3294 emitcode ("addc", "a,%s",
3295 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3299 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3303 emitcode ("push", "acc");
3307 _endLazyDPSEvaluation ();
3311 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3313 size = getDataSize (IC_LEFT (ic));
3314 rSize = getDataSize (IC_RESULT (ic));
3316 /* If the pushed data is bigger than the result,
3317 * simply discard unused bytes. Icky, but works.
3319 * Should we throw a warning here? We're losing data...
3321 while (size > rSize)
3323 D (emitcode (";", "discarding unused result byte.");
3325 emitcode ("pop", "acc");
3331 emitcode ("clr", "a");
3332 /* Conversly, we haven't pushed enough here.
3333 * just zero-pad, and all is well.
3335 while (size < rSize)
3337 emitcode ("push", "acc");
3343 _startLazyDPSEvaluation ();
3346 emitcode ("pop", "acc");
3347 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3349 _endLazyDPSEvaluation ();
3352 adjustArithmeticResult (ic);
3355 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3356 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3357 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3360 /*-----------------------------------------------------------------*/
3361 /* genMinusDec :- does subtraction with deccrement if possible */
3362 /*-----------------------------------------------------------------*/
3364 genMinusDec (iCode * ic)
3366 unsigned int icount;
3367 unsigned int size = getDataSize (IC_RESULT (ic));
3369 /* will try to generate an increment */
3370 /* if the right side is not a literal
3372 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3375 /* if the literal value of the right hand side
3376 is greater than 4 then it is not worth it */
3377 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3380 /* if decrement 16 bits in register */
3381 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3382 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3383 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3391 /* If the next instruction is a goto and the goto target
3392 * is <= 5 instructions previous to this, we can generate
3393 * jumps straight to that target.
3395 if (ic->next && ic->next->op == GOTO
3396 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3399 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3400 tlbl = IC_LABEL (ic->next);
3405 tlbl = newiTempLabel (NULL);
3409 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3410 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3412 IS_AOP_PREG (IC_RESULT (ic)))
3413 emitcode ("cjne", "%s,#0xff,%05d$"
3414 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3418 emitcode ("mov", "a,#0xff");
3419 emitcode ("cjne", "a,%s,%05d$"
3420 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3423 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3426 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3427 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3428 IS_AOP_PREG (IC_RESULT (ic)))
3429 emitcode ("cjne", "%s,#0xff,%05d$"
3430 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3434 emitcode ("cjne", "a,%s,%05d$"
3435 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3438 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3443 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3444 IS_AOP_PREG (IC_RESULT (ic)))
3445 emitcode ("cjne", "%s,#0xff,%05d$"
3446 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3450 emitcode ("cjne", "a,%s,%05d$"
3451 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3454 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3458 emitcode ("", "%05d$:", tlbl->key + 100);
3463 /* if the sizes are greater than 1 then we cannot */
3464 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3465 AOP_SIZE (IC_LEFT (ic)) > 1)
3468 /* we can if the aops of the left & result match or
3469 if they are in registers and the registers are the
3472 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3473 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3474 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3477 _startLazyDPSEvaluation ();
3480 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3482 _endLazyDPSEvaluation ();
3490 /*-----------------------------------------------------------------*/
3491 /* addSign - complete with sign */
3492 /*-----------------------------------------------------------------*/
3494 addSign (operand * result, int offset, int sign)
3496 int size = (getDataSize (result) - offset);
3501 emitcode ("rlc", "a");
3502 emitcode ("subb", "a,acc");
3504 aopPut (AOP (result), "a", offset++);
3508 aopPut (AOP (result), zero, offset++);
3512 /*-----------------------------------------------------------------*/
3513 /* genMinusBits - generates code for subtraction of two bits */
3514 /*-----------------------------------------------------------------*/
3516 genMinusBits (iCode * ic)
3518 symbol *lbl = newiTempLabel (NULL);
3520 D (emitcode (";", "genMinusBits ");
3523 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3525 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3526 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3527 emitcode ("cpl", "c");
3528 emitcode ("", "%05d$:", (lbl->key + 100));
3529 outBitC (IC_RESULT (ic));
3533 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3534 emitcode ("subb", "a,acc");
3535 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3536 emitcode ("inc", "a");
3537 emitcode ("", "%05d$:", (lbl->key + 100));
3538 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3539 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3543 /*-----------------------------------------------------------------*/
3544 /* genMinus - generates code for subtraction */
3545 /*-----------------------------------------------------------------*/
3547 genMinus (iCode * ic)
3549 int size, offset = 0;
3551 unsigned long lit = 0L;
3552 bool pushResult = FALSE;
3554 D (emitcode (";", "genMinus ");
3557 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3558 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3559 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3560 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3566 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3568 /* special cases :- */
3569 /* if both left & right are in bit space */
3570 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3571 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3577 /* if I can do an decrement instead
3578 of subtract then GOOD for ME */
3579 if (genMinusDec (ic) == TRUE)
3584 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3586 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3592 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3597 /* if literal, add a,#-lit, else normal subb */
3598 _startLazyDPSEvaluation ();
3601 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3602 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3603 emitcode ("subb", "a,%s",
3604 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3607 /* first add without previous c */
3609 emitcode ("add", "a,#0x%02x",
3610 (unsigned int) (lit & 0x0FFL));
3612 emitcode ("addc", "a,#0x%02x",
3613 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3618 emitcode ("push", "acc");
3622 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3626 _endLazyDPSEvaluation ();
3630 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3632 size = getDataSize (IC_LEFT (ic));
3633 rSize = getDataSize (IC_RESULT (ic));
3635 /* If the pushed data is bigger than the result,
3636 * simply discard unused bytes. Icky, but works.
3638 * Should we throw a warning here? We're losing data...
3640 while (size > getDataSize (IC_RESULT (ic)))
3642 emitcode (";", "discarding unused result byte.");
3643 emitcode ("pop", "acc");
3649 emitcode ("clr", "a");
3650 /* Conversly, we haven't pushed enough here.
3651 * just zero-pad, and all is well.
3653 while (size < rSize)
3655 emitcode ("push", "acc");
3663 emitcode ("pop", "acc");
3664 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3668 adjustArithmeticResult (ic);
3671 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3672 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3673 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3677 /*-----------------------------------------------------------------*/
3678 /* genMultbits :- multiplication of bits */
3679 /*-----------------------------------------------------------------*/
3681 genMultbits (operand * left,
3685 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3686 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3691 /*-----------------------------------------------------------------*/
3692 /* genMultOneByte : 8 bit multiplication & division */
3693 /*-----------------------------------------------------------------*/
3695 genMultOneByte (operand * left,
3699 sym_link *opetype = operandType (result);
3704 /* (if two literals, the value is computed before) */
3705 /* if one literal, literal on the right */
3706 if (AOP_TYPE (left) == AOP_LIT)
3713 size = AOP_SIZE (result);
3714 /* signed or unsigned */
3715 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3716 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3718 emitcode ("mul", "ab");
3719 /* if result size = 1, mul signed = mul unsigned */
3720 aopPut (AOP (result), "a", 0);
3723 if (SPEC_USIGN (opetype))
3725 aopPut (AOP (result), "b", 1);
3727 /* for filling the MSBs */
3728 emitcode ("clr", "a");
3732 emitcode ("mov", "a,b");
3734 /* adjust the MSB if left or right neg */
3736 /* if one literal */
3737 if (AOP_TYPE (right) == AOP_LIT)
3739 /* AND literal negative */
3740 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3742 /* adjust MSB (c==0 after mul) */
3743 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3748 lbl = newiTempLabel (NULL);
3749 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3750 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3751 emitcode ("", "%05d$:", (lbl->key + 100));
3752 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3753 lbl = newiTempLabel (NULL);
3754 emitcode ("jc", "%05d$", (lbl->key + 100));
3755 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3756 emitcode ("", "%05d$:", (lbl->key + 100));
3759 lbl = newiTempLabel (NULL);
3760 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3761 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3762 emitcode ("", "%05d$:", (lbl->key + 100));
3763 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3764 lbl = newiTempLabel (NULL);
3765 emitcode ("jc", "%05d$", (lbl->key + 100));
3766 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3767 emitcode ("", "%05d$:", (lbl->key + 100));
3769 aopPut (AOP (result), "a", 1);
3773 emitcode ("rlc", "a");
3774 emitcode ("subb", "a,acc");
3781 aopPut (AOP (result), "a", offset++);
3785 /*-----------------------------------------------------------------*/
3786 /* genMult - generates code for multiplication */
3787 /*-----------------------------------------------------------------*/
3789 genMult (iCode * ic)
3791 operand *left = IC_LEFT (ic);
3792 operand *right = IC_RIGHT (ic);
3793 operand *result = IC_RESULT (ic);
3795 D (emitcode (";", "genMult ");
3798 /* assign the amsops */
3801 /* special cases first */
3803 if (AOP_TYPE (left) == AOP_CRY &&
3804 AOP_TYPE (right) == AOP_CRY)
3806 genMultbits (left, right, result);
3810 /* if both are of size == 1 */
3811 if (AOP_SIZE (left) == 1 &&
3812 AOP_SIZE (right) == 1)
3814 genMultOneByte (left, right, result);
3818 /* should have been converted to function call */
3822 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3823 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3824 freeAsmop (result, NULL, ic, TRUE);
3827 /*-----------------------------------------------------------------*/
3828 /* genDivbits :- division of bits */
3829 /*-----------------------------------------------------------------*/
3831 genDivbits (operand * left,
3838 /* the result must be bit */
3839 LOAD_AB_FOR_DIV (left, right, l);
3840 emitcode ("div", "ab");
3841 emitcode ("rrc", "a");
3842 aopPut (AOP (result), "c", 0);
3845 /*-----------------------------------------------------------------*/
3846 /* genDivOneByte : 8 bit division */
3847 /*-----------------------------------------------------------------*/
3849 genDivOneByte (operand * left,
3853 sym_link *opetype = operandType (result);
3858 size = AOP_SIZE (result) - 1;
3860 /* signed or unsigned */
3861 if (SPEC_USIGN (opetype))
3863 /* unsigned is easy */
3864 LOAD_AB_FOR_DIV (left, right, l);
3865 emitcode ("div", "ab");
3866 aopPut (AOP (result), "a", 0);
3868 aopPut (AOP (result), zero, offset++);
3872 /* signed is a little bit more difficult */
3874 /* save the signs of the operands */
3875 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3877 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3878 emitcode ("push", "acc"); /* save it on the stack */
3880 /* now sign adjust for both left & right */
3881 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3883 lbl = newiTempLabel (NULL);
3884 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3885 emitcode ("cpl", "a");
3886 emitcode ("inc", "a");
3887 emitcode ("", "%05d$:", (lbl->key + 100));
3888 emitcode ("mov", "b,a");
3890 /* sign adjust left side */
3891 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3894 lbl = newiTempLabel (NULL);
3895 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3896 emitcode ("cpl", "a");
3897 emitcode ("inc", "a");
3898 emitcode ("", "%05d$:", (lbl->key + 100));
3900 /* now the division */
3901 emitcode ("nop", "; workaround for DS80C390 div bug.");
3902 emitcode ("div", "ab");
3903 /* we are interested in the lower order
3905 emitcode ("mov", "b,a");
3906 lbl = newiTempLabel (NULL);
3907 emitcode ("pop", "acc");
3908 /* if there was an over flow we don't
3909 adjust the sign of the result */
3910 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3911 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3913 emitcode ("clr", "a");
3914 emitcode ("subb", "a,b");
3915 emitcode ("mov", "b,a");
3916 emitcode ("", "%05d$:", (lbl->key + 100));
3918 /* now we are done */
3919 aopPut (AOP (result), "b", 0);
3922 emitcode ("mov", "c,b.7");
3923 emitcode ("subb", "a,acc");
3926 aopPut (AOP (result), "a", offset++);
3930 /*-----------------------------------------------------------------*/
3931 /* genDiv - generates code for division */
3932 /*-----------------------------------------------------------------*/
3936 operand *left = IC_LEFT (ic);
3937 operand *right = IC_RIGHT (ic);
3938 operand *result = IC_RESULT (ic);
3940 D (emitcode (";", "genDiv ");
3943 /* assign the amsops */
3946 /* special cases first */
3948 if (AOP_TYPE (left) == AOP_CRY &&
3949 AOP_TYPE (right) == AOP_CRY)
3951 genDivbits (left, right, result);
3955 /* if both are of size == 1 */
3956 if (AOP_SIZE (left) == 1 &&
3957 AOP_SIZE (right) == 1)
3959 genDivOneByte (left, right, result);
3963 /* should have been converted to function call */
3966 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3967 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3968 freeAsmop (result, NULL, ic, TRUE);
3971 /*-----------------------------------------------------------------*/
3972 /* genModbits :- modulus of bits */
3973 /*-----------------------------------------------------------------*/
3975 genModbits (operand * left,
3982 /* the result must be bit */
3983 LOAD_AB_FOR_DIV (left, right, l);
3984 emitcode ("div", "ab");
3985 emitcode ("mov", "a,b");
3986 emitcode ("rrc", "a");
3987 aopPut (AOP (result), "c", 0);
3990 /*-----------------------------------------------------------------*/
3991 /* genModOneByte : 8 bit modulus */
3992 /*-----------------------------------------------------------------*/
3994 genModOneByte (operand * left,
3998 sym_link *opetype = operandType (result);
4002 /* signed or unsigned */
4003 if (SPEC_USIGN (opetype))
4005 /* unsigned is easy */
4006 LOAD_AB_FOR_DIV (left, right, l);
4007 emitcode ("div", "ab");
4008 aopPut (AOP (result), "b", 0);
4012 /* signed is a little bit more difficult */
4014 /* save the signs of the operands */
4015 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4018 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4019 emitcode ("push", "acc"); /* save it on the stack */
4021 /* now sign adjust for both left & right */
4022 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4025 lbl = newiTempLabel (NULL);
4026 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4027 emitcode ("cpl", "a");
4028 emitcode ("inc", "a");
4029 emitcode ("", "%05d$:", (lbl->key + 100));
4030 emitcode ("mov", "b,a");
4032 /* sign adjust left side */
4033 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4036 lbl = newiTempLabel (NULL);
4037 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4038 emitcode ("cpl", "a");
4039 emitcode ("inc", "a");
4040 emitcode ("", "%05d$:", (lbl->key + 100));
4042 /* now the multiplication */
4043 emitcode ("nop", "; workaround for DS80C390 div bug.");
4044 emitcode ("div", "ab");
4045 /* we are interested in the lower order
4047 lbl = newiTempLabel (NULL);
4048 emitcode ("pop", "acc");
4049 /* if there was an over flow we don't
4050 adjust the sign of the result */
4051 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4052 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4054 emitcode ("clr", "a");
4055 emitcode ("subb", "a,b");
4056 emitcode ("mov", "b,a");
4057 emitcode ("", "%05d$:", (lbl->key + 100));
4059 /* now we are done */
4060 aopPut (AOP (result), "b", 0);
4064 /*-----------------------------------------------------------------*/
4065 /* genMod - generates code for division */
4066 /*-----------------------------------------------------------------*/
4070 operand *left = IC_LEFT (ic);
4071 operand *right = IC_RIGHT (ic);
4072 operand *result = IC_RESULT (ic);
4074 D (emitcode (";", "genMod ");
4077 /* assign the amsops */
4080 /* special cases first */
4082 if (AOP_TYPE (left) == AOP_CRY &&
4083 AOP_TYPE (right) == AOP_CRY)
4085 genModbits (left, right, result);
4089 /* if both are of size == 1 */
4090 if (AOP_SIZE (left) == 1 &&
4091 AOP_SIZE (right) == 1)
4093 genModOneByte (left, right, result);
4097 /* should have been converted to function call */
4101 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4103 freeAsmop (result, NULL, ic, TRUE);
4106 /*-----------------------------------------------------------------*/
4107 /* genIfxJump :- will create a jump depending on the ifx */
4108 /*-----------------------------------------------------------------*/
4110 genIfxJump (iCode * ic, char *jval)
4113 symbol *tlbl = newiTempLabel (NULL);
4116 D (emitcode (";", "genIfxJump ");
4119 /* if true label then we jump if condition
4123 jlbl = IC_TRUE (ic);
4124 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4125 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4129 /* false label is present */
4130 jlbl = IC_FALSE (ic);
4131 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4132 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4134 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4135 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4137 emitcode (inst, "%05d$", tlbl->key + 100);
4138 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4139 emitcode ("", "%05d$:", tlbl->key + 100);
4141 /* mark the icode as generated */
4145 /*-----------------------------------------------------------------*/
4146 /* genCmp :- greater or less than comparison */
4147 /*-----------------------------------------------------------------*/
4149 genCmp (operand * left, operand * right,
4150 iCode * ic, iCode * ifx, int sign)
4152 int size, offset = 0;
4153 unsigned long lit = 0L;
4156 D (emitcode (";", "genCmp");
4159 result = IC_RESULT (ic);
4161 /* if left & right are bit variables */
4162 if (AOP_TYPE (left) == AOP_CRY &&
4163 AOP_TYPE (right) == AOP_CRY)
4165 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4166 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4170 /* subtract right from left if at the
4171 end the carry flag is set then we know that
4172 left is greater than right */
4173 size = max (AOP_SIZE (left), AOP_SIZE (right));
4175 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4176 if ((size == 1) && !sign &&
4177 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4179 symbol *lbl = newiTempLabel (NULL);
4180 emitcode ("cjne", "%s,%s,%05d$",
4181 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4182 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4184 emitcode ("", "%05d$:", lbl->key + 100);
4188 if (AOP_TYPE (right) == AOP_LIT)
4190 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4191 /* optimize if(x < 0) or if(x >= 0) */
4200 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4202 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4203 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4205 aopOp (result, ic, FALSE, FALSE);
4207 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4209 freeAsmop (result, NULL, ic, TRUE);
4210 genIfxJump (ifx, "acc.7");
4215 emitcode ("rlc", "a");
4217 goto release_freedLR;
4225 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4226 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4227 emitcode (";", "genCmp #2");
4228 if (sign && (size == 0))
4230 emitcode (";", "genCmp #3");
4231 emitcode ("xrl", "a,#0x80");
4232 if (AOP_TYPE (right) == AOP_LIT)
4234 unsigned long lit = (unsigned long)
4235 floatFromVal (AOP (right)->aopu.aop_lit);
4236 emitcode (";", "genCmp #3.1");
4237 emitcode ("subb", "a,#0x%02x",
4238 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4242 emitcode (";", "genCmp #3.2");
4243 if (AOP_NEEDSACC (right))
4245 emitcode ("push", "acc");
4247 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4248 FALSE, FALSE, FALSE));
4249 emitcode ("xrl", "b,#0x80");
4250 if (AOP_NEEDSACC (right))
4252 emitcode ("pop", "acc");
4254 emitcode ("subb", "a,b");
4261 emitcode (";", "genCmp #4");
4262 if (AOP_NEEDSACC (right))
4265 emitcode (";", "genCmp #4.1");
4266 emitcode ("xch", "a, b");
4267 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4268 emitcode ("xch", "a, b");
4273 emitcode (";", "genCmp #4.2");
4274 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4277 emitcode ("subb", "a,%s", s);
4284 /* Don't need the left & right operands any more; do need the result. */
4285 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4286 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4288 aopOp (result, ic, FALSE, FALSE);
4292 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4298 /* if the result is used in the next
4299 ifx conditional branch then generate
4300 code a little differently */
4303 genIfxJump (ifx, "c");
4309 /* leave the result in acc */
4311 freeAsmop (result, NULL, ic, TRUE);
4314 /*-----------------------------------------------------------------*/
4315 /* genCmpGt :- greater than comparison */
4316 /*-----------------------------------------------------------------*/
4318 genCmpGt (iCode * ic, iCode * ifx)
4320 operand *left, *right;
4321 sym_link *letype, *retype;
4324 D (emitcode (";", "genCmpGt ");
4327 left = IC_LEFT (ic);
4328 right = IC_RIGHT (ic);
4330 letype = getSpec (operandType (left));
4331 retype = getSpec (operandType (right));
4332 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4334 /* assign the left & right amsops */
4337 genCmp (right, left, ic, ifx, sign);
4340 /*-----------------------------------------------------------------*/
4341 /* genCmpLt - less than comparisons */
4342 /*-----------------------------------------------------------------*/
4344 genCmpLt (iCode * ic, iCode * ifx)
4346 operand *left, *right;
4347 sym_link *letype, *retype;
4350 D (emitcode (";", "genCmpLt ");
4353 left = IC_LEFT (ic);
4354 right = IC_RIGHT (ic);
4356 letype = getSpec (operandType (left));
4357 retype = getSpec (operandType (right));
4358 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4360 /* assign the left & right amsops */
4363 genCmp (left, right, ic, ifx, sign);
4366 /*-----------------------------------------------------------------*/
4367 /* gencjneshort - compare and jump if not equal */
4368 /*-----------------------------------------------------------------*/
4370 gencjneshort (operand * left, operand * right, symbol * lbl)
4372 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4374 unsigned long lit = 0L;
4376 D (emitcode (";", "gencjneshort");
4379 /* if the left side is a literal or
4380 if the right is in a pointer register and left
4382 if ((AOP_TYPE (left) == AOP_LIT) ||
4383 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4390 if (AOP_TYPE (right) == AOP_LIT)
4391 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4393 if (opIsGptr (left) || opIsGptr (right))
4395 /* We are comparing a generic pointer to something.
4396 * Exclude the generic type byte from the comparison.
4399 D (emitcode (";", "cjneshort: generic ptr special case.");
4404 /* if the right side is a literal then anything goes */
4405 if (AOP_TYPE (right) == AOP_LIT &&
4406 AOP_TYPE (left) != AOP_DIR)
4410 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4412 emitcode ("cjne", "a,%s,%05d$",
4413 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4419 /* if the right side is in a register or in direct space or
4420 if the left is a pointer register & right is not */
4421 else if (AOP_TYPE (right) == AOP_REG ||
4422 AOP_TYPE (right) == AOP_DIR ||
4423 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4424 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4428 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4429 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4430 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4431 emitcode ("jnz", "%05d$", lbl->key + 100);
4433 emitcode ("cjne", "a,%s,%05d$",
4434 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4441 /* right is a pointer reg need both a & b */
4444 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4445 if (strcmp (l, "b"))
4446 emitcode ("mov", "b,%s", l);
4447 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4448 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4454 /*-----------------------------------------------------------------*/
4455 /* gencjne - compare and jump if not equal */
4456 /*-----------------------------------------------------------------*/
4458 gencjne (operand * left, operand * right, symbol * lbl)
4460 symbol *tlbl = newiTempLabel (NULL);
4462 D (emitcode (";", "gencjne");
4465 gencjneshort (left, right, lbl);
4467 emitcode ("mov", "a,%s", one);
4468 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4469 emitcode ("", "%05d$:", lbl->key + 100);
4470 emitcode ("clr", "a");
4471 emitcode ("", "%05d$:", tlbl->key + 100);
4474 /*-----------------------------------------------------------------*/
4475 /* genCmpEq - generates code for equal to */
4476 /*-----------------------------------------------------------------*/
4478 genCmpEq (iCode * ic, iCode * ifx)
4480 operand *left, *right, *result;
4482 D (emitcode (";", "genCmpEq ");
4486 AOP_SET_LOCALS (ic);
4488 /* if literal, literal on the right or
4489 if the right is in a pointer register and left
4491 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4492 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4494 operand *t = IC_RIGHT (ic);
4495 IC_RIGHT (ic) = IC_LEFT (ic);
4499 if (ifx && /* !AOP_SIZE(result) */
4500 OP_SYMBOL (result) &&
4501 OP_SYMBOL (result)->regType == REG_CND)
4504 /* if they are both bit variables */
4505 if (AOP_TYPE (left) == AOP_CRY &&
4506 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4508 if (AOP_TYPE (right) == AOP_LIT)
4510 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4513 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4514 emitcode ("cpl", "c");
4518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4522 emitcode ("clr", "c");
4524 /* AOP_TYPE(right) == AOP_CRY */
4528 symbol *lbl = newiTempLabel (NULL);
4529 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4530 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4531 emitcode ("cpl", "c");
4532 emitcode ("", "%05d$:", (lbl->key + 100));
4534 /* if true label then we jump if condition
4536 tlbl = newiTempLabel (NULL);
4539 emitcode ("jnc", "%05d$", tlbl->key + 100);
4540 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4544 emitcode ("jc", "%05d$", tlbl->key + 100);
4545 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4547 emitcode ("", "%05d$:", tlbl->key + 100);
4551 tlbl = newiTempLabel (NULL);
4552 gencjneshort (left, right, tlbl);
4555 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4556 emitcode ("", "%05d$:", tlbl->key + 100);
4560 symbol *lbl = newiTempLabel (NULL);
4561 emitcode ("sjmp", "%05d$", lbl->key + 100);
4562 emitcode ("", "%05d$:", tlbl->key + 100);
4563 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4564 emitcode ("", "%05d$:", lbl->key + 100);
4567 /* mark the icode as generated */
4570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4575 /* if they are both bit variables */
4576 if (AOP_TYPE (left) == AOP_CRY &&
4577 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4579 if (AOP_TYPE (right) == AOP_LIT)
4581 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4584 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4585 emitcode ("cpl", "c");
4589 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4593 emitcode ("clr", "c");
4595 /* AOP_TYPE(right) == AOP_CRY */
4599 symbol *lbl = newiTempLabel (NULL);
4600 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4601 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4602 emitcode ("cpl", "c");
4603 emitcode ("", "%05d$:", (lbl->key + 100));
4606 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4607 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4609 aopOp (result, ic, TRUE, FALSE);
4612 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4619 genIfxJump (ifx, "c");
4622 /* if the result is used in an arithmetic operation
4623 then put the result in place */
4628 gencjne (left, right, newiTempLabel (NULL));
4630 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4631 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4633 aopOp (result, ic, TRUE, FALSE);
4635 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4637 aopPut (AOP (result), "a", 0);
4642 genIfxJump (ifx, "a");
4645 /* if the result is used in an arithmetic operation
4646 then put the result in place */
4647 if (AOP_TYPE (result) != AOP_CRY)
4649 /* leave the result in acc */
4653 freeAsmop (result, NULL, ic, TRUE);
4656 /*-----------------------------------------------------------------*/
4657 /* ifxForOp - returns the icode containing the ifx for operand */
4658 /*-----------------------------------------------------------------*/
4660 ifxForOp (operand * op, iCode * ic)
4662 /* if true symbol then needs to be assigned */
4663 if (IS_TRUE_SYMOP (op))
4666 /* if this has register type condition and
4667 the next instruction is ifx with the same operand
4668 and live to of the operand is upto the ifx only then */
4670 ic->next->op == IFX &&
4671 IC_COND (ic->next)->key == op->key &&
4672 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4677 /*-----------------------------------------------------------------*/
4678 /* genAndOp - for && operation */
4679 /*-----------------------------------------------------------------*/
4681 genAndOp (iCode * ic)
4683 operand *left, *right, *result;
4686 D (emitcode (";", "genAndOp ");
4689 /* note here that && operations that are in an
4690 if statement are taken away by backPatchLabels
4691 only those used in arthmetic operations remain */
4693 AOP_SET_LOCALS (ic);
4695 /* if both are bit variables */
4696 if (AOP_TYPE (left) == AOP_CRY &&
4697 AOP_TYPE (right) == AOP_CRY)
4699 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4700 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4705 tlbl = newiTempLabel (NULL);
4707 emitcode ("jz", "%05d$", tlbl->key + 100);
4709 emitcode ("", "%05d$:", tlbl->key + 100);
4713 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4715 freeAsmop (result, NULL, ic, TRUE);
4719 /*-----------------------------------------------------------------*/
4720 /* genOrOp - for || operation */
4721 /*-----------------------------------------------------------------*/
4723 genOrOp (iCode * ic)
4725 operand *left, *right, *result;
4728 D (emitcode (";", "genOrOp ");
4731 /* note here that || operations that are in an
4732 if statement are taken away by backPatchLabels
4733 only those used in arthmetic operations remain */
4735 AOP_SET_LOCALS (ic);
4737 /* if both are bit variables */
4738 if (AOP_TYPE (left) == AOP_CRY &&
4739 AOP_TYPE (right) == AOP_CRY)
4741 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4742 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4747 tlbl = newiTempLabel (NULL);
4749 emitcode ("jnz", "%05d$", tlbl->key + 100);
4751 emitcode ("", "%05d$:", tlbl->key + 100);
4755 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4757 freeAsmop (result, NULL, ic, TRUE);
4760 /*-----------------------------------------------------------------*/
4761 /* isLiteralBit - test if lit == 2^n */
4762 /*-----------------------------------------------------------------*/
4764 isLiteralBit (unsigned long lit)
4766 unsigned long pw[32] =
4767 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4768 0x100L, 0x200L, 0x400L, 0x800L,
4769 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4770 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4771 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4772 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4773 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4776 for (idx = 0; idx < 32; idx++)
4782 /*-----------------------------------------------------------------*/
4783 /* continueIfTrue - */
4784 /*-----------------------------------------------------------------*/
4786 continueIfTrue (iCode * ic)
4789 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4793 /*-----------------------------------------------------------------*/
4795 /*-----------------------------------------------------------------*/
4797 jumpIfTrue (iCode * ic)
4800 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4804 /*-----------------------------------------------------------------*/
4805 /* jmpTrueOrFalse - */
4806 /*-----------------------------------------------------------------*/
4808 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4810 // ugly but optimized by peephole
4813 symbol *nlbl = newiTempLabel (NULL);
4814 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4815 emitcode ("", "%05d$:", tlbl->key + 100);
4816 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4817 emitcode ("", "%05d$:", nlbl->key + 100);
4821 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4822 emitcode ("", "%05d$:", tlbl->key + 100);
4827 /*-----------------------------------------------------------------*/
4828 /* genAnd - code for and */
4829 /*-----------------------------------------------------------------*/
4831 genAnd (iCode * ic, iCode * ifx)
4833 operand *left, *right, *result;
4834 int size, offset = 0;
4835 unsigned long lit = 0L;
4839 D (emitcode (";", "genAnd ");
4843 AOP_SET_LOCALS (ic);
4846 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4848 AOP_TYPE (left), AOP_TYPE (right));
4849 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4851 AOP_SIZE (left), AOP_SIZE (right));
4854 /* if left is a literal & right is not then exchange them */
4855 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4856 AOP_NEEDSACC (left))
4858 operand *tmp = right;
4863 /* if result = right then exchange them */
4864 if (sameRegs (AOP (result), AOP (right)))
4866 operand *tmp = right;
4871 /* if right is bit then exchange them */
4872 if (AOP_TYPE (right) == AOP_CRY &&
4873 AOP_TYPE (left) != AOP_CRY)
4875 operand *tmp = right;
4879 if (AOP_TYPE (right) == AOP_LIT)
4880 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4882 size = AOP_SIZE (result);
4885 // result = bit & yy;
4886 if (AOP_TYPE (left) == AOP_CRY)
4888 // c = bit & literal;
4889 if (AOP_TYPE (right) == AOP_LIT)
4893 if (size && sameRegs (AOP (result), AOP (left)))
4896 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4901 if (size && (AOP_TYPE (result) == AOP_CRY))
4903 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4906 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4911 emitcode ("clr", "c");
4916 if (AOP_TYPE (right) == AOP_CRY)
4919 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4920 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4925 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4927 emitcode ("rrc", "a");
4928 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4936 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4937 genIfxJump (ifx, "c");
4941 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4942 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4943 if ((AOP_TYPE (right) == AOP_LIT) &&
4944 (AOP_TYPE (result) == AOP_CRY) &&
4945 (AOP_TYPE (left) != AOP_CRY))
4947 int posbit = isLiteralBit (lit);
4952 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4955 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4961 sprintf (buffer, "acc.%d", posbit & 0x07);
4962 genIfxJump (ifx, buffer);
4969 symbol *tlbl = newiTempLabel (NULL);
4970 int sizel = AOP_SIZE (left);
4972 emitcode ("setb", "c");
4975 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4977 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4979 if ((posbit = isLiteralBit (bytelit)) != 0)
4980 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4983 if (bytelit != 0x0FFL)
4984 emitcode ("anl", "a,%s",
4985 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4986 emitcode ("jnz", "%05d$", tlbl->key + 100);
4991 // bit = left & literal
4994 emitcode ("clr", "c");
4995 emitcode ("", "%05d$:", tlbl->key + 100);
4997 // if(left & literal)
5001 jmpTrueOrFalse (ifx, tlbl);
5009 /* if left is same as result */
5010 if (sameRegs (AOP (result), AOP (left)))
5012 for (; size--; offset++)
5014 if (AOP_TYPE (right) == AOP_LIT)
5016 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5018 else if (bytelit == 0)
5019 aopPut (AOP (result), zero, offset);
5020 else if (IS_AOP_PREG (result))
5022 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5023 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5024 aopPut (AOP (result), "a", offset);
5027 emitcode ("anl", "%s,%s",
5028 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5029 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5033 if (AOP_TYPE (left) == AOP_ACC)
5034 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5037 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5038 if (IS_AOP_PREG (result))
5040 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5041 aopPut (AOP (result), "a", offset);
5045 emitcode ("anl", "%s,a",
5046 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5053 // left & result in different registers
5054 if (AOP_TYPE (result) == AOP_CRY)
5057 // if(size), result in bit
5058 // if(!size && ifx), conditional oper: if(left & right)
5059 symbol *tlbl = newiTempLabel (NULL);
5060 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5062 emitcode ("setb", "c");
5065 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5066 emitcode ("anl", "a,%s",
5067 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5068 emitcode ("jnz", "%05d$", tlbl->key + 100);
5074 emitcode ("", "%05d$:", tlbl->key + 100);
5078 jmpTrueOrFalse (ifx, tlbl);
5082 for (; (size--); offset++)
5085 // result = left & right
5086 if (AOP_TYPE (right) == AOP_LIT)
5088 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5090 aopPut (AOP (result),
5091 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5095 else if (bytelit == 0)
5097 aopPut (AOP (result), zero, offset);
5100 D (emitcode (";", "better literal AND.");
5102 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5103 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5104 FALSE, FALSE, FALSE));
5109 // faster than result <- left, anl result,right
5110 // and better if result is SFR
5111 if (AOP_TYPE (left) == AOP_ACC)
5113 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5114 FALSE, FALSE, FALSE));
5118 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5119 emitcode ("anl", "a,%s",
5120 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5123 aopPut (AOP (result), "a", offset);
5129 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5130 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5131 freeAsmop (result, NULL, ic, TRUE);
5134 /*-----------------------------------------------------------------*/
5135 /* genOr - code for or */
5136 /*-----------------------------------------------------------------*/
5138 genOr (iCode * ic, iCode * ifx)
5140 operand *left, *right, *result;
5141 int size, offset = 0;
5142 unsigned long lit = 0L;
5144 D (emitcode (";", "genOr ");
5148 AOP_SET_LOCALS (ic);
5151 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5153 AOP_TYPE (left), AOP_TYPE (right));
5154 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5156 AOP_SIZE (left), AOP_SIZE (right));
5159 /* if left is a literal & right is not then exchange them */
5160 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5161 AOP_NEEDSACC (left))
5163 operand *tmp = right;
5168 /* if result = right then exchange them */
5169 if (sameRegs (AOP (result), AOP (right)))
5171 operand *tmp = right;
5176 /* if right is bit then exchange them */
5177 if (AOP_TYPE (right) == AOP_CRY &&
5178 AOP_TYPE (left) != AOP_CRY)
5180 operand *tmp = right;
5184 if (AOP_TYPE (right) == AOP_LIT)
5185 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5187 size = AOP_SIZE (result);
5191 if (AOP_TYPE (left) == AOP_CRY)
5193 if (AOP_TYPE (right) == AOP_LIT)
5195 // c = bit & literal;
5198 // lit != 0 => result = 1
5199 if (AOP_TYPE (result) == AOP_CRY)
5202 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5204 continueIfTrue (ifx);
5207 emitcode ("setb", "c");
5211 // lit == 0 => result = left
5212 if (size && sameRegs (AOP (result), AOP (left)))
5214 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5219 if (AOP_TYPE (right) == AOP_CRY)
5222 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5223 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5228 symbol *tlbl = newiTempLabel (NULL);
5229 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5230 emitcode ("setb", "c");
5231 emitcode ("jb", "%s,%05d$",
5232 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5234 emitcode ("jnz", "%05d$", tlbl->key + 100);
5235 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5237 jmpTrueOrFalse (ifx, tlbl);
5243 emitcode ("", "%05d$:", tlbl->key + 100);
5252 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5253 genIfxJump (ifx, "c");
5257 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5258 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5259 if ((AOP_TYPE (right) == AOP_LIT) &&
5260 (AOP_TYPE (result) == AOP_CRY) &&
5261 (AOP_TYPE (left) != AOP_CRY))
5267 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5269 continueIfTrue (ifx);
5274 // lit = 0, result = boolean(left)
5276 emitcode ("setb", "c");
5280 symbol *tlbl = newiTempLabel (NULL);
5281 emitcode ("jnz", "%05d$", tlbl->key + 100);
5283 emitcode ("", "%05d$:", tlbl->key + 100);
5287 genIfxJump (ifx, "a");
5295 /* if left is same as result */
5296 if (sameRegs (AOP (result), AOP (left)))
5298 for (; size--; offset++)
5300 if (AOP_TYPE (right) == AOP_LIT)
5302 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5308 if (IS_AOP_PREG (left))
5310 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5311 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5312 aopPut (AOP (result), "a", offset);
5316 emitcode ("orl", "%s,%s",
5317 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5318 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5324 if (AOP_TYPE (left) == AOP_ACC)
5326 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5330 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5331 if (IS_AOP_PREG (left))
5333 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5334 aopPut (AOP (result), "a", offset);
5338 emitcode ("orl", "%s,a",
5339 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5347 // left & result in different registers
5348 if (AOP_TYPE (result) == AOP_CRY)
5351 // if(size), result in bit
5352 // if(!size && ifx), conditional oper: if(left | right)
5353 symbol *tlbl = newiTempLabel (NULL);
5354 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5356 emitcode ("setb", "c");
5359 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5360 emitcode ("orl", "a,%s",
5361 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5362 emitcode ("jnz", "%05d$", tlbl->key + 100);
5368 emitcode ("", "%05d$:", tlbl->key + 100);
5372 jmpTrueOrFalse (ifx, tlbl);
5376 for (; (size--); offset++)
5379 // result = left & right
5380 if (AOP_TYPE (right) == AOP_LIT)
5382 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5384 aopPut (AOP (result),
5385 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5389 D (emitcode (";", "better literal OR.");
5391 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5392 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5393 FALSE, FALSE, FALSE));
5398 // faster than result <- left, anl result,right
5399 // and better if result is SFR
5400 if (AOP_TYPE (left) == AOP_ACC)
5402 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5403 FALSE, FALSE, FALSE));
5407 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5408 emitcode ("orl", "a,%s",
5409 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5412 aopPut (AOP (result), "a", offset);
5418 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5420 freeAsmop (result, NULL, ic, TRUE);
5423 /*-----------------------------------------------------------------*/
5424 /* genXor - code for xclusive or */
5425 /*-----------------------------------------------------------------*/
5427 genXor (iCode * ic, iCode * ifx)
5429 operand *left, *right, *result;
5430 int size, offset = 0;
5431 unsigned long lit = 0L;
5433 D (emitcode (";", "genXor ");
5437 AOP_SET_LOCALS (ic);
5440 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5442 AOP_TYPE (left), AOP_TYPE (right));
5443 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5445 AOP_SIZE (left), AOP_SIZE (right));
5448 /* if left is a literal & right is not ||
5449 if left needs acc & right does not */
5450 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5451 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5453 operand *tmp = right;
5458 /* if result = right then exchange them */
5459 if (sameRegs (AOP (result), AOP (right)))
5461 operand *tmp = right;
5466 /* if right is bit then exchange them */
5467 if (AOP_TYPE (right) == AOP_CRY &&
5468 AOP_TYPE (left) != AOP_CRY)
5470 operand *tmp = right;
5474 if (AOP_TYPE (right) == AOP_LIT)
5475 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5477 size = AOP_SIZE (result);
5481 if (AOP_TYPE (left) == AOP_CRY)
5483 if (AOP_TYPE (right) == AOP_LIT)
5485 // c = bit & literal;
5488 // lit>>1 != 0 => result = 1
5489 if (AOP_TYPE (result) == AOP_CRY)
5492 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5494 continueIfTrue (ifx);
5497 emitcode ("setb", "c");
5504 // lit == 0, result = left
5505 if (size && sameRegs (AOP (result), AOP (left)))
5507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5511 // lit == 1, result = not(left)
5512 if (size && sameRegs (AOP (result), AOP (left)))
5514 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5519 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5520 emitcode ("cpl", "c");
5529 symbol *tlbl = newiTempLabel (NULL);
5530 if (AOP_TYPE (right) == AOP_CRY)
5533 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5537 int sizer = AOP_SIZE (right);
5539 // if val>>1 != 0, result = 1
5540 emitcode ("setb", "c");
5543 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5545 // test the msb of the lsb
5546 emitcode ("anl", "a,#0xfe");
5547 emitcode ("jnz", "%05d$", tlbl->key + 100);
5551 emitcode ("rrc", "a");
5553 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5554 emitcode ("cpl", "c");
5555 emitcode ("", "%05d$:", (tlbl->key + 100));
5562 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5563 genIfxJump (ifx, "c");
5567 if (sameRegs (AOP (result), AOP (left)))
5569 /* if left is same as result */
5570 for (; size--; offset++)
5572 if (AOP_TYPE (right) == AOP_LIT)
5574 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5576 else if (IS_AOP_PREG (left))
5578 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5579 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5580 aopPut (AOP (result), "a", offset);
5583 emitcode ("xrl", "%s,%s",
5584 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5585 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5589 if (AOP_TYPE (left) == AOP_ACC)
5590 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5593 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5594 if (IS_AOP_PREG (left))
5596 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5597 aopPut (AOP (result), "a", offset);
5600 emitcode ("xrl", "%s,a",
5601 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5608 // left & result in different registers
5609 if (AOP_TYPE (result) == AOP_CRY)
5612 // if(size), result in bit
5613 // if(!size && ifx), conditional oper: if(left ^ right)
5614 symbol *tlbl = newiTempLabel (NULL);
5615 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5617 emitcode ("setb", "c");
5620 if ((AOP_TYPE (right) == AOP_LIT) &&
5621 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5623 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5627 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5628 emitcode ("xrl", "a,%s",
5629 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5631 emitcode ("jnz", "%05d$", tlbl->key + 100);
5637 emitcode ("", "%05d$:", tlbl->key + 100);
5641 jmpTrueOrFalse (ifx, tlbl);
5644 for (; (size--); offset++)
5647 // result = left & right
5648 if (AOP_TYPE (right) == AOP_LIT)
5650 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5652 aopPut (AOP (result),
5653 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5657 D (emitcode (";", "better literal XOR.");
5659 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5660 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5661 FALSE, FALSE, FALSE));
5665 // faster than result <- left, anl result,right
5666 // and better if result is SFR
5667 if (AOP_TYPE (left) == AOP_ACC)
5669 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5670 FALSE, FALSE, FALSE));
5674 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5675 emitcode ("xrl", "a,%s",
5676 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5679 aopPut (AOP (result), "a", offset);
5684 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5685 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5686 freeAsmop (result, NULL, ic, TRUE);
5689 /*-----------------------------------------------------------------*/
5690 /* genInline - write the inline code out */
5691 /*-----------------------------------------------------------------*/
5693 genInline (iCode * ic)
5695 char buffer[MAX_INLINEASM];
5699 D (emitcode (";", "genInline ");
5702 _G.inLine += (!options.asmpeep);
5703 strcpy (buffer, IC_INLINE (ic));
5705 /* emit each line as a code */
5730 /* emitcode("",buffer); */
5731 _G.inLine -= (!options.asmpeep);
5734 /*-----------------------------------------------------------------*/
5735 /* genRRC - rotate right with carry */
5736 /*-----------------------------------------------------------------*/
5740 operand *left, *result;
5741 int size, offset = 0;
5744 D (emitcode (";", "genRRC ");
5747 /* rotate right with carry */
5748 left = IC_LEFT (ic);
5749 result = IC_RESULT (ic);
5750 aopOp (left, ic, FALSE, FALSE);
5751 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5753 /* move it to the result */
5754 size = AOP_SIZE (result);
5758 _startLazyDPSEvaluation ();
5761 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5763 emitcode ("rrc", "a");
5764 if (AOP_SIZE (result) > 1)
5765 aopPut (AOP (result), "a", offset--);
5767 _endLazyDPSEvaluation ();
5769 /* now we need to put the carry into the
5770 highest order byte of the result */
5771 if (AOP_SIZE (result) > 1)
5773 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5776 emitcode ("mov", "acc.7,c");
5777 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5778 freeAsmop (left, NULL, ic, TRUE);
5779 freeAsmop (result, NULL, ic, TRUE);
5782 /*-----------------------------------------------------------------*/
5783 /* genRLC - generate code for rotate left with carry */
5784 /*-----------------------------------------------------------------*/
5788 operand *left, *result;
5789 int size, offset = 0;
5792 D (emitcode (";", "genRLC ");
5795 /* rotate right with carry */
5796 left = IC_LEFT (ic);
5797 result = IC_RESULT (ic);
5798 aopOp (left, ic, FALSE, FALSE);
5799 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5801 /* move it to the result */
5802 size = AOP_SIZE (result);
5806 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5808 emitcode ("add", "a,acc");
5809 if (AOP_SIZE (result) > 1)
5811 aopPut (AOP (result), "a", offset++);
5814 _startLazyDPSEvaluation ();
5817 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5819 emitcode ("rlc", "a");
5820 if (AOP_SIZE (result) > 1)
5821 aopPut (AOP (result), "a", offset++);
5823 _endLazyDPSEvaluation ();
5825 /* now we need to put the carry into the
5826 highest order byte of the result */
5827 if (AOP_SIZE (result) > 1)
5829 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5832 emitcode ("mov", "acc.0,c");
5833 aopPut (AOP (result), "a", 0);
5834 freeAsmop (left, NULL, ic, TRUE);
5835 freeAsmop (result, NULL, ic, TRUE);
5838 /*-----------------------------------------------------------------*/
5839 /* genGetHbit - generates code get highest order bit */
5840 /*-----------------------------------------------------------------*/
5842 genGetHbit (iCode * ic)
5844 operand *left, *result;
5845 left = IC_LEFT (ic);
5846 result = IC_RESULT (ic);
5847 aopOp (left, ic, FALSE, FALSE);
5848 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5850 D (emitcode (";", "genGetHbit ");
5853 /* get the highest order byte into a */
5854 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5855 if (AOP_TYPE (result) == AOP_CRY)
5857 emitcode ("rlc", "a");
5862 emitcode ("rl", "a");
5863 emitcode ("anl", "a,#0x01");
5868 freeAsmop (left, NULL, ic, TRUE);
5869 freeAsmop (result, NULL, ic, TRUE);
5872 /*-----------------------------------------------------------------*/
5873 /* AccRol - rotate left accumulator by known count */
5874 /*-----------------------------------------------------------------*/
5876 AccRol (int shCount)
5878 shCount &= 0x0007; // shCount : 0..7
5885 emitcode ("rl", "a");
5888 emitcode ("rl", "a");
5889 emitcode ("rl", "a");
5892 emitcode ("swap", "a");
5893 emitcode ("rr", "a");
5896 emitcode ("swap", "a");
5899 emitcode ("swap", "a");
5900 emitcode ("rl", "a");
5903 emitcode ("rr", "a");
5904 emitcode ("rr", "a");
5907 emitcode ("rr", "a");
5912 /*-----------------------------------------------------------------*/
5913 /* AccLsh - left shift accumulator by known count */
5914 /*-----------------------------------------------------------------*/
5916 AccLsh (int shCount)
5921 emitcode ("add", "a,acc");
5922 else if (shCount == 2)
5924 emitcode ("add", "a,acc");
5925 emitcode ("add", "a,acc");
5929 /* rotate left accumulator */
5931 /* and kill the lower order bits */
5932 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5937 /*-----------------------------------------------------------------*/
5938 /* AccRsh - right shift accumulator by known count */
5939 /*-----------------------------------------------------------------*/
5941 AccRsh (int shCount)
5948 emitcode ("rrc", "a");
5952 /* rotate right accumulator */
5953 AccRol (8 - shCount);
5954 /* and kill the higher order bits */
5955 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5962 /*-----------------------------------------------------------------*/
5963 /* AccSRsh - signed right shift accumulator by known count */
5964 /*-----------------------------------------------------------------*/
5966 AccSRsh (int shCount)
5973 emitcode ("mov", "c,acc.7");
5974 emitcode ("rrc", "a");
5976 else if (shCount == 2)
5978 emitcode ("mov", "c,acc.7");
5979 emitcode ("rrc", "a");
5980 emitcode ("mov", "c,acc.7");
5981 emitcode ("rrc", "a");
5985 tlbl = newiTempLabel (NULL);
5986 /* rotate right accumulator */
5987 AccRol (8 - shCount);
5988 /* and kill the higher order bits */
5989 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5990 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5991 emitcode ("orl", "a,#0x%02x",
5992 (unsigned char) ~SRMask[shCount]);
5993 emitcode ("", "%05d$:", tlbl->key + 100);
6001 /*-----------------------------------------------------------------*/
6002 /* shiftR1Left2Result - shift right one byte from left to result */
6003 /*-----------------------------------------------------------------*/
6005 shiftR1Left2Result (operand * left, int offl,
6006 operand * result, int offr,
6007 int shCount, int sign)
6009 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6010 /* shift right accumulator */
6015 aopPut (AOP (result), "a", offr);
6021 /*-----------------------------------------------------------------*/
6022 /* shiftL1Left2Result - shift left one byte from left to result */
6023 /*-----------------------------------------------------------------*/
6025 shiftL1Left2Result (operand * left, int offl,
6026 operand * result, int offr, int shCount)
6029 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6031 /* shift left accumulator */
6033 aopPut (AOP (result), "a", offr);
6039 /*-----------------------------------------------------------------*/
6040 /* movLeft2Result - move byte from left to result */
6041 /*-----------------------------------------------------------------*/
6043 movLeft2Result (operand * left, int offl,
6044 operand * result, int offr, int sign)
6047 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6049 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6051 if (*l == '@' && (IS_AOP_PREG (result)))
6053 emitcode ("mov", "a,%s", l);
6054 aopPut (AOP (result), "a", offr);
6059 aopPut (AOP (result), l, offr);
6062 /* MSB sign in acc.7 ! */
6063 if (getDataSize (left) == offl + 1)
6065 emitcode ("mov", "a,%s", l);
6066 aopPut (AOP (result), "a", offr);
6076 /*-----------------------------------------------------------------*/
6077 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6078 /*-----------------------------------------------------------------*/
6082 emitcode ("rrc", "a");
6083 emitcode ("xch", "a,%s", x);
6084 emitcode ("rrc", "a");
6085 emitcode ("xch", "a,%s", x);
6091 /*-----------------------------------------------------------------*/
6092 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6093 /*-----------------------------------------------------------------*/
6097 emitcode ("xch", "a,%s", x);
6098 emitcode ("rlc", "a");
6099 emitcode ("xch", "a,%s", x);
6100 emitcode ("rlc", "a");
6106 /*-----------------------------------------------------------------*/
6107 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6108 /*-----------------------------------------------------------------*/
6112 emitcode ("xch", "a,%s", x);
6113 emitcode ("add", "a,acc");
6114 emitcode ("xch", "a,%s", x);
6115 emitcode ("rlc", "a");
6121 /*-----------------------------------------------------------------*/
6122 /* AccAXLsh - left shift a:x by known count (0..7) */
6123 /*-----------------------------------------------------------------*/
6125 AccAXLsh (char *x, int shCount)
6140 case 5: // AAAAABBB:CCCCCDDD
6142 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6144 emitcode ("anl", "a,#0x%02x",
6145 SLMask[shCount]); // BBB00000:CCCCCDDD
6147 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6149 AccRol (shCount); // DDDCCCCC:BBB00000
6151 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6153 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6155 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6157 emitcode ("anl", "a,#0x%02x",
6158 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6160 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6162 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6165 case 6: // AAAAAABB:CCCCCCDD
6167 emitcode ("anl", "a,#0x%02x",
6168 SRMask[shCount]); // 000000BB:CCCCCCDD
6170 emitcode ("mov", "c,acc.0"); // c = B
6172 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6174 AccAXRrl1 (x); // BCCCCCCD:D000000B
6176 AccAXRrl1 (x); // BBCCCCCC:DD000000
6179 case 7: // a:x <<= 7
6181 emitcode ("anl", "a,#0x%02x",
6182 SRMask[shCount]); // 0000000B:CCCCCCCD
6184 emitcode ("mov", "c,acc.0"); // c = B
6186 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6188 AccAXRrl1 (x); // BCCCCCCC:D0000000
6199 /*-----------------------------------------------------------------*/
6200 /* AccAXRsh - right shift a:x known count (0..7) */
6201 /*-----------------------------------------------------------------*/
6203 AccAXRsh (char *x, int shCount)
6211 AccAXRrl1 (x); // 0->a:x
6216 AccAXRrl1 (x); // 0->a:x
6219 AccAXRrl1 (x); // 0->a:x
6224 case 5: // AAAAABBB:CCCCCDDD = a:x
6226 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6228 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6230 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6232 emitcode ("anl", "a,#0x%02x",
6233 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6235 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6237 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6239 emitcode ("anl", "a,#0x%02x",
6240 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6242 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6244 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6246 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6249 case 6: // AABBBBBB:CCDDDDDD
6251 emitcode ("mov", "c,acc.7");
6252 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6254 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6256 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6258 emitcode ("anl", "a,#0x%02x",
6259 SRMask[shCount]); // 000000AA:BBBBBBCC
6262 case 7: // ABBBBBBB:CDDDDDDD
6264 emitcode ("mov", "c,acc.7"); // c = A
6266 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6268 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6270 emitcode ("anl", "a,#0x%02x",
6271 SRMask[shCount]); // 0000000A:BBBBBBBC
6282 /*-----------------------------------------------------------------*/
6283 /* AccAXRshS - right shift signed a:x known count (0..7) */
6284 /*-----------------------------------------------------------------*/
6286 AccAXRshS (char *x, int shCount)
6294 emitcode ("mov", "c,acc.7");
6295 AccAXRrl1 (x); // s->a:x
6299 emitcode ("mov", "c,acc.7");
6300 AccAXRrl1 (x); // s->a:x
6302 emitcode ("mov", "c,acc.7");
6303 AccAXRrl1 (x); // s->a:x
6308 case 5: // AAAAABBB:CCCCCDDD = a:x
6310 tlbl = newiTempLabel (NULL);
6311 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6313 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6315 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6317 emitcode ("anl", "a,#0x%02x",
6318 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6320 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6322 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6324 emitcode ("anl", "a,#0x%02x",
6325 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6327 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6329 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6331 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6333 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6334 emitcode ("orl", "a,#0x%02x",
6335 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6337 emitcode ("", "%05d$:", tlbl->key + 100);
6338 break; // SSSSAAAA:BBBCCCCC
6340 case 6: // AABBBBBB:CCDDDDDD
6342 tlbl = newiTempLabel (NULL);
6343 emitcode ("mov", "c,acc.7");
6344 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6346 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6348 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6350 emitcode ("anl", "a,#0x%02x",
6351 SRMask[shCount]); // 000000AA:BBBBBBCC
6353 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6354 emitcode ("orl", "a,#0x%02x",
6355 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6357 emitcode ("", "%05d$:", tlbl->key + 100);
6359 case 7: // ABBBBBBB:CDDDDDDD
6361 tlbl = newiTempLabel (NULL);
6362 emitcode ("mov", "c,acc.7"); // c = A
6364 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6366 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6368 emitcode ("anl", "a,#0x%02x",
6369 SRMask[shCount]); // 0000000A:BBBBBBBC
6371 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6372 emitcode ("orl", "a,#0x%02x",
6373 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6375 emitcode ("", "%05d$:", tlbl->key + 100);
6385 /*-----------------------------------------------------------------*/
6386 /* shiftL2Left2Result - shift left two bytes from left to result */
6387 /*-----------------------------------------------------------------*/
6389 shiftL2Left2Result (operand * left, int offl,
6390 operand * result, int offr, int shCount)
6392 if (sameRegs (AOP (result), AOP (left)) &&
6393 ((offl + MSB16) == offr))
6395 /* don't crash result[offr] */
6396 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6397 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6401 movLeft2Result (left, offl, result, offr, 0);
6402 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6404 /* ax << shCount (x = lsb(result)) */
6405 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6406 aopPut (AOP (result), "a", offr + MSB16);
6412 /*-----------------------------------------------------------------*/
6413 /* shiftR2Left2Result - shift right two bytes from left to result */
6414 /*-----------------------------------------------------------------*/
6416 shiftR2Left2Result (operand * left, int offl,
6417 operand * result, int offr,
6418 int shCount, int sign)
6420 if (sameRegs (AOP (result), AOP (left)) &&
6421 ((offl + MSB16) == offr))
6423 /* don't crash result[offr] */
6424 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6425 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6429 movLeft2Result (left, offl, result, offr, 0);
6430 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6432 /* a:x >> shCount (x = lsb(result)) */
6434 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6436 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6437 if (getDataSize (result) > 1)
6438 aopPut (AOP (result), "a", offr + MSB16);
6444 /*-----------------------------------------------------------------*/
6445 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6446 /*-----------------------------------------------------------------*/
6448 shiftLLeftOrResult (operand * left, int offl,
6449 operand * result, int offr, int shCount)
6451 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6452 /* shift left accumulator */
6454 /* or with result */
6455 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6456 /* back to result */
6457 aopPut (AOP (result), "a", offr);
6463 /*-----------------------------------------------------------------*/
6464 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6465 /*-----------------------------------------------------------------*/
6467 shiftRLeftOrResult (operand * left, int offl,
6468 operand * result, int offr, int shCount)
6470 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6471 /* shift right accumulator */
6473 /* or with result */
6474 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6475 /* back to result */
6476 aopPut (AOP (result), "a", offr);
6482 /*-----------------------------------------------------------------*/
6483 /* genlshOne - left shift a one byte quantity by known count */
6484 /*-----------------------------------------------------------------*/
6486 genlshOne (operand * result, operand * left, int shCount)
6488 D (emitcode (";", "genlshOne ");
6490 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6496 /*-----------------------------------------------------------------*/
6497 /* genlshTwo - left shift two bytes by known amount != 0 */
6498 /*-----------------------------------------------------------------*/
6500 genlshTwo (operand * result, operand * left, int shCount)
6504 D (emitcode (";", "genlshTwo ");
6507 size = getDataSize (result);
6509 /* if shCount >= 8 */
6517 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6519 movLeft2Result (left, LSB, result, MSB16, 0);
6521 aopPut (AOP (result), zero, LSB);
6524 /* 1 <= shCount <= 7 */
6528 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6530 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6537 /*-----------------------------------------------------------------*/
6538 /* shiftLLong - shift left one long from left to result */
6539 /* offl = LSB or MSB16 */
6540 /*-----------------------------------------------------------------*/
6542 shiftLLong (operand * left, operand * result, int offr)
6545 int size = AOP_SIZE (result);
6547 if (size >= LSB + offr)
6549 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6551 emitcode ("add", "a,acc");
6552 if (sameRegs (AOP (left), AOP (result)) &&
6553 size >= MSB16 + offr && offr != LSB)
6554 emitcode ("xch", "a,%s",
6555 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6557 aopPut (AOP (result), "a", LSB + offr);
6560 if (size >= MSB16 + offr)
6562 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6564 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6567 emitcode ("rlc", "a");
6568 if (sameRegs (AOP (left), AOP (result)) &&
6569 size >= MSB24 + offr && offr != LSB)
6570 emitcode ("xch", "a,%s",
6571 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6573 aopPut (AOP (result), "a", MSB16 + offr);
6576 if (size >= MSB24 + offr)
6578 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6580 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6583 emitcode ("rlc", "a");
6584 if (sameRegs (AOP (left), AOP (result)) &&
6585 size >= MSB32 + offr && offr != LSB)
6586 emitcode ("xch", "a,%s",
6587 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6589 aopPut (AOP (result), "a", MSB24 + offr);
6592 if (size > MSB32 + offr)
6594 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6596 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6599 emitcode ("rlc", "a");
6600 aopPut (AOP (result), "a", MSB32 + offr);
6603 aopPut (AOP (result), zero, LSB);
6609 /*-----------------------------------------------------------------*/
6610 /* genlshFour - shift four byte by a known amount != 0 */
6611 /*-----------------------------------------------------------------*/
6613 genlshFour (operand * result, operand * left, int shCount)
6617 D (emitcode (";", "genlshFour ");
6620 size = AOP_SIZE (result);
6622 /* if shifting more that 3 bytes */
6627 /* lowest order of left goes to the highest
6628 order of the destination */
6629 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6631 movLeft2Result (left, LSB, result, MSB32, 0);
6632 aopPut (AOP (result), zero, LSB);
6633 aopPut (AOP (result), zero, MSB16);
6634 aopPut (AOP (result), zero, MSB32);
6638 /* more than two bytes */
6639 else if (shCount >= 16)
6641 /* lower order two bytes goes to higher order two bytes */
6643 /* if some more remaining */
6645 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6648 movLeft2Result (left, MSB16, result, MSB32, 0);
6649 movLeft2Result (left, LSB, result, MSB24, 0);
6651 aopPut (AOP (result), zero, MSB16);
6652 aopPut (AOP (result), zero, LSB);
6656 /* if more than 1 byte */
6657 else if (shCount >= 8)
6659 /* lower order three bytes goes to higher order three bytes */
6664 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6666 movLeft2Result (left, LSB, result, MSB16, 0);
6672 movLeft2Result (left, MSB24, result, MSB32, 0);
6673 movLeft2Result (left, MSB16, result, MSB24, 0);
6674 movLeft2Result (left, LSB, result, MSB16, 0);
6675 aopPut (AOP (result), zero, LSB);
6677 else if (shCount == 1)
6678 shiftLLong (left, result, MSB16);
6681 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6682 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6683 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6684 aopPut (AOP (result), zero, LSB);
6689 /* 1 <= shCount <= 7 */
6690 else if (shCount <= 2)
6692 shiftLLong (left, result, LSB);
6694 shiftLLong (result, result, LSB);
6696 /* 3 <= shCount <= 7, optimize */
6699 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6700 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6701 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6708 /*-----------------------------------------------------------------*/
6709 /* genLeftShiftLiteral - left shifting by known count */
6710 /*-----------------------------------------------------------------*/
6712 genLeftShiftLiteral (operand * left,
6717 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6720 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6723 freeAsmop (right, NULL, ic, TRUE);
6725 aopOp (left, ic, FALSE, FALSE);
6726 aopOp (result, ic, FALSE, TRUE);
6728 size = getSize (operandType (result));
6731 emitcode ("; shift left ", "result %d, left %d", size,
6735 /* I suppose that the left size >= result size */
6740 movLeft2Result (left, size, result, size, 0);
6744 else if (shCount >= (size * 8))
6746 aopPut (AOP (result), zero, size);
6752 genlshOne (result, left, shCount);
6756 case 3: /* bug: this is for generic pointers, I bet. */
6757 genlshTwo (result, left, shCount);
6761 genlshFour (result, left, shCount);
6765 freeAsmop (left, NULL, ic, TRUE);
6766 freeAsmop (result, NULL, ic, TRUE);
6770 /*-----------------------------------------------------------------*/
6771 /* genLeftShift - generates code for left shifting */
6772 /*-----------------------------------------------------------------*/
6774 genLeftShift (iCode * ic)
6776 operand *left, *right, *result;
6779 symbol *tlbl, *tlbl1;
6781 D (emitcode (";", "genLeftShift ");
6784 right = IC_RIGHT (ic);
6785 left = IC_LEFT (ic);
6786 result = IC_RESULT (ic);
6788 aopOp (right, ic, FALSE, FALSE);
6791 /* if the shift count is known then do it
6792 as efficiently as possible */
6793 if (AOP_TYPE (right) == AOP_LIT)
6795 genLeftShiftLiteral (left, right, result, ic);
6800 /* shift count is unknown then we have to form
6801 a loop get the loop count in B : Note: we take
6802 only the lower order byte since shifting
6803 more that 32 bits make no sense anyway, ( the
6804 largest size of an object can be only 32 bits ) */
6806 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6807 emitcode ("inc", "b");
6808 freeAsmop (right, NULL, ic, TRUE);
6809 aopOp (left, ic, FALSE, FALSE);
6810 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6812 /* now move the left to the result if they are not the
6814 if (!sameRegs (AOP (left), AOP (result)) &&
6815 AOP_SIZE (result) > 1)
6818 size = AOP_SIZE (result);
6820 _startLazyDPSEvaluation ();
6823 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6824 if (*l == '@' && (IS_AOP_PREG (result)))
6827 emitcode ("mov", "a,%s", l);
6828 aopPut (AOP (result), "a", offset);
6831 aopPut (AOP (result), l, offset);
6834 _endLazyDPSEvaluation ();
6837 tlbl = newiTempLabel (NULL);
6838 size = AOP_SIZE (result);
6840 tlbl1 = newiTempLabel (NULL);
6842 /* if it is only one byte then */
6845 symbol *tlbl1 = newiTempLabel (NULL);
6847 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6849 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6850 emitcode ("", "%05d$:", tlbl->key + 100);
6851 emitcode ("add", "a,acc");
6852 emitcode ("", "%05d$:", tlbl1->key + 100);
6853 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6854 aopPut (AOP (result), "a", 0);
6858 reAdjustPreg (AOP (result));
6860 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6861 emitcode ("", "%05d$:", tlbl->key + 100);
6862 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6864 emitcode ("add", "a,acc");
6865 aopPut (AOP (result), "a", offset++);
6866 _startLazyDPSEvaluation ();
6869 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6871 emitcode ("rlc", "a");
6872 aopPut (AOP (result), "a", offset++);
6874 _endLazyDPSEvaluation ();
6875 reAdjustPreg (AOP (result));
6877 emitcode ("", "%05d$:", tlbl1->key + 100);
6878 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6880 freeAsmop (left, NULL, ic, TRUE);
6881 freeAsmop (result, NULL, ic, TRUE);
6886 /*-----------------------------------------------------------------*/
6887 /* genrshOne - right shift a one byte quantity by known count */
6888 /*-----------------------------------------------------------------*/
6890 genrshOne (operand * result, operand * left,
6891 int shCount, int sign)
6893 D (emitcode (";", "genrshOne");
6895 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6901 /*-----------------------------------------------------------------*/
6902 /* genrshTwo - right shift two bytes by known amount != 0 */
6903 /*-----------------------------------------------------------------*/
6905 genrshTwo (operand * result, operand * left,
6906 int shCount, int sign)
6908 D (emitcode (";", "genrshTwo");
6911 /* if shCount >= 8 */
6916 shiftR1Left2Result (left, MSB16, result, LSB,
6919 movLeft2Result (left, MSB16, result, LSB, sign);
6920 addSign (result, MSB16, sign);
6923 /* 1 <= shCount <= 7 */
6925 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6931 /*-----------------------------------------------------------------*/
6932 /* shiftRLong - shift right one long from left to result */
6933 /* offl = LSB or MSB16 */
6934 /*-----------------------------------------------------------------*/
6936 shiftRLong (operand * left, int offl,
6937 operand * result, int sign)
6940 emitcode ("clr", "c");
6941 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6943 emitcode ("mov", "c,acc.7");
6944 emitcode ("rrc", "a");
6945 aopPut (AOP (result), "a", MSB32 - offl);
6947 /* add sign of "a" */
6948 addSign (result, MSB32, sign);
6950 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6951 emitcode ("rrc", "a");
6952 aopPut (AOP (result), "a", MSB24 - offl);
6954 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6955 emitcode ("rrc", "a");
6956 aopPut (AOP (result), "a", MSB16 - offl);
6960 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6961 emitcode ("rrc", "a");
6962 aopPut (AOP (result), "a", LSB);
6969 /*-----------------------------------------------------------------*/
6970 /* genrshFour - shift four byte by a known amount != 0 */
6971 /*-----------------------------------------------------------------*/
6973 genrshFour (operand * result, operand * left,
6974 int shCount, int sign)
6976 D (emitcode (";", "genrshFour");
6979 /* if shifting more that 3 bytes */
6984 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6986 movLeft2Result (left, MSB32, result, LSB, sign);
6987 addSign (result, MSB16, sign);
6989 else if (shCount >= 16)
6993 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6996 movLeft2Result (left, MSB24, result, LSB, 0);
6997 movLeft2Result (left, MSB32, result, MSB16, sign);
6999 addSign (result, MSB24, sign);
7001 else if (shCount >= 8)
7005 shiftRLong (left, MSB16, result, sign);
7006 else if (shCount == 0)
7008 movLeft2Result (left, MSB16, result, LSB, 0);
7009 movLeft2Result (left, MSB24, result, MSB16, 0);
7010 movLeft2Result (left, MSB32, result, MSB24, sign);
7011 addSign (result, MSB32, sign);
7015 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7016 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7017 /* the last shift is signed */
7018 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7019 addSign (result, MSB32, sign);
7023 { /* 1 <= shCount <= 7 */
7026 shiftRLong (left, LSB, result, sign);
7028 shiftRLong (result, LSB, result, sign);
7032 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7033 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7034 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7042 /*-----------------------------------------------------------------*/
7043 /* genRightShiftLiteral - right shifting by known count */
7044 /*-----------------------------------------------------------------*/
7046 genRightShiftLiteral (operand * left,
7052 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7055 D (emitcode (";", "genRightShiftLiteral");
7058 freeAsmop (right, NULL, ic, TRUE);
7060 aopOp (left, ic, FALSE, FALSE);
7061 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7064 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7068 size = getDataSize (left);
7069 /* test the LEFT size !!! */
7071 /* I suppose that the left size >= result size */
7074 size = getDataSize (result);
7076 movLeft2Result (left, size, result, size, 0);
7079 else if (shCount >= (size * 8))
7082 /* get sign in acc.7 */
7083 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7084 addSign (result, LSB, sign);
7091 genrshOne (result, left, shCount, sign);
7095 genrshTwo (result, left, shCount, sign);
7099 genrshFour (result, left, shCount, sign);
7105 freeAsmop (left, NULL, ic, TRUE);
7106 freeAsmop (result, NULL, ic, TRUE);
7111 /*-----------------------------------------------------------------*/
7112 /* genSignedRightShift - right shift of signed number */
7113 /*-----------------------------------------------------------------*/
7115 genSignedRightShift (iCode * ic)
7117 operand *right, *left, *result;
7120 symbol *tlbl, *tlbl1;
7122 D (emitcode (";", "genSignedRightShift ");
7125 /* we do it the hard way put the shift count in b
7126 and loop thru preserving the sign */
7128 right = IC_RIGHT (ic);
7129 left = IC_LEFT (ic);
7130 result = IC_RESULT (ic);
7132 aopOp (right, ic, FALSE, FALSE);
7135 if (AOP_TYPE (right) == AOP_LIT)
7137 genRightShiftLiteral (left, right, result, ic, 1);
7141 /* shift count is unknown then we have to form
7142 a loop get the loop count in B : Note: we take
7143 only the lower order byte since shifting
7144 more that 32 bits make no sense anyway, ( the
7145 largest size of an object can be only 32 bits ) */
7147 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7148 emitcode ("inc", "b");
7149 freeAsmop (right, NULL, ic, TRUE);
7150 aopOp (left, ic, FALSE, FALSE);
7151 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7153 /* now move the left to the result if they are not the
7155 if (!sameRegs (AOP (left), AOP (result)) &&
7156 AOP_SIZE (result) > 1)
7159 size = AOP_SIZE (result);
7161 _startLazyDPSEvaluation ();
7164 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7165 if (*l == '@' && IS_AOP_PREG (result))
7168 emitcode ("mov", "a,%s", l);
7169 aopPut (AOP (result), "a", offset);
7172 aopPut (AOP (result), l, offset);
7175 _endLazyDPSEvaluation ();
7178 /* mov the highest order bit to OVR */
7179 tlbl = newiTempLabel (NULL);
7180 tlbl1 = newiTempLabel (NULL);
7182 size = AOP_SIZE (result);
7184 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7185 emitcode ("rlc", "a");
7186 emitcode ("mov", "ov,c");
7187 /* if it is only one byte then */
7190 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7192 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7193 emitcode ("", "%05d$:", tlbl->key + 100);
7194 emitcode ("mov", "c,ov");
7195 emitcode ("rrc", "a");
7196 emitcode ("", "%05d$:", tlbl1->key + 100);
7197 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7198 aopPut (AOP (result), "a", 0);
7202 reAdjustPreg (AOP (result));
7203 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7204 emitcode ("", "%05d$:", tlbl->key + 100);
7205 emitcode ("mov", "c,ov");
7206 _startLazyDPSEvaluation ();
7209 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7211 emitcode ("rrc", "a");
7212 aopPut (AOP (result), "a", offset--);
7214 _endLazyDPSEvaluation ();
7215 reAdjustPreg (AOP (result));
7216 emitcode ("", "%05d$:", tlbl1->key + 100);
7217 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7220 freeAsmop (left, NULL, ic, TRUE);
7221 freeAsmop (result, NULL, ic, TRUE);
7224 /*-----------------------------------------------------------------*/
7225 /* genRightShift - generate code for right shifting */
7226 /*-----------------------------------------------------------------*/
7228 genRightShift (iCode * ic)
7230 operand *right, *left, *result;
7234 symbol *tlbl, *tlbl1;
7236 D (emitcode (";", "genRightShift ");
7239 /* if signed then we do it the hard way preserve the
7240 sign bit moving it inwards */
7241 retype = getSpec (operandType (IC_RESULT (ic)));
7243 if (!SPEC_USIGN (retype))
7245 genSignedRightShift (ic);
7249 /* signed & unsigned types are treated the same : i.e. the
7250 signed is NOT propagated inwards : quoting from the
7251 ANSI - standard : "for E1 >> E2, is equivalent to division
7252 by 2**E2 if unsigned or if it has a non-negative value,
7253 otherwise the result is implementation defined ", MY definition
7254 is that the sign does not get propagated */
7256 right = IC_RIGHT (ic);
7257 left = IC_LEFT (ic);
7258 result = IC_RESULT (ic);
7260 aopOp (right, ic, FALSE, FALSE);
7263 /* if the shift count is known then do it
7264 as efficiently as possible */
7265 if (AOP_TYPE (right) == AOP_LIT)
7267 genRightShiftLiteral (left, right, result, ic, 0);
7272 /* shift count is unknown then we have to form
7273 a loop get the loop count in B : Note: we take
7274 only the lower order byte since shifting
7275 more that 32 bits make no sense anyway, ( the
7276 largest size of an object can be only 32 bits ) */
7278 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7279 emitcode ("inc", "b");
7280 freeAsmop (right, NULL, ic, TRUE);
7281 aopOp (left, ic, FALSE, FALSE);
7282 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7284 /* now move the left to the result if they are not the
7286 if (!sameRegs (AOP (left), AOP (result)) &&
7287 AOP_SIZE (result) > 1)
7290 size = AOP_SIZE (result);
7292 _startLazyDPSEvaluation ();
7295 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7296 if (*l == '@' && IS_AOP_PREG (result))
7299 emitcode ("mov", "a,%s", l);
7300 aopPut (AOP (result), "a", offset);
7303 aopPut (AOP (result), l, offset);
7306 _endLazyDPSEvaluation ();
7309 tlbl = newiTempLabel (NULL);
7310 tlbl1 = newiTempLabel (NULL);
7311 size = AOP_SIZE (result);
7314 /* if it is only one byte then */
7317 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7319 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7320 emitcode ("", "%05d$:", tlbl->key + 100);
7322 emitcode ("rrc", "a");
7323 emitcode ("", "%05d$:", tlbl1->key + 100);
7324 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7325 aopPut (AOP (result), "a", 0);
7329 reAdjustPreg (AOP (result));
7330 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7331 emitcode ("", "%05d$:", tlbl->key + 100);
7333 _startLazyDPSEvaluation ();
7336 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7338 emitcode ("rrc", "a");
7339 aopPut (AOP (result), "a", offset--);
7341 _endLazyDPSEvaluation ();
7342 reAdjustPreg (AOP (result));
7344 emitcode ("", "%05d$:", tlbl1->key + 100);
7345 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7348 freeAsmop (left, NULL, ic, TRUE);
7349 freeAsmop (result, NULL, ic, TRUE);
7352 /*-----------------------------------------------------------------*/
7353 /* genUnpackBits - generates code for unpacking bits */
7354 /*-----------------------------------------------------------------*/
7356 genUnpackBits (operand * result, char *rname, int ptype)
7363 D (emitcode (";", "genUnpackBits ");
7366 etype = getSpec (operandType (result));
7368 /* read the first byte */
7374 emitcode ("mov", "a,@%s", rname);
7378 emitcode ("movx", "a,@%s", rname);
7382 emitcode ("movx", "a,@dptr");
7386 emitcode ("clr", "a");
7387 emitcode ("movc", "a", "@a+dptr");
7391 emitcode ("lcall", "__gptrget");
7395 /* if we have bitdisplacement then it fits */
7396 /* into this byte completely or if length is */
7397 /* less than a byte */
7398 if ((shCnt = SPEC_BSTR (etype)) ||
7399 (SPEC_BLEN (etype) <= 8))
7402 /* shift right acc */
7405 emitcode ("anl", "a,#0x%02x",
7406 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7407 aopPut (AOP (result), "a", offset);
7411 /* bit field did not fit in a byte */
7412 rlen = SPEC_BLEN (etype) - 8;
7413 aopPut (AOP (result), "a", offset++);
7422 emitcode ("inc", "%s", rname);
7423 emitcode ("mov", "a,@%s", rname);
7427 emitcode ("inc", "%s", rname);
7428 emitcode ("movx", "a,@%s", rname);
7432 emitcode ("inc", "dptr");
7433 emitcode ("movx", "a,@dptr");
7437 emitcode ("clr", "a");
7438 emitcode ("inc", "dptr");
7439 emitcode ("movc", "a", "@a+dptr");
7443 emitcode ("inc", "dptr");
7444 emitcode ("lcall", "__gptrget");
7449 /* if we are done */
7453 aopPut (AOP (result), "a", offset++);
7459 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7460 aopPut (AOP (result), "a", offset);
7467 /*-----------------------------------------------------------------*/
7468 /* genDataPointerGet - generates code when ptr offset is known */
7469 /*-----------------------------------------------------------------*/
7471 genDataPointerGet (operand * left,
7477 int size, offset = 0;
7478 aopOp (result, ic, TRUE, FALSE);
7480 /* get the string representation of the name */
7481 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7482 size = AOP_SIZE (result);
7483 _startLazyDPSEvaluation ();
7487 sprintf (buffer, "(%s + %d)", l + 1, offset);
7489 sprintf (buffer, "%s", l + 1);
7490 aopPut (AOP (result), buffer, offset++);
7492 _endLazyDPSEvaluation ();
7494 freeAsmop (left, NULL, ic, TRUE);
7495 freeAsmop (result, NULL, ic, TRUE);
7498 /*-----------------------------------------------------------------*/
7499 /* genNearPointerGet - emitcode for near pointer fetch */
7500 /*-----------------------------------------------------------------*/
7502 genNearPointerGet (operand * left,
7509 sym_link *rtype, *retype, *letype;
7510 sym_link *ltype = operandType (left);
7513 rtype = operandType (result);
7514 retype = getSpec (rtype);
7515 letype = getSpec (ltype);
7517 aopOp (left, ic, FALSE, FALSE);
7519 /* if left is rematerialisable and
7520 result is not bit variable type and
7521 the left is pointer to data space i.e
7522 lower 128 bytes of space */
7523 if (AOP_TYPE (left) == AOP_IMMD &&
7524 !IS_BITVAR (retype) &&
7525 !IS_BITVAR (letype) &&
7526 DCL_TYPE (ltype) == POINTER)
7528 genDataPointerGet (left, result, ic);
7532 /* if the value is already in a pointer register
7533 then don't need anything more */
7534 if (!AOP_INPREG (AOP (left)))
7536 /* otherwise get a free pointer register */
7538 preg = getFreePtr (ic, &aop, FALSE);
7539 emitcode ("mov", "%s,%s",
7541 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7545 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7547 freeAsmop (left, NULL, ic, TRUE);
7548 aopOp (result, ic, FALSE, FALSE);
7550 /* if bitfield then unpack the bits */
7551 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7552 genUnpackBits (result, rname, POINTER);
7555 /* we have can just get the values */
7556 int size = AOP_SIZE (result);
7561 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7564 emitcode ("mov", "a,@%s", rname);
7565 aopPut (AOP (result), "a", offset);
7569 sprintf (buffer, "@%s", rname);
7570 aopPut (AOP (result), buffer, offset);
7574 emitcode ("inc", "%s", rname);
7578 /* now some housekeeping stuff */
7581 /* we had to allocate for this iCode */
7582 freeAsmop (NULL, aop, ic, TRUE);
7586 /* we did not allocate which means left
7587 already in a pointer register, then
7588 if size > 0 && this could be used again
7589 we have to point it back to where it
7591 if (AOP_SIZE (result) > 1 &&
7592 !OP_SYMBOL (left)->remat &&
7593 (OP_SYMBOL (left)->liveTo > ic->seq ||
7596 int size = AOP_SIZE (result) - 1;
7598 emitcode ("dec", "%s", rname);
7603 freeAsmop (result, NULL, ic, TRUE);
7607 /*-----------------------------------------------------------------*/
7608 /* genPagedPointerGet - emitcode for paged pointer fetch */
7609 /*-----------------------------------------------------------------*/
7611 genPagedPointerGet (operand * left,
7618 sym_link *rtype, *retype, *letype;
7620 rtype = operandType (result);
7621 retype = getSpec (rtype);
7622 letype = getSpec (operandType (left));
7623 aopOp (left, ic, FALSE, FALSE);
7625 /* if the value is already in a pointer register
7626 then don't need anything more */
7627 if (!AOP_INPREG (AOP (left)))
7629 /* otherwise get a free pointer register */
7631 preg = getFreePtr (ic, &aop, FALSE);
7632 emitcode ("mov", "%s,%s",
7634 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7638 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7640 freeAsmop (left, NULL, ic, TRUE);
7641 aopOp (result, ic, FALSE, FALSE);
7643 /* if bitfield then unpack the bits */
7644 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7645 genUnpackBits (result, rname, PPOINTER);
7648 /* we have can just get the values */
7649 int size = AOP_SIZE (result);
7655 emitcode ("movx", "a,@%s", rname);
7656 aopPut (AOP (result), "a", offset);
7661 emitcode ("inc", "%s", rname);
7665 /* now some housekeeping stuff */
7668 /* we had to allocate for this iCode */
7669 freeAsmop (NULL, aop, ic, TRUE);
7673 /* we did not allocate which means left
7674 already in a pointer register, then
7675 if size > 0 && this could be used again
7676 we have to point it back to where it
7678 if (AOP_SIZE (result) > 1 &&
7679 !OP_SYMBOL (left)->remat &&
7680 (OP_SYMBOL (left)->liveTo > ic->seq ||
7683 int size = AOP_SIZE (result) - 1;
7685 emitcode ("dec", "%s", rname);
7690 freeAsmop (result, NULL, ic, TRUE);
7695 /*-----------------------------------------------------------------*/
7696 /* genFarPointerGet - gget value from far space */
7697 /*-----------------------------------------------------------------*/
7699 genFarPointerGet (operand * left,
7700 operand * result, iCode * ic)
7703 sym_link *retype = getSpec (operandType (result));
7704 sym_link *letype = getSpec (operandType (left));
7705 D (emitcode (";", "genFarPointerGet");
7708 aopOp (left, ic, FALSE, FALSE);
7710 /* if the operand is already in dptr
7711 then we do nothing else we move the value to dptr */
7712 if (AOP_TYPE (left) != AOP_STR)
7714 /* if this is remateriazable */
7715 if (AOP_TYPE (left) == AOP_IMMD)
7717 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7721 /* we need to get it byte by byte */
7722 _startLazyDPSEvaluation ();
7723 if (AOP_TYPE (left) != AOP_DPTR)
7725 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7726 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7727 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7731 /* We need to generate a load to DPTR indirect through DPTR. */
7732 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7734 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7735 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7736 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7737 emitcode ("pop", "dph");
7738 emitcode ("pop", "dpl");
7740 _endLazyDPSEvaluation ();
7743 /* so dptr know contains the address */
7744 freeAsmop (left, NULL, ic, TRUE);
7745 aopOp (result, ic, FALSE, TRUE);
7747 /* if bit then unpack */
7748 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7749 genUnpackBits (result, "dptr", FPOINTER);
7752 size = AOP_SIZE (result);
7755 _startLazyDPSEvaluation ();
7762 emitcode ("movx", "a,@dptr");
7764 emitcode ("inc", "dptr");
7766 aopPut (AOP (result), "a", offset++);
7768 _endLazyDPSEvaluation ();
7771 freeAsmop (result, NULL, ic, TRUE);
7774 /*-----------------------------------------------------------------*/
7775 /* emitcodePointerGet - gget value from code space */
7776 /*-----------------------------------------------------------------*/
7778 emitcodePointerGet (operand * left,
7779 operand * result, iCode * ic)
7782 sym_link *retype = getSpec (operandType (result));
7784 aopOp (left, ic, FALSE, FALSE);
7786 /* if the operand is already in dptr
7787 then we do nothing else we move the value to dptr */
7788 if (AOP_TYPE (left) != AOP_STR)
7790 /* if this is remateriazable */
7791 if (AOP_TYPE (left) == AOP_IMMD)
7793 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7796 { /* we need to get it byte by byte */
7797 _startLazyDPSEvaluation ();
7798 if (AOP_TYPE (left) != AOP_DPTR)
7800 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7801 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7802 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7806 /* We need to generate a load to DPTR indirect through DPTR. */
7807 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7809 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7810 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7811 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7812 emitcode ("pop", "dph");
7813 emitcode ("pop", "dpl");
7815 _endLazyDPSEvaluation ();
7818 /* so dptr know contains the address */
7819 freeAsmop (left, NULL, ic, TRUE);
7820 aopOp (result, ic, FALSE, TRUE);
7822 /* if bit then unpack */
7823 if (IS_BITVAR (retype))
7824 genUnpackBits (result, "dptr", CPOINTER);
7827 size = AOP_SIZE (result);
7830 _startLazyDPSEvaluation ();
7836 emitcode ("clr", "a");
7837 emitcode ("movc", "a,@a+dptr");
7839 emitcode ("inc", "dptr");
7840 aopPut (AOP (result), "a", offset++);
7842 _endLazyDPSEvaluation ();
7845 freeAsmop (result, NULL, ic, TRUE);
7848 /*-----------------------------------------------------------------*/
7849 /* genGenPointerGet - gget value from generic pointer space */
7850 /*-----------------------------------------------------------------*/
7852 genGenPointerGet (operand * left,
7853 operand * result, iCode * ic)
7856 sym_link *retype = getSpec (operandType (result));
7857 sym_link *letype = getSpec (operandType (left));
7859 D (emitcode (";", "genGenPointerGet "); );
7861 aopOp (left, ic, FALSE, TRUE);
7863 /* if the operand is already in dptr
7864 then we do nothing else we move the value to dptr */
7865 if (AOP_TYPE (left) != AOP_STR)
7867 /* if this is remateriazable */
7868 if (AOP_TYPE (left) == AOP_IMMD)
7870 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7871 emitcode ("mov", "b,#%d", pointerCode (retype));
7874 { /* we need to get it byte by byte */
7875 _startLazyDPSEvaluation ();
7876 if (AOP(left)->type==AOP_DPTR2) {
7878 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7881 emitcode ("mov", "dpl,%s", l);
7882 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7885 emitcode ("mov", "dph,%s", l);
7886 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7889 emitcode ("mov", "dpx,%s", l);
7890 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7892 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7893 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7894 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7895 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7897 _endLazyDPSEvaluation ();
7900 /* so dptr know contains the address */
7901 freeAsmop (left, NULL, ic, TRUE);
7902 aopOp (result, ic, FALSE, TRUE);
7904 /* if bit then unpack */
7905 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7906 genUnpackBits (result, "dptr", GPOINTER);
7909 size = AOP_SIZE (result);
7914 emitcode ("lcall", "__gptrget");
7915 aopPut (AOP (result), "a", offset++);
7917 emitcode ("inc", "dptr");
7921 freeAsmop (result, NULL, ic, TRUE);
7924 /*-----------------------------------------------------------------*/
7925 /* genPointerGet - generate code for pointer get */
7926 /*-----------------------------------------------------------------*/
7928 genPointerGet (iCode * ic)
7930 operand *left, *result;
7931 sym_link *type, *etype;
7934 D (emitcode (";", "genPointerGet ");
7937 left = IC_LEFT (ic);
7938 result = IC_RESULT (ic);
7940 /* depending on the type of pointer we need to
7941 move it to the correct pointer register */
7942 type = operandType (left);
7943 etype = getSpec (type);
7944 /* if left is of type of pointer then it is simple */
7945 if (IS_PTR (type) && !IS_FUNC (type->next))
7946 p_type = DCL_TYPE (type);
7949 /* we have to go by the storage class */
7950 p_type = PTR_TYPE (SPEC_OCLS (etype));
7953 /* now that we have the pointer type we assign
7954 the pointer values */
7960 genNearPointerGet (left, result, ic);
7964 genPagedPointerGet (left, result, ic);
7968 genFarPointerGet (left, result, ic);
7972 emitcodePointerGet (left, result, ic);
7976 genGenPointerGet (left, result, ic);
7982 /*-----------------------------------------------------------------*/
7983 /* genPackBits - generates code for packed bit storage */
7984 /*-----------------------------------------------------------------*/
7986 genPackBits (sym_link * etype,
7988 char *rname, int p_type)
7996 blen = SPEC_BLEN (etype);
7997 bstr = SPEC_BSTR (etype);
7999 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8002 /* if the bit lenth is less than or */
8003 /* it exactly fits a byte then */
8004 if (SPEC_BLEN (etype) <= 8)
8006 shCount = SPEC_BSTR (etype);
8008 /* shift left acc */
8011 if (SPEC_BLEN (etype) < 8)
8012 { /* if smaller than a byte */
8018 emitcode ("mov", "b,a");
8019 emitcode ("mov", "a,@%s", rname);
8023 emitcode ("mov", "b,a");
8024 emitcode ("movx", "a,@dptr");
8028 emitcode ("push", "b");
8029 emitcode ("push", "acc");
8030 emitcode ("lcall", "__gptrget");
8031 emitcode ("pop", "b");
8035 emitcode ("anl", "a,#0x%02x", (unsigned char)
8036 ((unsigned char) (0xFF << (blen + bstr)) |
8037 (unsigned char) (0xFF >> (8 - bstr))));
8038 emitcode ("orl", "a,b");
8039 if (p_type == GPOINTER)
8040 emitcode ("pop", "b");
8047 emitcode ("mov", "@%s,a", rname);
8051 emitcode ("movx", "@dptr,a");
8055 emitcode ("lcall", "__gptrput");
8060 if (SPEC_BLEN (etype) <= 8)
8063 emitcode ("inc", "%s", rname);
8064 rLen = SPEC_BLEN (etype);
8066 /* now generate for lengths greater than one byte */
8070 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8082 emitcode ("mov", "@%s,a", rname);
8085 emitcode ("mov", "@%s,%s", rname, l);
8090 emitcode ("movx", "@dptr,a");
8095 emitcode ("lcall", "__gptrput");
8098 emitcode ("inc", "%s", rname);
8103 /* last last was not complete */
8106 /* save the byte & read byte */
8110 emitcode ("mov", "b,a");
8111 emitcode ("mov", "a,@%s", rname);
8115 emitcode ("mov", "b,a");
8116 emitcode ("movx", "a,@dptr");
8120 emitcode ("push", "b");
8121 emitcode ("push", "acc");
8122 emitcode ("lcall", "__gptrget");
8123 emitcode ("pop", "b");
8127 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8128 emitcode ("orl", "a,b");
8131 if (p_type == GPOINTER)
8132 emitcode ("pop", "b");
8138 emitcode ("mov", "@%s,a", rname);
8142 emitcode ("movx", "@dptr,a");
8146 emitcode ("lcall", "__gptrput");
8150 /*-----------------------------------------------------------------*/
8151 /* genDataPointerSet - remat pointer to data space */
8152 /*-----------------------------------------------------------------*/
8154 genDataPointerSet (operand * right,
8158 int size, offset = 0;
8159 char *l, buffer[256];
8161 aopOp (right, ic, FALSE, FALSE);
8163 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8164 size = AOP_SIZE (right);
8168 sprintf (buffer, "(%s + %d)", l + 1, offset);
8170 sprintf (buffer, "%s", l + 1);
8171 emitcode ("mov", "%s,%s", buffer,
8172 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8175 freeAsmop (right, NULL, ic, TRUE);
8176 freeAsmop (result, NULL, ic, TRUE);
8179 /*-----------------------------------------------------------------*/
8180 /* genNearPointerSet - emitcode for near pointer put */
8181 /*-----------------------------------------------------------------*/
8183 genNearPointerSet (operand * right,
8190 sym_link *retype, *letype;
8191 sym_link *ptype = operandType (result);
8193 retype = getSpec (operandType (right));
8194 letype = getSpec (ptype);
8196 aopOp (result, ic, FALSE, FALSE);
8198 /* if the result is rematerializable &
8199 in data space & not a bit variable */
8200 if (AOP_TYPE (result) == AOP_IMMD &&
8201 DCL_TYPE (ptype) == POINTER &&
8202 !IS_BITVAR (retype) &&
8203 !IS_BITVAR (letype))
8205 genDataPointerSet (right, result, ic);
8209 /* if the value is already in a pointer register
8210 then don't need anything more */
8211 if (!AOP_INPREG (AOP (result)))
8213 /* otherwise get a free pointer register */
8215 preg = getFreePtr (ic, &aop, FALSE);
8216 emitcode ("mov", "%s,%s",
8218 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8222 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8224 freeAsmop (result, NULL, ic, TRUE);
8225 aopOp (right, ic, FALSE, FALSE);
8227 /* if bitfield then unpack the bits */
8228 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8229 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8232 /* we have can just get the values */
8233 int size = AOP_SIZE (right);
8238 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8242 emitcode ("mov", "@%s,a", rname);
8245 emitcode ("mov", "@%s,%s", rname, l);
8247 emitcode ("inc", "%s", rname);
8252 /* now some housekeeping stuff */
8255 /* we had to allocate for this iCode */
8256 freeAsmop (NULL, aop, ic, TRUE);
8260 /* we did not allocate which means left
8261 already in a pointer register, then
8262 if size > 0 && this could be used again
8263 we have to point it back to where it
8265 if (AOP_SIZE (right) > 1 &&
8266 !OP_SYMBOL (result)->remat &&
8267 (OP_SYMBOL (result)->liveTo > ic->seq ||
8270 int size = AOP_SIZE (right) - 1;
8272 emitcode ("dec", "%s", rname);
8277 freeAsmop (right, NULL, ic, TRUE);
8282 /*-----------------------------------------------------------------*/
8283 /* genPagedPointerSet - emitcode for Paged pointer put */
8284 /*-----------------------------------------------------------------*/
8286 genPagedPointerSet (operand * right,
8293 sym_link *retype, *letype;
8295 retype = getSpec (operandType (right));
8296 letype = getSpec (operandType (result));
8298 aopOp (result, ic, FALSE, FALSE);
8300 /* if the value is already in a pointer register
8301 then don't need anything more */
8302 if (!AOP_INPREG (AOP (result)))
8304 /* otherwise get a free pointer register */
8306 preg = getFreePtr (ic, &aop, FALSE);
8307 emitcode ("mov", "%s,%s",
8309 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8313 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8315 freeAsmop (result, NULL, ic, TRUE);
8316 aopOp (right, ic, FALSE, FALSE);
8318 /* if bitfield then unpack the bits */
8319 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8320 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8323 /* we have can just get the values */
8324 int size = AOP_SIZE (right);
8329 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8332 emitcode ("movx", "@%s,a", rname);
8335 emitcode ("inc", "%s", rname);
8341 /* now some housekeeping stuff */
8344 /* we had to allocate for this iCode */
8345 freeAsmop (NULL, aop, ic, TRUE);
8349 /* we did not allocate which means left
8350 already in a pointer register, then
8351 if size > 0 && this could be used again
8352 we have to point it back to where it
8354 if (AOP_SIZE (right) > 1 &&
8355 !OP_SYMBOL (result)->remat &&
8356 (OP_SYMBOL (result)->liveTo > ic->seq ||
8359 int size = AOP_SIZE (right) - 1;
8361 emitcode ("dec", "%s", rname);
8366 freeAsmop (right, NULL, ic, TRUE);
8371 /*-----------------------------------------------------------------*/
8372 /* genFarPointerSet - set value from far space */
8373 /*-----------------------------------------------------------------*/
8375 genFarPointerSet (operand * right,
8376 operand * result, iCode * ic)
8379 sym_link *retype = getSpec (operandType (right));
8380 sym_link *letype = getSpec (operandType (result));
8382 aopOp (result, ic, FALSE, FALSE);
8384 /* if the operand is already in dptr
8385 then we do nothing else we move the value to dptr */
8386 if (AOP_TYPE (result) != AOP_STR)
8388 /* if this is remateriazable */
8389 if (AOP_TYPE (result) == AOP_IMMD)
8390 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8393 /* we need to get it byte by byte */
8394 _startLazyDPSEvaluation ();
8395 if (AOP_TYPE (result) != AOP_DPTR)
8397 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8398 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8399 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8403 /* We need to generate a load to DPTR indirect through DPTR. */
8404 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8406 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8407 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8408 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8409 emitcode ("pop", "dph");
8410 emitcode ("pop", "dpl");
8412 _endLazyDPSEvaluation ();
8415 /* so dptr know contains the address */
8416 freeAsmop (result, NULL, ic, TRUE);
8417 aopOp (right, ic, FALSE, TRUE);
8419 /* if bit then unpack */
8420 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8421 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8424 size = AOP_SIZE (right);
8427 _startLazyDPSEvaluation ();
8430 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8436 emitcode ("movx", "@dptr,a");
8438 emitcode ("inc", "dptr");
8440 _endLazyDPSEvaluation ();
8443 freeAsmop (right, NULL, ic, TRUE);
8446 /*-----------------------------------------------------------------*/
8447 /* genGenPointerSet - set value from generic pointer space */
8448 /*-----------------------------------------------------------------*/
8450 genGenPointerSet (operand * right,
8451 operand * result, iCode * ic)
8454 sym_link *retype = getSpec (operandType (right));
8455 sym_link *letype = getSpec (operandType (result));
8457 aopOp (result, ic, FALSE, TRUE);
8459 /* if the operand is already in dptr
8460 then we do nothing else we move the value to dptr */
8461 if (AOP_TYPE (result) != AOP_STR)
8463 _startLazyDPSEvaluation ();
8464 /* if this is remateriazable */
8465 if (AOP_TYPE (result) == AOP_IMMD)
8467 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8468 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8471 { /* we need to get it byte by byte */
8472 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8473 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8474 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8475 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8477 _endLazyDPSEvaluation ();
8479 /* so dptr know contains the address */
8480 freeAsmop (result, NULL, ic, TRUE);
8481 aopOp (right, ic, FALSE, TRUE);
8483 /* if bit then unpack */
8484 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8485 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8488 size = AOP_SIZE (right);
8491 _startLazyDPSEvaluation ();
8494 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8500 emitcode ("lcall", "__gptrput");
8502 emitcode ("inc", "dptr");
8504 _endLazyDPSEvaluation ();
8507 freeAsmop (right, NULL, ic, TRUE);
8510 /*-----------------------------------------------------------------*/
8511 /* genPointerSet - stores the value into a pointer location */
8512 /*-----------------------------------------------------------------*/
8514 genPointerSet (iCode * ic)
8516 operand *right, *result;
8517 sym_link *type, *etype;
8520 D (emitcode (";", "genPointerSet ");
8523 right = IC_RIGHT (ic);
8524 result = IC_RESULT (ic);
8526 /* depending on the type of pointer we need to
8527 move it to the correct pointer register */
8528 type = operandType (result);
8529 etype = getSpec (type);
8530 /* if left is of type of pointer then it is simple */
8531 if (IS_PTR (type) && !IS_FUNC (type->next))
8533 p_type = DCL_TYPE (type);
8537 /* we have to go by the storage class */
8538 p_type = PTR_TYPE (SPEC_OCLS (etype));
8541 /* now that we have the pointer type we assign
8542 the pointer values */
8548 genNearPointerSet (right, result, ic);
8552 genPagedPointerSet (right, result, ic);
8556 genFarPointerSet (right, result, ic);
8560 genGenPointerSet (right, result, ic);
8566 /*-----------------------------------------------------------------*/
8567 /* genIfx - generate code for Ifx statement */
8568 /*-----------------------------------------------------------------*/
8570 genIfx (iCode * ic, iCode * popIc)
8572 operand *cond = IC_COND (ic);
8575 D (emitcode (";", "genIfx ");
8578 aopOp (cond, ic, FALSE, FALSE);
8580 /* get the value into acc */
8581 if (AOP_TYPE (cond) != AOP_CRY)
8585 /* the result is now in the accumulator */
8586 freeAsmop (cond, NULL, ic, TRUE);
8588 /* if there was something to be popped then do it */
8592 /* if the condition is a bit variable */
8593 if (isbit && IS_ITEMP (cond) &&
8595 genIfxJump (ic, SPIL_LOC (cond)->rname);
8596 else if (isbit && !IS_ITEMP (cond))
8597 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8599 genIfxJump (ic, "a");
8604 /*-----------------------------------------------------------------*/
8605 /* genAddrOf - generates code for address of */
8606 /*-----------------------------------------------------------------*/
8608 genAddrOf (iCode * ic)
8610 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8613 D (emitcode (";", "genAddrOf ");
8616 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8618 /* if the operand is on the stack then we
8619 need to get the stack offset of this
8623 /* if it has an offset then we need to compute
8627 emitcode ("mov", "a,_bp");
8628 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8629 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8633 /* we can just move _bp */
8634 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8636 /* fill the result with zero */
8637 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8640 if (options.stack10bit && size < (FPTRSIZE - 1))
8643 "*** warning: pointer to stack var truncated.\n");
8650 if (options.stack10bit && offset == 2)
8652 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8656 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8663 /* object not on stack then we need the name */
8664 size = AOP_SIZE (IC_RESULT (ic));
8669 char s[SDCC_NAME_MAX];
8671 sprintf (s, "#(%s >> %d)",
8675 sprintf (s, "#%s", sym->rname);
8676 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8680 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8684 /*-----------------------------------------------------------------*/
8685 /* genFarFarAssign - assignment when both are in far space */
8686 /*-----------------------------------------------------------------*/
8688 genFarFarAssign (operand * result, operand * right, iCode * ic)
8690 int size = AOP_SIZE (right);
8696 /* This is a net loss for size == 1, but a big gain
8699 D (emitcode (";", "genFarFarAssign (improved)");
8702 aopOp (result, ic, TRUE, TRUE);
8704 _startLazyDPSEvaluation ();
8707 aopPut (AOP (result),
8708 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8711 _endLazyDPSEvaluation ();
8712 freeAsmop (result, NULL, ic, FALSE);
8713 freeAsmop (right, NULL, ic, FALSE);
8717 D (emitcode (";", "genFarFarAssign ");
8720 /* first push the right side on to the stack */
8721 _startLazyDPSEvaluation ();
8724 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8726 emitcode ("push", "acc");
8729 freeAsmop (right, NULL, ic, FALSE);
8730 /* now assign DPTR to result */
8731 aopOp (result, ic, FALSE, FALSE);
8732 size = AOP_SIZE (result);
8735 emitcode ("pop", "acc");
8736 aopPut (AOP (result), "a", --offset);
8738 freeAsmop (result, NULL, ic, FALSE);
8739 _endLazyDPSEvaluation ();
8743 /*-----------------------------------------------------------------*/
8744 /* genAssign - generate code for assignment */
8745 /*-----------------------------------------------------------------*/
8747 genAssign (iCode * ic)
8749 operand *result, *right;
8751 unsigned long lit = 0L;
8753 D (emitcode (";", "genAssign ");
8756 result = IC_RESULT (ic);
8757 right = IC_RIGHT (ic);
8759 /* if they are the same */
8760 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8763 aopOp (right, ic, FALSE, FALSE);
8765 emitcode (";", "genAssign: resultIsFar = %s",
8766 isOperandInFarSpace (result) ?
8769 /* special case both in far space */
8770 if ((AOP_TYPE (right) == AOP_DPTR ||
8771 AOP_TYPE (right) == AOP_DPTR2) &&
8772 /* IS_TRUE_SYMOP(result) && */
8773 isOperandInFarSpace (result))
8775 genFarFarAssign (result, right, ic);
8779 aopOp (result, ic, TRUE, FALSE);
8781 /* if they are the same registers */
8782 if (sameRegs (AOP (right), AOP (result)))
8785 /* if the result is a bit */
8786 if (AOP_TYPE (result) == AOP_CRY)
8789 /* if the right size is a literal then
8790 we know what the value is */
8791 if (AOP_TYPE (right) == AOP_LIT)
8793 if (((int) operandLitValue (right)))
8794 aopPut (AOP (result), one, 0);
8796 aopPut (AOP (result), zero, 0);
8800 /* the right is also a bit variable */
8801 if (AOP_TYPE (right) == AOP_CRY)
8803 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8804 aopPut (AOP (result), "c", 0);
8810 aopPut (AOP (result), "a", 0);
8814 /* bit variables done */
8816 size = AOP_SIZE (result);
8818 if (AOP_TYPE (right) == AOP_LIT)
8819 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8822 (AOP_TYPE (result) != AOP_REG) &&
8823 (AOP_TYPE (right) == AOP_LIT) &&
8824 !IS_FLOAT (operandType (right)))
8826 D (emitcode (";", "Kevin's better literal load code");
8828 _startLazyDPSEvaluation ();
8829 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8831 aopPut (AOP (result),
8832 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8837 /* And now fill the rest with zeros. */
8840 emitcode ("clr", "a");
8844 aopPut (AOP (result), "a", offset++);
8846 _endLazyDPSEvaluation ();
8850 _startLazyDPSEvaluation ();
8853 aopPut (AOP (result),
8854 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8858 _endLazyDPSEvaluation ();
8862 freeAsmop (right, NULL, ic, FALSE);
8863 freeAsmop (result, NULL, ic, TRUE);
8866 /*-----------------------------------------------------------------*/
8867 /* genJumpTab - generates code for jump table */
8868 /*-----------------------------------------------------------------*/
8870 genJumpTab (iCode * ic)
8875 D (emitcode (";", "genJumpTab ");
8878 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8879 /* get the condition into accumulator */
8880 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8882 /* multiply by four! */
8883 emitcode ("add", "a,acc");
8884 emitcode ("add", "a,acc");
8885 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8887 jtab = newiTempLabel (NULL);
8888 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8889 emitcode ("jmp", "@a+dptr");
8890 emitcode ("", "%05d$:", jtab->key + 100);
8891 /* now generate the jump labels */
8892 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8893 jtab = setNextItem (IC_JTLABELS (ic)))
8894 emitcode ("ljmp", "%05d$", jtab->key + 100);
8898 /*-----------------------------------------------------------------*/
8899 /* genCast - gen code for casting */
8900 /*-----------------------------------------------------------------*/
8902 genCast (iCode * ic)
8904 operand *result = IC_RESULT (ic);
8905 sym_link *ctype = operandType (IC_LEFT (ic));
8906 sym_link *rtype = operandType (IC_RIGHT (ic));
8907 operand *right = IC_RIGHT (ic);
8910 D (emitcode (";", "genCast ");
8913 /* if they are equivalent then do nothing */
8914 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8917 aopOp (right, ic, FALSE, FALSE);
8918 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8920 /* if the result is a bit */
8921 if (AOP_TYPE (result) == AOP_CRY)
8923 /* if the right size is a literal then
8924 we know what the value is */
8925 if (AOP_TYPE (right) == AOP_LIT)
8927 if (((int) operandLitValue (right)))
8928 aopPut (AOP (result), one, 0);
8930 aopPut (AOP (result), zero, 0);
8935 /* the right is also a bit variable */
8936 if (AOP_TYPE (right) == AOP_CRY)
8938 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8939 aopPut (AOP (result), "c", 0);
8945 aopPut (AOP (result), "a", 0);
8949 /* if they are the same size : or less */
8950 if (AOP_SIZE (result) <= AOP_SIZE (right))
8953 /* if they are in the same place */
8954 if (sameRegs (AOP (right), AOP (result)))
8957 /* if they in different places then copy */
8958 size = AOP_SIZE (result);
8960 _startLazyDPSEvaluation ();
8963 aopPut (AOP (result),
8964 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8968 _endLazyDPSEvaluation ();
8973 /* if the result is of type pointer */
8978 sym_link *type = operandType (right);
8980 /* pointer to generic pointer */
8981 if (IS_GENPTR (ctype))
8987 p_type = DCL_TYPE (type);
8991 #if OLD_CAST_BEHAVIOR
8992 /* KV: we are converting a non-pointer type to
8993 * a generic pointer. This (ifdef'd out) code
8994 * says that the resulting generic pointer
8995 * should have the same class as the storage
8996 * location of the non-pointer variable.
8998 * For example, converting an int (which happens
8999 * to be stored in DATA space) to a pointer results
9000 * in a DATA generic pointer; if the original int
9001 * in XDATA space, so will be the resulting pointer.
9003 * I don't like that behavior, and thus this change:
9004 * all such conversions will be forced to XDATA and
9005 * throw a warning. If you want some non-XDATA
9006 * type, or you want to suppress the warning, you
9007 * must go through an intermediate cast, like so:
9009 * char _generic *gp = (char _xdata *)(intVar);
9011 sym_link *etype = getSpec (type);
9013 /* we have to go by the storage class */
9014 if (SPEC_OCLS (etype) != generic)
9016 p_type = PTR_TYPE (SPEC_OCLS (etype));
9021 /* Converting unknown class (i.e. register variable)
9022 * to generic pointer. This is not good, but
9023 * we'll make a guess (and throw a warning).
9026 werror (W_INT_TO_GEN_PTR_CAST);
9030 /* the first two bytes are known */
9031 size = GPTRSIZE - 1;
9033 _startLazyDPSEvaluation ();
9036 aopPut (AOP (result),
9037 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9041 _endLazyDPSEvaluation ();
9043 /* the last byte depending on type */
9061 /* this should never happen */
9062 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9063 "got unknown pointer type");
9066 aopPut (AOP (result), l, GPTRSIZE - 1);
9070 /* just copy the pointers */
9071 size = AOP_SIZE (result);
9073 _startLazyDPSEvaluation ();
9076 aopPut (AOP (result),
9077 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9081 _endLazyDPSEvaluation ();
9085 /* so we now know that the size of destination is greater
9086 than the size of the source */
9087 /* we move to result for the size of source */
9088 size = AOP_SIZE (right);
9090 _startLazyDPSEvaluation ();
9093 aopPut (AOP (result),
9094 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9098 _endLazyDPSEvaluation ();
9100 /* now depending on the sign of the source && destination */
9101 size = AOP_SIZE (result) - AOP_SIZE (right);
9102 /* if unsigned or not an integral type */
9103 /* also, if the source is a bit, we don't need to sign extend, because
9104 * it can't possibly have set the sign bit.
9106 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9110 aopPut (AOP (result), zero, offset++);
9115 /* we need to extend the sign :{ */
9116 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9117 FALSE, FALSE, TRUE);
9119 emitcode ("rlc", "a");
9120 emitcode ("subb", "a,acc");
9122 aopPut (AOP (result), "a", offset++);
9125 /* we are done hurray !!!! */
9128 freeAsmop (right, NULL, ic, TRUE);
9129 freeAsmop (result, NULL, ic, TRUE);
9133 /*-----------------------------------------------------------------*/
9134 /* genDjnz - generate decrement & jump if not zero instrucion */
9135 /*-----------------------------------------------------------------*/
9137 genDjnz (iCode * ic, iCode * ifx)
9143 /* if the if condition has a false label
9144 then we cannot save */
9148 /* if the minus is not of the form
9150 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9151 !IS_OP_LITERAL (IC_RIGHT (ic)))
9154 if (operandLitValue (IC_RIGHT (ic)) != 1)
9157 /* if the size of this greater than one then no
9159 if (getSize (operandType (IC_RESULT (ic))) > 1)
9162 /* otherwise we can save BIG */
9163 lbl = newiTempLabel (NULL);
9164 lbl1 = newiTempLabel (NULL);
9166 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9168 if (IS_AOP_PREG (IC_RESULT (ic)))
9170 emitcode ("dec", "%s",
9171 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9172 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9173 emitcode ("jnz", "%05d$", lbl->key + 100);
9177 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9180 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9181 emitcode ("", "%05d$:", lbl->key + 100);
9182 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9183 emitcode ("", "%05d$:", lbl1->key + 100);
9185 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9190 /*-----------------------------------------------------------------*/
9191 /* genReceive - generate code for a receive iCode */
9192 /*-----------------------------------------------------------------*/
9194 genReceive (iCode * ic)
9197 D (emitcode (";", "genReceive ");
9200 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9201 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9202 IS_TRUE_SYMOP (IC_RESULT (ic))))
9204 int size = getSize (operandType (IC_RESULT (ic)));
9205 int offset = fReturnSize_390 - size;
9208 emitcode ("push", "%s", (strcmp (fReturn[fReturnSize_390 - offset - 1], "a") ?
9209 fReturn[fReturnSize_390 - offset - 1] : "acc"));
9212 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9213 size = AOP_SIZE (IC_RESULT (ic));
9217 emitcode ("pop", "acc");
9218 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9225 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9227 assignResultValue (IC_RESULT (ic));
9230 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9233 /*-----------------------------------------------------------------*/
9234 /* gen390Code - generate code for Dallas 390 based controllers */
9235 /*-----------------------------------------------------------------*/
9237 gen390Code (iCode * lic)
9242 lineHead = lineCurr = NULL;
9246 /* print the allocation information */
9248 printAllocInfo (currFunc, codeOutFile);
9250 /* if debug information required */
9251 if (options.debug && currFunc)
9253 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9255 if (IS_STATIC (currFunc->etype))
9256 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9258 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9261 /* stack pointer name */
9262 if (options.useXstack)
9268 for (ic = lic; ic; ic = ic->next)
9271 if (cln != ic->lineno)
9276 emitcode ("", "C$%s$%d$%d$%d ==.",
9277 FileBaseName (ic->filename), ic->lineno,
9278 ic->level, ic->block);
9281 emitcode (";", "%s %d", ic->filename, ic->lineno);
9284 /* if the result is marked as
9285 spilt and rematerializable or code for
9286 this has already been generated then
9288 if (resultRemat (ic) || ic->generated)
9291 /* depending on the operation */
9311 /* IPOP happens only when trying to restore a
9312 spilt live range, if there is an ifx statement
9313 following this pop then the if statement might
9314 be using some of the registers being popped which
9315 would destory the contents of the register so
9316 we need to check for this condition and handle it */
9318 ic->next->op == IFX &&
9319 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9320 genIfx (ic->next, ic);
9338 genEndFunction (ic);
9358 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9375 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9379 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9386 /* note these two are xlated by algebraic equivalence
9387 during parsing SDCC.y */
9388 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9389 "got '>=' or '<=' shouldn't have come here");
9393 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9405 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9409 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9413 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9440 case GET_VALUE_AT_ADDRESS:
9445 if (POINTER_SET (ic))
9472 addSet (&_G.sendSet, ic);
9477 /* piCode(ic,stdout); */
9483 /* now we are ready to call the
9484 peep hole optimizer */
9485 if (!options.nopeep)
9486 peepHole (&lineHead);
9488 /* now do the actual printing */
9489 printLine (lineHead, codeOutFile);