1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
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!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 char *aopLiteral (value * val, int offset);
53 /* this is the down and dirty file with all kinds of
54 kludgy & hacky stuff. This is what it is all about
55 CODE GENERATION for a specific MCU . some of the
56 routines may be reusable, will have to see */
58 static char *zero = "#0x00";
59 static char *one = "#0x01";
64 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
65 static char *fReturn[] =
66 {"dpl", "dph", "dpx", "b", "a"};
67 static char *accUse[] =
70 static short rbank = -1;
84 static void saverbank (int, iCode *, bool);
86 #define RESULTONSTACK(x) \
87 (IC_RESULT(x) && IC_RESULT(x)->aop && \
88 IC_RESULT(x)->aop->type == AOP_STK )
90 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
91 #define MOVA(x) { char *_mova_tmp = strdup(x); \
92 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
94 emitcode("mov","a,%s",_mova_tmp); \
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG "ap"
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
120 /*-----------------------------------------------------------------*/
121 /* emitcode - writes the code into a file : for now it is simple */
122 /*-----------------------------------------------------------------*/
124 emitcode (char *inst, char *fmt,...)
127 char lb[MAX_INLINEASM];
135 sprintf (lb, "%s\t", inst);
137 sprintf (lb, "%s", inst);
138 vsprintf (lb + (strlen (lb)), fmt, ap);
141 vsprintf (lb, fmt, ap);
143 while (isspace (*lbp))
147 lineCurr = (lineCurr ?
148 connectLine (lineCurr, newLineNode (lb)) :
149 (lineHead = newLineNode (lb)));
150 lineCurr->isInline = _G.inLine;
151 lineCurr->isDebug = _G.debugLine;
155 /*-----------------------------------------------------------------*/
156 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
157 /*-----------------------------------------------------------------*/
159 getFreePtr (iCode * ic, asmop ** aopp, bool result)
161 bool r0iu = FALSE, r1iu = FALSE;
162 bool r0ou = FALSE, r1ou = FALSE;
164 /* the logic: if r0 & r1 used in the instruction
165 then we are in trouble otherwise */
167 /* first check if r0 & r1 are used by this
168 instruction, in which case we are in trouble */
169 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
170 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
175 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
176 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
178 /* if no usage of r0 then return it */
181 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
182 (*aopp)->type = AOP_R0;
184 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
187 /* if no usage of r1 then return it */
190 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
191 (*aopp)->type = AOP_R1;
193 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
196 /* now we know they both have usage */
197 /* if r0 not used in this instruction */
200 /* push it if not already pushed */
203 emitcode ("push", "%s",
204 ds390_regWithIdx (R0_IDX)->dname);
208 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
209 (*aopp)->type = AOP_R0;
211 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
214 /* if r1 not used then */
218 /* push it if not already pushed */
221 emitcode ("push", "%s",
222 ds390_regWithIdx (R1_IDX)->dname);
226 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
227 (*aopp)->type = AOP_R1;
228 return ds390_regWithIdx (R1_IDX);
232 /* I said end of world but not quite end of world yet */
233 /* if this is a result then we can push it on the stack */
236 (*aopp)->type = AOP_STK;
240 /* other wise this is true end of the world */
241 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
242 "getFreePtr should never reach here");
246 /*-----------------------------------------------------------------*/
247 /* newAsmop - creates a new asmOp */
248 /*-----------------------------------------------------------------*/
250 newAsmop (short type)
254 aop = Safe_calloc (1, sizeof (asmop));
259 static int _currentDPS; /* Current processor DPS. */
260 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
261 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
263 /*-----------------------------------------------------------------*/
264 /* genSetDPTR: generate code to select which DPTR is in use (zero */
265 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
266 /* alternate DPTR (DPL1/DPH1/DPX1). */
267 /*-----------------------------------------------------------------*/
272 /* If we are doing lazy evaluation, simply note the desired
273 * change, but don't emit any code yet.
283 emitcode ("mov", "dps, #0x00");
287 emitcode ("mov", "dps, #0x01");
291 /*-----------------------------------------------------------------*/
292 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
294 /* Any code that operates on DPTR (NB: not on the individual */
295 /* components, like DPH) *must* call _flushLazyDPS() before using */
296 /* DPTR within a lazy DPS evaluation block. */
298 /* Note that aopPut and aopGet already contain the proper calls to */
299 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
300 /* DPS evaluation block. */
302 /* Also, _flushLazyDPS must be called before any flow control */
303 /* operations that could potentially branch out of the block. */
305 /* Lazy DPS evaluation is simply an optimization (though an */
306 /* important one), so if in doubt, leave it out. */
307 /*-----------------------------------------------------------------*/
309 _startLazyDPSEvaluation (void)
316 /*-----------------------------------------------------------------*/
317 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
318 /* desired one. Call before using DPTR within a lazy DPS evaluation */
320 /*-----------------------------------------------------------------*/
330 if (_desiredDPS != _currentDPS)
334 emitcode ("inc", "dps");
338 emitcode ("dec", "dps");
340 _currentDPS = _desiredDPS;
344 /*-----------------------------------------------------------------*/
345 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
347 /* Forces us back to the safe state (standard DPTR selected). */
348 /*-----------------------------------------------------------------*/
350 _endLazyDPSEvaluation (void)
364 /*-----------------------------------------------------------------*/
365 /* pointerCode - returns the code for a pointer type */
366 /*-----------------------------------------------------------------*/
368 pointerCode (sym_link * etype)
371 return PTR_TYPE (SPEC_OCLS (etype));
375 /*-----------------------------------------------------------------*/
376 /* aopForSym - for a true symbol */
377 /*-----------------------------------------------------------------*/
379 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
382 memmap *space = SPEC_OCLS (sym->etype);
384 /* if already has one */
388 /* assign depending on the storage class */
389 /* if it is on the stack or indirectly addressable */
390 /* space we need to assign either r0 or r1 to it */
391 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
393 sym->aop = aop = newAsmop (0);
394 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
395 aop->size = getSize (sym->type);
397 /* now assign the address of the variable to
398 the pointer register */
399 if (aop->type != AOP_STK)
405 emitcode ("push", "acc");
407 emitcode ("mov", "a,_bp");
408 emitcode ("add", "a,#0x%02x",
410 ((char) (sym->stack - _G.nRegsSaved)) :
411 ((char) sym->stack)) & 0xff);
412 emitcode ("mov", "%s,a",
413 aop->aopu.aop_ptr->name);
416 emitcode ("pop", "acc");
419 emitcode ("mov", "%s,#%s",
420 aop->aopu.aop_ptr->name,
422 aop->paged = space->paged;
425 aop->aopu.aop_stk = sym->stack;
429 if (sym->onStack && options.stack10bit)
431 /* It's on the 10 bit stack, which is located in
436 emitcode ("push", "acc");
438 emitcode ("mov", "a,_bp");
439 emitcode ("add", "a,#0x%02x",
441 ((char) (sym->stack - _G.nRegsSaved)) :
442 ((char) sym->stack)) & 0xff);
447 emitcode ("mov", "dpx1,#0x40");
448 emitcode ("mov", "dph1,#0x00");
449 emitcode ("mov", "dpl1, a");
454 emitcode ("mov", "dpx,#0x40");
455 emitcode ("mov", "dph,#0x00");
456 emitcode ("mov", "dpl, a");
460 emitcode ("pop", "acc");
462 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
463 aop->size = getSize (sym->type);
467 /* if in bit space */
468 if (IN_BITSPACE (space))
470 sym->aop = aop = newAsmop (AOP_CRY);
471 aop->aopu.aop_dir = sym->rname;
472 aop->size = getSize (sym->type);
475 /* if it is in direct space */
476 if (IN_DIRSPACE (space))
478 sym->aop = aop = newAsmop (AOP_DIR);
479 aop->aopu.aop_dir = sym->rname;
480 aop->size = getSize (sym->type);
484 /* special case for a function */
485 if (IS_FUNC (sym->type))
487 sym->aop = aop = newAsmop (AOP_IMMD);
488 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
489 strcpy (aop->aopu.aop_immd, sym->rname);
490 aop->size = FPTRSIZE;
494 /* only remaining is far space */
495 /* in which case DPTR gets the address */
496 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
501 emitcode ("mov", "dptr,#%s", sym->rname);
506 emitcode ("mov", "dptr,#%s", sym->rname);
508 aop->size = getSize (sym->type);
510 /* if it is in code space */
511 if (IN_CODESPACE (space))
517 /*-----------------------------------------------------------------*/
518 /* aopForRemat - rematerialzes an object */
519 /*-----------------------------------------------------------------*/
521 aopForRemat (symbol * sym)
523 iCode *ic = sym->rematiCode;
524 asmop *aop = newAsmop (AOP_IMMD);
531 val += (int) operandLitValue (IC_RIGHT (ic));
532 else if (ic->op == '-')
533 val -= (int) operandLitValue (IC_RIGHT (ic));
537 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
541 sprintf (buffer, "(%s %c 0x%04x)",
542 OP_SYMBOL (IC_LEFT (ic))->rname,
543 val >= 0 ? '+' : '-',
546 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
548 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
549 strcpy (aop->aopu.aop_immd, buffer);
553 /*-----------------------------------------------------------------*/
554 /* regsInCommon - two operands have some registers in common */
555 /*-----------------------------------------------------------------*/
557 regsInCommon (operand * op1, operand * op2)
562 /* if they have registers in common */
563 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
566 sym1 = OP_SYMBOL (op1);
567 sym2 = OP_SYMBOL (op2);
569 if (sym1->nRegs == 0 || sym2->nRegs == 0)
572 for (i = 0; i < sym1->nRegs; i++)
578 for (j = 0; j < sym2->nRegs; j++)
583 if (sym2->regs[j] == sym1->regs[i])
591 /*-----------------------------------------------------------------*/
592 /* operandsEqu - equivalent */
593 /*-----------------------------------------------------------------*/
595 operandsEqu (operand * op1, operand * op2)
599 /* if they not symbols */
600 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
603 sym1 = OP_SYMBOL (op1);
604 sym2 = OP_SYMBOL (op2);
606 /* if both are itemps & one is spilt
607 and the other is not then false */
608 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
609 sym1->isspilt != sym2->isspilt)
612 /* if they are the same */
616 if (strcmp (sym1->rname, sym2->rname) == 0)
620 /* if left is a tmp & right is not */
621 if (IS_ITEMP (op1) &&
624 (sym1->usl.spillLoc == sym2))
627 if (IS_ITEMP (op2) &&
631 (sym2->usl.spillLoc == sym1))
637 /*-----------------------------------------------------------------*/
638 /* sameRegs - two asmops have the same registers */
639 /*-----------------------------------------------------------------*/
641 sameRegs (asmop * aop1, asmop * aop2)
647 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
654 if (aop1->type != AOP_REG ||
655 aop2->type != AOP_REG)
658 if (aop1->size != aop2->size)
661 for (i = 0; i < aop1->size; i++)
662 if (aop1->aopu.aop_reg[i] !=
663 aop2->aopu.aop_reg[i])
669 /*-----------------------------------------------------------------*/
670 /* aopOp - allocates an asmop for an operand : */
671 /*-----------------------------------------------------------------*/
673 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
682 /* if this a literal */
683 if (IS_OP_LITERAL (op))
685 op->aop = aop = newAsmop (AOP_LIT);
686 aop->aopu.aop_lit = op->operand.valOperand;
687 aop->size = getSize (operandType (op));
691 /* if already has a asmop then continue */
695 /* if the underlying symbol has a aop */
696 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
698 op->aop = OP_SYMBOL (op)->aop;
702 /* if this is a true symbol */
703 if (IS_TRUE_SYMOP (op))
705 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
709 /* this is a temporary : this has
715 e) can be a return use only */
717 sym = OP_SYMBOL (op);
720 /* if the type is a conditional */
721 if (sym->regType == REG_CND)
723 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
728 /* if it is spilt then two situations
730 b) has a spill location */
731 if (sym->isspilt || sym->nRegs == 0)
734 /* rematerialize it NOW */
737 sym->aop = op->aop = aop =
739 aop->size = getSize (sym->type);
746 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
747 aop->size = getSize (sym->type);
748 for (i = 0; i < 2; i++)
749 aop->aopu.aop_str[i] = accUse[i];
759 /* a AOP_STR uses DPTR, but DPTR is already in use;
762 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
765 aop = op->aop = sym->aop = newAsmop (AOP_STR);
766 aop->size = getSize (sym->type);
767 for (i = 0; i < (int) fReturnSizeDS390; i++)
768 aop->aopu.aop_str[i] = fReturn[i];
772 /* else spill location */
773 sym->aop = op->aop = aop =
774 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
775 aop->size = getSize (sym->type);
779 /* must be in a register */
780 sym->aop = op->aop = aop = newAsmop (AOP_REG);
781 aop->size = sym->nRegs;
782 for (i = 0; i < sym->nRegs; i++)
783 aop->aopu.aop_reg[i] = sym->regs[i];
786 /*-----------------------------------------------------------------*/
787 /* freeAsmop - free up the asmop given to an operand */
788 /*----------------------------------------------------------------*/
790 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
807 /* depending on the asmop type only three cases need work AOP_RO
808 , AOP_R1 && AOP_STK */
816 emitcode ("pop", "ar0");
820 bitVectUnSetBit (ic->rUsed, R0_IDX);
828 emitcode ("pop", "ar1");
832 bitVectUnSetBit (ic->rUsed, R1_IDX);
838 int stk = aop->aopu.aop_stk + aop->size;
839 bitVectUnSetBit (ic->rUsed, R0_IDX);
840 bitVectUnSetBit (ic->rUsed, R1_IDX);
842 getFreePtr (ic, &aop, FALSE);
844 if (options.stack10bit)
846 /* I'm not sure what to do here yet... */
849 "*** Warning: probably generating bad code for "
850 "10 bit stack mode.\n");
855 emitcode ("mov", "a,_bp");
856 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
857 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
861 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
866 emitcode ("pop", "acc");
867 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
870 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
873 freeAsmop (op, NULL, ic, TRUE);
876 emitcode ("pop", "ar0");
882 emitcode ("pop", "ar1");
889 /* all other cases just dealloc */
895 OP_SYMBOL (op)->aop = NULL;
896 /* if the symbol has a spill */
898 SPIL_LOC (op)->aop = NULL;
903 /*------------------------------------------------------------------*/
904 /* aopGet - for fetching value of the aop */
906 /* Set canClobberACC if you are sure it is OK to clobber the value */
907 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
908 /* just less efficient. */
909 /*------------------------------------------------------------------*/
921 /* offset is greater than
923 if (offset > (aop->size - 1) &&
924 aop->type != AOP_LIT)
927 /* depending on type */
933 /* if we need to increment it */
934 while (offset > aop->coff)
936 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
940 while (offset < aop->coff)
942 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
949 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
950 return (dname ? "acc" : "a");
952 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
953 rs = Safe_calloc (1, strlen (s) + 1);
960 if (aop->type == AOP_DPTR2)
965 emitcode ("xch", "a, %s", DP2_RESULT_REG);
971 while (offset > aop->coff)
973 emitcode ("inc", "dptr");
977 while (offset < aop->coff)
979 emitcode ("lcall", "__decdptr");
986 emitcode ("clr", "a");
987 emitcode ("movc", "a,@a+dptr");
991 emitcode ("movx", "a,@dptr");
994 if (aop->type == AOP_DPTR2)
999 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1000 return DP2_RESULT_REG;
1003 return (dname ? "acc" : "a");
1007 sprintf (s, "#%s", aop->aopu.aop_immd);
1009 sprintf (s, "#(%s >> %d)",
1014 aop->aopu.aop_immd);
1015 rs = Safe_calloc (1, strlen (s) + 1);
1021 sprintf (s, "(%s + %d)",
1025 sprintf (s, "%s", aop->aopu.aop_dir);
1026 rs = Safe_calloc (1, strlen (s) + 1);
1032 return aop->aopu.aop_reg[offset]->dname;
1034 return aop->aopu.aop_reg[offset]->name;
1037 emitcode ("clr", "a");
1038 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1039 emitcode ("rlc", "a");
1040 return (dname ? "acc" : "a");
1043 if (!offset && dname)
1045 return aop->aopu.aop_str[offset];
1048 return aopLiteral (aop->aopu.aop_lit, offset);
1052 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1056 return aop->aopu.aop_str[offset];
1060 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1061 "aopget got unsupported aop->type");
1064 /*-----------------------------------------------------------------*/
1065 /* aopPut - puts a string for a aop */
1066 /*-----------------------------------------------------------------*/
1068 aopPut (asmop * aop, char *s, int offset)
1072 if (aop->size && offset > (aop->size - 1))
1074 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1075 "aopPut got offset > aop->size");
1079 /* will assign value to value */
1080 /* depending on where it is ofcourse */
1085 sprintf (d, "(%s + %d)",
1086 aop->aopu.aop_dir, offset);
1088 sprintf (d, "%s", aop->aopu.aop_dir);
1091 emitcode ("mov", "%s,%s", d, s);
1096 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1097 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1100 strcmp (s, "r0") == 0 ||
1101 strcmp (s, "r1") == 0 ||
1102 strcmp (s, "r2") == 0 ||
1103 strcmp (s, "r3") == 0 ||
1104 strcmp (s, "r4") == 0 ||
1105 strcmp (s, "r5") == 0 ||
1106 strcmp (s, "r6") == 0 ||
1107 strcmp (s, "r7") == 0)
1108 emitcode ("mov", "%s,%s",
1109 aop->aopu.aop_reg[offset]->dname, s);
1111 emitcode ("mov", "%s,%s",
1112 aop->aopu.aop_reg[offset]->name, s);
1119 if (aop->type == AOP_DPTR2)
1127 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1128 "aopPut writting to code space");
1132 while (offset > aop->coff)
1135 emitcode ("inc", "dptr");
1138 while (offset < aop->coff)
1141 emitcode ("lcall", "__decdptr");
1146 /* if not in accumulater */
1149 emitcode ("movx", "@dptr,a");
1151 if (aop->type == AOP_DPTR2)
1159 while (offset > aop->coff)
1162 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1164 while (offset < aop->coff)
1167 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1174 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1180 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1182 else if (strcmp (s, "r0") == 0 ||
1183 strcmp (s, "r1") == 0 ||
1184 strcmp (s, "r2") == 0 ||
1185 strcmp (s, "r3") == 0 ||
1186 strcmp (s, "r4") == 0 ||
1187 strcmp (s, "r5") == 0 ||
1188 strcmp (s, "r6") == 0 ||
1189 strcmp (s, "r7") == 0)
1192 sprintf (buffer, "a%s", s);
1193 emitcode ("mov", "@%s,%s",
1194 aop->aopu.aop_ptr->name, buffer);
1197 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1202 if (strcmp (s, "a") == 0)
1203 emitcode ("push", "acc");
1205 emitcode ("push", "%s", s);
1210 /* if bit variable */
1211 if (!aop->aopu.aop_dir)
1213 emitcode ("clr", "a");
1214 emitcode ("rlc", "a");
1219 emitcode ("clr", "%s", aop->aopu.aop_dir);
1221 emitcode ("setb", "%s", aop->aopu.aop_dir);
1222 else if (!strcmp (s, "c"))
1223 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1226 if (strcmp (s, "a"))
1231 symbol *lbl = newiTempLabel (NULL);
1232 emitcode ("clr", "c");
1233 emitcode ("jz", "%05d$", lbl->key + 100);
1234 emitcode ("cpl", "c");
1235 emitcode ("", "%05d$:", lbl->key + 100);
1236 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1244 if (strcmp (aop->aopu.aop_str[offset], s))
1245 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1250 if (!offset && (strcmp (s, "acc") == 0))
1253 if (strcmp (aop->aopu.aop_str[offset], s))
1254 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1258 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1259 "aopPut got unsupported aop->type");
1266 /*--------------------------------------------------------------------*/
1267 /* reAdjustPreg - points a register back to where it should (coff==0) */
1268 /*--------------------------------------------------------------------*/
1270 reAdjustPreg (asmop * aop)
1272 if ((aop->coff==0) || (aop->size <= 1)) {
1281 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1285 if (aop->type == AOP_DPTR2)
1292 emitcode ("lcall", "__decdptr");
1295 if (aop->type == AOP_DPTR2)
1305 #define AOP(op) op->aop
1306 #define AOP_TYPE(op) AOP(op)->type
1307 #define AOP_SIZE(op) AOP(op)->size
1308 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1309 AOP_TYPE(x) == AOP_R0))
1311 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1312 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1315 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1316 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1317 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1319 /* Workaround for DS80C390 bug: div ab may return bogus results
1320 * if A is accessed in instruction immediately before the div.
1322 * Will be fixed in B4 rev of processor, Dallas claims.
1325 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1326 if (!AOP_NEEDSACC(RIGHT)) \
1328 /* We can load A first, then B, since \
1329 * B (the RIGHT operand) won't clobber A, \
1330 * thus avoiding touching A right before the div. \
1332 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1333 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1335 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1339 /* Just stuff in a nop after loading A. */ \
1340 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1341 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1343 emitcode("nop", "; workaround for DS80C390 div bug."); \
1346 /*-----------------------------------------------------------------*/
1347 /* genNotFloat - generates not for float operations */
1348 /*-----------------------------------------------------------------*/
1350 genNotFloat (operand * op, operand * res)
1356 D (emitcode (";", "genNotFloat ");
1359 /* we will put 127 in the first byte of
1361 aopPut (AOP (res), "#127", 0);
1362 size = AOP_SIZE (op) - 1;
1365 _startLazyDPSEvaluation ();
1366 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1371 emitcode ("orl", "a,%s",
1373 offset++, FALSE, FALSE, FALSE));
1375 _endLazyDPSEvaluation ();
1377 tlbl = newiTempLabel (NULL);
1378 aopPut (res->aop, one, 1);
1379 emitcode ("jz", "%05d$", (tlbl->key + 100));
1380 aopPut (res->aop, zero, 1);
1381 emitcode ("", "%05d$:", (tlbl->key + 100));
1383 size = res->aop->size - 2;
1385 /* put zeros in the rest */
1387 aopPut (res->aop, zero, offset++);
1390 /*-----------------------------------------------------------------*/
1391 /* opIsGptr: returns non-zero if the passed operand is */
1392 /* a generic pointer type. */
1393 /*-----------------------------------------------------------------*/
1395 opIsGptr (operand * op)
1397 sym_link *type = operandType (op);
1399 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1406 /*-----------------------------------------------------------------*/
1407 /* getDataSize - get the operand data size */
1408 /*-----------------------------------------------------------------*/
1410 getDataSize (operand * op)
1413 size = AOP_SIZE (op);
1414 if (size == GPTRSIZE)
1416 sym_link *type = operandType (op);
1417 if (IS_GENPTR (type))
1419 /* generic pointer; arithmetic operations
1420 * should ignore the high byte (pointer type).
1428 /*-----------------------------------------------------------------*/
1429 /* outAcc - output Acc */
1430 /*-----------------------------------------------------------------*/
1432 outAcc (operand * result)
1435 size = getDataSize (result);
1438 aopPut (AOP (result), "a", 0);
1441 /* unsigned or positive */
1444 aopPut (AOP (result), zero, offset++);
1449 /*-----------------------------------------------------------------*/
1450 /* outBitC - output a bit C */
1451 /*-----------------------------------------------------------------*/
1453 outBitC (operand * result)
1455 /* if the result is bit */
1456 if (AOP_TYPE (result) == AOP_CRY)
1458 aopPut (AOP (result), "c", 0);
1462 emitcode ("clr", "a");
1463 emitcode ("rlc", "a");
1468 /*-----------------------------------------------------------------*/
1469 /* toBoolean - emit code for orl a,operator(sizeop) */
1470 /*-----------------------------------------------------------------*/
1472 toBoolean (operand * oper)
1474 int size = AOP_SIZE (oper) - 1;
1478 /* The generic part of a generic pointer should
1479 * not participate in it's truth value.
1481 * i.e. 0x10000000 is zero.
1483 if (opIsGptr (oper))
1485 D (emitcode (";", "toBoolean: generic ptr special case.");
1490 _startLazyDPSEvaluation ();
1491 if (AOP_NEEDSACC (oper) && size)
1494 emitcode ("push", "b");
1495 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1499 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1505 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1509 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1512 _endLazyDPSEvaluation ();
1516 emitcode ("mov", "a,b");
1517 emitcode ("pop", "b");
1522 /*-----------------------------------------------------------------*/
1523 /* genNot - generate code for ! operation */
1524 /*-----------------------------------------------------------------*/
1529 sym_link *optype = operandType (IC_LEFT (ic));
1531 D (emitcode (";", "genNot ");
1534 /* assign asmOps to operand & result */
1535 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1536 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1538 /* if in bit space then a special case */
1539 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1541 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1542 emitcode ("cpl", "c");
1543 outBitC (IC_RESULT (ic));
1547 /* if type float then do float */
1548 if (IS_FLOAT (optype))
1550 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1554 toBoolean (IC_LEFT (ic));
1556 tlbl = newiTempLabel (NULL);
1557 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1558 emitcode ("", "%05d$:", tlbl->key + 100);
1559 outBitC (IC_RESULT (ic));
1562 /* release the aops */
1563 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1564 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1568 /*-----------------------------------------------------------------*/
1569 /* genCpl - generate code for complement */
1570 /*-----------------------------------------------------------------*/
1577 D (emitcode (";", "genCpl ");
1581 /* assign asmOps to operand & result */
1582 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1585 /* if both are in bit space then
1587 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1588 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1591 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1592 emitcode ("cpl", "c");
1593 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1597 size = AOP_SIZE (IC_RESULT (ic));
1598 _startLazyDPSEvaluation ();
1601 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1603 emitcode ("cpl", "a");
1604 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1606 _endLazyDPSEvaluation ();
1610 /* release the aops */
1611 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1612 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* genUminusFloat - unary minus for floating points */
1617 /*-----------------------------------------------------------------*/
1619 genUminusFloat (operand * op, operand * result)
1621 int size, offset = 0;
1623 /* for this we just need to flip the
1624 first it then copy the rest in place */
1625 D (emitcode (";", "genUminusFloat");
1628 _startLazyDPSEvaluation ();
1629 size = AOP_SIZE (op) - 1;
1630 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1633 emitcode ("cpl", "acc.7");
1634 aopPut (AOP (result), "a", 3);
1638 aopPut (AOP (result),
1639 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1643 _endLazyDPSEvaluation ();
1646 /*-----------------------------------------------------------------*/
1647 /* genUminus - unary minus code generation */
1648 /*-----------------------------------------------------------------*/
1650 genUminus (iCode * ic)
1653 sym_link *optype, *rtype;
1655 D (emitcode (";", "genUminus ");
1660 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1661 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1663 /* if both in bit space then special
1665 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1666 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1669 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1670 emitcode ("cpl", "c");
1671 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1675 optype = operandType (IC_LEFT (ic));
1676 rtype = operandType (IC_RESULT (ic));
1678 /* if float then do float stuff */
1679 if (IS_FLOAT (optype))
1681 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1685 /* otherwise subtract from zero */
1686 size = AOP_SIZE (IC_LEFT (ic));
1688 _startLazyDPSEvaluation ();
1691 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1692 if (!strcmp (l, "a"))
1696 emitcode ("cpl", "a");
1697 emitcode ("addc", "a,#0");
1703 emitcode ("clr", "a");
1704 emitcode ("subb", "a,%s", l);
1706 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1708 _endLazyDPSEvaluation ();
1710 /* if any remaining bytes in the result */
1711 /* we just need to propagate the sign */
1712 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1714 emitcode ("rlc", "a");
1715 emitcode ("subb", "a,acc");
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1721 /* release the aops */
1722 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1723 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1726 /*-----------------------------------------------------------------*/
1727 /* saveRegisters - will look for a call and save the registers */
1728 /*-----------------------------------------------------------------*/
1730 saveRegisters (iCode * lic)
1738 for (ic = lic; ic; ic = ic->next)
1739 if (ic->op == CALL || ic->op == PCALL)
1744 fprintf (stderr, "found parameter push with no function call\n");
1748 /* if the registers have been saved already then
1750 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1753 /* find the registers in use at this time
1754 and push them away to safety */
1755 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1759 if (options.useXstack)
1761 if (bitVectBitValue (rsave, R0_IDX))
1762 emitcode ("mov", "b,r0");
1763 emitcode ("mov", "r0,%s", spname);
1764 for (i = 0; i < ds390_nRegs; i++)
1766 if (bitVectBitValue (rsave, i))
1769 emitcode ("mov", "a,b");
1771 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1772 emitcode ("movx", "@r0,a");
1773 emitcode ("inc", "r0");
1776 emitcode ("mov", "%s,r0", spname);
1777 if (bitVectBitValue (rsave, R0_IDX))
1778 emitcode ("mov", "r0,b");
1781 for (i = 0; i < ds390_nRegs; i++)
1783 if (bitVectBitValue (rsave, i))
1784 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1787 detype = getSpec (operandType (IC_LEFT (ic)));
1789 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1790 IS_ISR (currFunc->etype) &&
1793 saverbank (SPEC_BANK (detype), ic, TRUE);
1796 /*-----------------------------------------------------------------*/
1797 /* unsaveRegisters - pop the pushed registers */
1798 /*-----------------------------------------------------------------*/
1800 unsaveRegisters (iCode * ic)
1804 /* find the registers in use at this time
1805 and push them away to safety */
1806 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1809 if (options.useXstack)
1811 emitcode ("mov", "r0,%s", spname);
1812 for (i = ds390_nRegs; i >= 0; i--)
1814 if (bitVectBitValue (rsave, i))
1816 emitcode ("dec", "r0");
1817 emitcode ("movx", "a,@r0");
1819 emitcode ("mov", "b,a");
1821 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1825 emitcode ("mov", "%s,r0", spname);
1826 if (bitVectBitValue (rsave, R0_IDX))
1827 emitcode ("mov", "r0,b");
1830 for (i = ds390_nRegs; i >= 0; i--)
1832 if (bitVectBitValue (rsave, i))
1833 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1839 /*-----------------------------------------------------------------*/
1841 /*-----------------------------------------------------------------*/
1843 pushSide (operand * oper, int size)
1846 _startLazyDPSEvaluation ();
1849 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1850 if (AOP_TYPE (oper) != AOP_REG &&
1851 AOP_TYPE (oper) != AOP_DIR &&
1854 emitcode ("mov", "a,%s", l);
1855 emitcode ("push", "acc");
1858 emitcode ("push", "%s", l);
1860 _endLazyDPSEvaluation ();
1863 /*-----------------------------------------------------------------*/
1864 /* assignResultValue - */
1865 /*-----------------------------------------------------------------*/
1867 assignResultValue (operand * oper)
1870 int size = AOP_SIZE (oper);
1872 _startLazyDPSEvaluation ();
1875 aopPut (AOP (oper), fReturn[offset], offset);
1878 _endLazyDPSEvaluation ();
1882 /*-----------------------------------------------------------------*/
1883 /* genXpush - pushes onto the external stack */
1884 /*-----------------------------------------------------------------*/
1886 genXpush (iCode * ic)
1888 asmop *aop = newAsmop (0);
1890 int size, offset = 0;
1892 D (emitcode (";", "genXpush ");
1895 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1896 r = getFreePtr (ic, &aop, FALSE);
1899 emitcode ("mov", "%s,_spx", r->name);
1901 size = AOP_SIZE (IC_LEFT (ic));
1902 _startLazyDPSEvaluation ();
1906 char *l = aopGet (AOP (IC_LEFT (ic)),
1907 offset++, FALSE, FALSE, TRUE);
1909 emitcode ("movx", "@%s,a", r->name);
1910 emitcode ("inc", "%s", r->name);
1913 _endLazyDPSEvaluation ();
1916 emitcode ("mov", "_spx,%s", r->name);
1918 freeAsmop (NULL, aop, ic, TRUE);
1919 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1922 /*-----------------------------------------------------------------*/
1923 /* genIpush - genrate code for pushing this gets a little complex */
1924 /*-----------------------------------------------------------------*/
1926 genIpush (iCode * ic)
1928 int size, offset = 0;
1931 D (emitcode (";", "genIpush ");
1934 /* if this is not a parm push : ie. it is spill push
1935 and spill push is always done on the local stack */
1939 /* and the item is spilt then do nothing */
1940 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1943 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944 size = AOP_SIZE (IC_LEFT (ic));
1945 /* push it on the stack */
1946 _startLazyDPSEvaluation ();
1949 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1955 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1957 _endLazyDPSEvaluation ();
1961 /* this is a paramter push: in this case we call
1962 the routine to find the call and save those
1963 registers that need to be saved */
1966 /* if use external stack then call the external
1967 stack pushing routine */
1968 if (options.useXstack)
1974 /* then do the push */
1975 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1977 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1978 size = AOP_SIZE (IC_LEFT (ic));
1980 _startLazyDPSEvaluation ();
1983 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1984 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1985 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1988 emitcode ("mov", "a,%s", l);
1989 emitcode ("push", "acc");
1992 emitcode ("push", "%s ;jwk genIpush", l);
1994 _endLazyDPSEvaluation ();
1996 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1999 /*-----------------------------------------------------------------*/
2000 /* genIpop - recover the registers: can happen only for spilling */
2001 /*-----------------------------------------------------------------*/
2003 genIpop (iCode * ic)
2007 D (emitcode (";", "genIpop ");
2011 /* if the temp was not pushed then */
2012 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2015 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2016 size = AOP_SIZE (IC_LEFT (ic));
2017 offset = (size - 1);
2018 _startLazyDPSEvaluation ();
2021 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2022 FALSE, TRUE, TRUE));
2024 _endLazyDPSEvaluation ();
2026 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2029 /*-----------------------------------------------------------------*/
2030 /* unsaverbank - restores the resgister bank from stack */
2031 /*-----------------------------------------------------------------*/
2033 unsaverbank (int bank, iCode * ic, bool popPsw)
2041 if (options.useXstack)
2044 r = getFreePtr (ic, &aop, FALSE);
2047 emitcode ("mov", "%s,_spx", r->name);
2048 emitcode ("movx", "a,@%s", r->name);
2049 emitcode ("mov", "psw,a");
2050 emitcode ("dec", "%s", r->name);
2054 emitcode ("pop", "psw");
2057 for (i = (ds390_nRegs - 1); i >= 0; i--)
2059 if (options.useXstack)
2061 emitcode ("movx", "a,@%s", r->name);
2062 emitcode ("mov", "(%s+%d),a",
2063 regs390[i].base, 8 * bank + regs390[i].offset);
2064 emitcode ("dec", "%s", r->name);
2068 emitcode ("pop", "(%s+%d)",
2069 regs390[i].base, 8 * bank + regs390[i].offset);
2072 if (options.useXstack)
2075 emitcode ("mov", "_spx,%s", r->name);
2076 freeAsmop (NULL, aop, ic, TRUE);
2081 /*-----------------------------------------------------------------*/
2082 /* saverbank - saves an entire register bank on the stack */
2083 /*-----------------------------------------------------------------*/
2085 saverbank (int bank, iCode * ic, bool pushPsw)
2091 if (options.useXstack)
2095 r = getFreePtr (ic, &aop, FALSE);
2096 emitcode ("mov", "%s,_spx", r->name);
2100 for (i = 0; i < ds390_nRegs; i++)
2102 if (options.useXstack)
2104 emitcode ("inc", "%s", r->name);
2105 emitcode ("mov", "a,(%s+%d)",
2106 regs390[i].base, 8 * bank + regs390[i].offset);
2107 emitcode ("movx", "@%s,a", r->name);
2110 emitcode ("push", "(%s+%d)",
2111 regs390[i].base, 8 * bank + regs390[i].offset);
2116 if (options.useXstack)
2118 emitcode ("mov", "a,psw");
2119 emitcode ("movx", "@%s,a", r->name);
2120 emitcode ("inc", "%s", r->name);
2121 emitcode ("mov", "_spx,%s", r->name);
2122 freeAsmop (NULL, aop, ic, TRUE);
2126 emitcode ("push", "psw");
2128 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2134 /*-----------------------------------------------------------------*/
2135 /* genCall - generates a call statement */
2136 /*-----------------------------------------------------------------*/
2138 genCall (iCode * ic)
2142 D (emitcode (";", "genCall ");
2145 /* if caller saves & we have not saved then */
2149 /* if we are calling a function that is not using
2150 the same register bank then we need to save the
2151 destination registers on the stack */
2152 detype = getSpec (operandType (IC_LEFT (ic)));
2154 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2155 IS_ISR (currFunc->etype) &&
2158 saverbank (SPEC_BANK (detype), ic, TRUE);
2160 /* if send set is not empty the assign */
2165 for (sic = setFirstItem (_G.sendSet); sic;
2166 sic = setNextItem (_G.sendSet))
2168 int size, offset = 0;
2170 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2171 size = AOP_SIZE (IC_LEFT (sic));
2173 _startLazyDPSEvaluation ();
2176 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2177 FALSE, FALSE, TRUE);
2178 if (strcmp (l, fReturn[offset])) {
2181 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2187 _endLazyDPSEvaluation ();
2188 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2193 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2194 OP_SYMBOL (IC_LEFT (ic))->rname :
2195 OP_SYMBOL (IC_LEFT (ic))->name));
2197 /* if we need assign a result value */
2198 if ((IS_ITEMP (IC_RESULT (ic)) &&
2199 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2200 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2201 IS_TRUE_SYMOP (IC_RESULT (ic)))
2203 if (isOperandInFarSpace (IC_RESULT (ic))
2204 && getSize (operandType (IC_RESULT (ic))) <= 2)
2206 int size = getSize (operandType (IC_RESULT (ic)));
2208 /* Special case for 1 or 2 byte return in far space. */
2209 emitcode (";", "Kevin function call abuse #1");
2214 emitcode ("mov", "b,%s", fReturn[1]);
2217 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2218 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2222 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2224 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2229 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2232 assignResultValue (IC_RESULT (ic));
2234 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2238 /* adjust the stack for parameters if
2243 if (ic->parmBytes > 3)
2245 emitcode ("mov", "a,%s", spname);
2246 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2247 emitcode ("mov", "%s,a", spname);
2250 for (i = 0; i < ic->parmBytes; i++)
2251 emitcode ("dec", "%s", spname);
2255 /* if register bank was saved then pop them */
2257 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2259 /* if we hade saved some registers then unsave them */
2260 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2261 unsaveRegisters (ic);
2266 /*-----------------------------------------------------------------*/
2267 /* genPcall - generates a call by pointer statement */
2268 /*-----------------------------------------------------------------*/
2270 genPcall (iCode * ic)
2273 symbol *rlbl = newiTempLabel (NULL);
2275 D (emitcode (";", "genPcall ");
2279 /* if caller saves & we have not saved then */
2283 /* if we are calling a function that is not using
2284 the same register bank then we need to save the
2285 destination registers on the stack */
2286 detype = getSpec (operandType (IC_LEFT (ic)));
2288 IS_ISR (currFunc->etype) &&
2289 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2290 saverbank (SPEC_BANK (detype), ic, TRUE);
2293 /* push the return address on to the stack */
2294 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2295 emitcode ("push", "acc");
2296 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2297 emitcode ("push", "acc");
2299 if (options.model == MODEL_FLAT24)
2301 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2302 emitcode ("push", "acc");
2305 /* now push the calling address */
2306 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2308 pushSide (IC_LEFT (ic), FPTRSIZE);
2310 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2312 /* if send set is not empty the assign */
2317 for (sic = setFirstItem (_G.sendSet); sic;
2318 sic = setNextItem (_G.sendSet))
2320 int size, offset = 0;
2322 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2323 size = AOP_SIZE (IC_LEFT (sic));
2324 _startLazyDPSEvaluation ();
2327 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2328 FALSE, FALSE, TRUE);
2329 if (strcmp (l, fReturn[offset]))
2331 emitcode ("mov", "%s,%s",
2337 _endLazyDPSEvaluation ();
2338 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2343 emitcode ("ret", "");
2344 emitcode ("", "%05d$:", (rlbl->key + 100));
2347 /* if we need assign a result value */
2348 if ((IS_ITEMP (IC_RESULT (ic)) &&
2349 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2350 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2351 IS_TRUE_SYMOP (IC_RESULT (ic)))
2355 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2358 assignResultValue (IC_RESULT (ic));
2360 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2363 /* adjust the stack for parameters if
2368 if (ic->parmBytes > 3)
2370 emitcode ("mov", "a,%s", spname);
2371 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2372 emitcode ("mov", "%s,a", spname);
2375 for (i = 0; i < ic->parmBytes; i++)
2376 emitcode ("dec", "%s", spname);
2380 /* if register bank was saved then unsave them */
2382 (SPEC_BANK (currFunc->etype) !=
2383 SPEC_BANK (detype)))
2384 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2386 /* if we hade saved some registers then
2389 unsaveRegisters (ic);
2393 /*-----------------------------------------------------------------*/
2394 /* resultRemat - result is rematerializable */
2395 /*-----------------------------------------------------------------*/
2397 resultRemat (iCode * ic)
2399 if (SKIP_IC (ic) || ic->op == IFX)
2402 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2404 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2405 if (sym->remat && !POINTER_SET (ic))
2412 #if defined(__BORLANDC__) || defined(_MSC_VER)
2413 #define STRCASECMP stricmp
2415 #define STRCASECMP strcasecmp
2418 /*-----------------------------------------------------------------*/
2419 /* inExcludeList - return 1 if the string is in exclude Reg list */
2420 /*-----------------------------------------------------------------*/
2422 inExcludeList (char *s)
2426 if (options.excludeRegs[i] &&
2427 STRCASECMP (options.excludeRegs[i], "none") == 0)
2430 for (i = 0; options.excludeRegs[i]; i++)
2432 if (options.excludeRegs[i] &&
2433 STRCASECMP (s, options.excludeRegs[i]) == 0)
2439 /*-----------------------------------------------------------------*/
2440 /* genFunction - generated code for function entry */
2441 /*-----------------------------------------------------------------*/
2443 genFunction (iCode * ic)
2448 D (emitcode (";", "genFunction ");
2452 /* create the function header */
2453 emitcode (";", "-----------------------------------------");
2454 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2455 emitcode (";", "-----------------------------------------");
2457 emitcode ("", "%s:", sym->rname);
2458 fetype = getSpec (operandType (IC_LEFT (ic)));
2460 /* if critical function then turn interrupts off */
2461 if (SPEC_CRTCL (fetype))
2462 emitcode ("clr", "ea");
2464 /* here we need to generate the equates for the
2465 register bank if required */
2466 if (SPEC_BANK (fetype) != rbank)
2470 rbank = SPEC_BANK (fetype);
2471 for (i = 0; i < ds390_nRegs; i++)
2473 if (strcmp (regs390[i].base, "0") == 0)
2474 emitcode ("", "%s = 0x%02x",
2476 8 * rbank + regs390[i].offset);
2478 emitcode ("", "%s = %s + 0x%02x",
2481 8 * rbank + regs390[i].offset);
2485 /* if this is an interrupt service routine then
2486 save acc, b, dpl, dph */
2487 if (IS_ISR (sym->etype))
2490 if (!inExcludeList ("acc"))
2491 emitcode ("push", "acc");
2492 if (!inExcludeList ("b"))
2493 emitcode ("push", "b");
2494 if (!inExcludeList ("dpl"))
2495 emitcode ("push", "dpl");
2496 if (!inExcludeList ("dph"))
2497 emitcode ("push", "dph");
2498 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2500 emitcode ("push", "dpx");
2501 /* Make sure we're using standard DPTR */
2502 emitcode ("push", "dps");
2503 emitcode ("mov", "dps, #0x00");
2504 if (options.stack10bit)
2506 /* This ISR could conceivably use DPTR2. Better save it. */
2507 emitcode ("push", "dpl1");
2508 emitcode ("push", "dph1");
2509 emitcode ("push", "dpx1");
2510 emitcode ("push", DP2_RESULT_REG);
2513 /* if this isr has no bank i.e. is going to
2514 run with bank 0 , then we need to save more
2516 if (!SPEC_BANK (sym->etype))
2519 /* if this function does not call any other
2520 function then we can be economical and
2521 save only those registers that are used */
2526 /* if any registers used */
2529 /* save the registers used */
2530 for (i = 0; i < sym->regsUsed->size; i++)
2532 if (bitVectBitValue (sym->regsUsed, i) ||
2533 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2534 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2541 /* this function has a function call cannot
2542 determines register usage so we will have the
2544 saverbank (0, ic, FALSE);
2550 /* if callee-save to be used for this function
2551 then save the registers being used in this function */
2552 if (sym->calleeSave)
2556 /* if any registers used */
2559 /* save the registers used */
2560 for (i = 0; i < sym->regsUsed->size; i++)
2562 if (bitVectBitValue (sym->regsUsed, i) ||
2563 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2565 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2573 /* set the register bank to the desired value */
2574 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2576 emitcode ("push", "psw");
2577 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2580 if (IS_RENT (sym->etype) || options.stackAuto)
2583 if (options.useXstack)
2585 emitcode ("mov", "r0,%s", spname);
2586 emitcode ("mov", "a,_bp");
2587 emitcode ("movx", "@r0,a");
2588 emitcode ("inc", "%s", spname);
2592 /* set up the stack */
2593 emitcode ("push", "_bp"); /* save the callers stack */
2595 emitcode ("mov", "_bp,%s", spname);
2598 /* adjust the stack for the function */
2604 werror (W_STACK_OVERFLOW, sym->name);
2606 if (i > 3 && sym->recvSize < 4)
2609 emitcode ("mov", "a,sp");
2610 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2611 emitcode ("mov", "sp,a");
2616 emitcode ("inc", "sp");
2622 emitcode ("mov", "a,_spx");
2623 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2624 emitcode ("mov", "_spx,a");
2629 /*-----------------------------------------------------------------*/
2630 /* genEndFunction - generates epilogue for functions */
2631 /*-----------------------------------------------------------------*/
2633 genEndFunction (iCode * ic)
2635 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2637 D (emitcode (";", "genEndFunction ");
2640 if (IS_RENT (sym->etype) || options.stackAuto)
2642 emitcode ("mov", "%s,_bp", spname);
2645 /* if use external stack but some variables were
2646 added to the local stack then decrement the
2648 if (options.useXstack && sym->stack)
2650 emitcode ("mov", "a,sp");
2651 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2652 emitcode ("mov", "sp,a");
2656 if ((IS_RENT (sym->etype) || options.stackAuto))
2658 if (options.useXstack)
2660 emitcode ("mov", "r0,%s", spname);
2661 emitcode ("movx", "a,@r0");
2662 emitcode ("mov", "_bp,a");
2663 emitcode ("dec", "%s", spname);
2667 emitcode ("pop", "_bp");
2671 /* restore the register bank */
2672 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2673 emitcode ("pop", "psw");
2675 if (IS_ISR (sym->etype))
2678 /* now we need to restore the registers */
2679 /* if this isr has no bank i.e. is going to
2680 run with bank 0 , then we need to save more
2682 if (!SPEC_BANK (sym->etype))
2685 /* if this function does not call any other
2686 function then we can be economical and
2687 save only those registers that are used */
2692 /* if any registers used */
2695 /* save the registers used */
2696 for (i = sym->regsUsed->size; i >= 0; i--)
2698 if (bitVectBitValue (sym->regsUsed, i) ||
2699 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2700 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2707 /* this function has a function call cannot
2708 determines register usage so we will have the
2710 unsaverbank (0, ic, FALSE);
2714 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2716 if (options.stack10bit)
2718 emitcode ("pop", DP2_RESULT_REG);
2719 emitcode ("pop", "dpx1");
2720 emitcode ("pop", "dph1");
2721 emitcode ("pop", "dpl1");
2723 emitcode ("pop", "dps");
2724 emitcode ("pop", "dpx");
2726 if (!inExcludeList ("dph"))
2727 emitcode ("pop", "dph");
2728 if (!inExcludeList ("dpl"))
2729 emitcode ("pop", "dpl");
2730 if (!inExcludeList ("b"))
2731 emitcode ("pop", "b");
2732 if (!inExcludeList ("acc"))
2733 emitcode ("pop", "acc");
2735 if (SPEC_CRTCL (sym->etype))
2736 emitcode ("setb", "ea");
2738 /* if debug then send end of function */
2739 /* if (options.debug && currFunc) { */
2743 emitcode ("", "C$%s$%d$%d$%d ==.",
2744 FileBaseName (ic->filename), currFunc->lastLine,
2745 ic->level, ic->block);
2746 if (IS_STATIC (currFunc->etype))
2747 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2749 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2753 emitcode ("reti", "");
2757 if (SPEC_CRTCL (sym->etype))
2758 emitcode ("setb", "ea");
2760 if (sym->calleeSave)
2764 /* if any registers used */
2767 /* save the registers used */
2768 for (i = sym->regsUsed->size; i >= 0; i--)
2770 if (bitVectBitValue (sym->regsUsed, i) ||
2771 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2772 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2778 /* if debug then send end of function */
2782 emitcode ("", "C$%s$%d$%d$%d ==.",
2783 FileBaseName (ic->filename), currFunc->lastLine,
2784 ic->level, ic->block);
2785 if (IS_STATIC (currFunc->etype))
2786 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2788 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2792 emitcode ("ret", "");
2797 /*-----------------------------------------------------------------*/
2798 /* genRet - generate code for return statement */
2799 /*-----------------------------------------------------------------*/
2803 int size, offset = 0, pushed = 0;
2805 D (emitcode (";", "genRet ");
2808 /* if we have no return value then
2809 just generate the "ret" */
2813 /* we have something to return then
2814 move the return value into place */
2815 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2816 size = AOP_SIZE (IC_LEFT (ic));
2818 _startLazyDPSEvaluation ();
2822 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2824 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2825 FALSE, TRUE, FALSE);
2826 emitcode ("push", "%s", l);
2831 l = aopGet (AOP (IC_LEFT (ic)), offset,
2832 FALSE, FALSE, FALSE);
2833 if (strcmp (fReturn[offset], l))
2834 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2837 _endLazyDPSEvaluation ();
2844 if (strcmp (fReturn[pushed], "a"))
2845 emitcode ("pop", fReturn[pushed]);
2847 emitcode ("pop", "acc");
2850 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2853 /* generate a jump to the return label
2854 if the next is not the return statement */
2855 if (!(ic->next && ic->next->op == LABEL &&
2856 IC_LABEL (ic->next) == returnLabel))
2858 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2862 /*-----------------------------------------------------------------*/
2863 /* genLabel - generates a label */
2864 /*-----------------------------------------------------------------*/
2866 genLabel (iCode * ic)
2868 /* special case never generate */
2869 if (IC_LABEL (ic) == entryLabel)
2872 D (emitcode (";", "genLabel ");
2875 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2878 /*-----------------------------------------------------------------*/
2879 /* genGoto - generates a ljmp */
2880 /*-----------------------------------------------------------------*/
2882 genGoto (iCode * ic)
2884 D (emitcode (";", "genGoto ");
2886 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2889 /*-----------------------------------------------------------------*/
2890 /* findLabelBackwards: walks back through the iCode chain looking */
2891 /* for the given label. Returns number of iCode instructions */
2892 /* between that label and given ic. */
2893 /* Returns zero if label not found. */
2894 /*-----------------------------------------------------------------*/
2896 findLabelBackwards (iCode * ic, int key)
2905 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2907 /* printf("findLabelBackwards = %d\n", count); */
2915 /*-----------------------------------------------------------------*/
2916 /* genPlusIncr :- does addition with increment if possible */
2917 /*-----------------------------------------------------------------*/
2919 genPlusIncr (iCode * ic)
2921 unsigned int icount;
2922 unsigned int size = getDataSize (IC_RESULT (ic));
2924 /* will try to generate an increment */
2925 /* if the right side is not a literal
2927 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2930 /* if the literal value of the right hand side
2931 is greater than 4 then it is not worth it */
2932 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2935 /* if increment 16 bits in register */
2937 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2938 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2939 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2947 /* If the next instruction is a goto and the goto target
2948 * is <= 5 instructions previous to this, we can generate
2949 * jumps straight to that target.
2951 if (ic->next && ic->next->op == GOTO
2952 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2955 emitcode (";", "tail increment optimized (range %d)", labelRange);
2956 tlbl = IC_LABEL (ic->next);
2961 tlbl = newiTempLabel (NULL);
2964 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2965 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2966 IS_AOP_PREG (IC_RESULT (ic)))
2967 emitcode ("cjne", "%s,#0x00,%05d$"
2968 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2972 emitcode ("clr", "a");
2973 emitcode ("cjne", "a,%s,%05d$"
2974 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2978 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982 IS_AOP_PREG (IC_RESULT (ic)))
2983 emitcode ("cjne", "%s,#0x00,%05d$"
2984 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2987 emitcode ("cjne", "a,%s,%05d$"
2988 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2991 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2995 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2996 IS_AOP_PREG (IC_RESULT (ic)))
2997 emitcode ("cjne", "%s,#0x00,%05d$"
2998 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3002 emitcode ("cjne", "a,%s,%05d$"
3003 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3006 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3011 emitcode ("", "%05d$:", tlbl->key + 100);
3016 /* if the sizes are greater than 1 then we cannot */
3017 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3018 AOP_SIZE (IC_LEFT (ic)) > 1)
3021 /* we can if the aops of the left & result match or
3022 if they are in registers and the registers are the
3025 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3026 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3027 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3032 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3033 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3034 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3039 _startLazyDPSEvaluation ();
3042 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3044 _endLazyDPSEvaluation ();
3053 /*-----------------------------------------------------------------*/
3054 /* outBitAcc - output a bit in acc */
3055 /*-----------------------------------------------------------------*/
3057 outBitAcc (operand * result)
3059 symbol *tlbl = newiTempLabel (NULL);
3060 /* if the result is a bit */
3061 if (AOP_TYPE (result) == AOP_CRY)
3063 aopPut (AOP (result), "a", 0);
3067 emitcode ("jz", "%05d$", tlbl->key + 100);
3068 emitcode ("mov", "a,%s", one);
3069 emitcode ("", "%05d$:", tlbl->key + 100);
3074 /*-----------------------------------------------------------------*/
3075 /* genPlusBits - generates code for addition of two bits */
3076 /*-----------------------------------------------------------------*/
3078 genPlusBits (iCode * ic)
3080 D (emitcode (";", "genPlusBits ");
3082 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3084 symbol *lbl = newiTempLabel (NULL);
3085 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3086 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3087 emitcode ("cpl", "c");
3088 emitcode ("", "%05d$:", (lbl->key + 100));
3089 outBitC (IC_RESULT (ic));
3093 emitcode ("clr", "a");
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("rlc", "a");
3096 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3097 emitcode ("addc", "a,#0x00");
3098 outAcc (IC_RESULT (ic));
3103 adjustArithmeticResult (iCode * ic)
3105 if (opIsGptr (IC_RESULT (ic)) &&
3106 opIsGptr (IC_LEFT (ic)) &&
3107 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3109 aopPut (AOP (IC_RESULT (ic)),
3110 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3114 if (opIsGptr (IC_RESULT (ic)) &&
3115 opIsGptr (IC_RIGHT (ic)) &&
3116 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3118 aopPut (AOP (IC_RESULT (ic)),
3119 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3123 if (opIsGptr (IC_RESULT (ic)) &&
3124 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3125 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3126 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3127 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3130 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3131 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3135 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3136 // (because all three operands are in far space).
3137 #define AOP_OP_3(ic) \
3138 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3139 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3140 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3141 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3142 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3143 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3145 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3147 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3150 // Macro to aopOp all three operands of an ic. If this cannot be done,
3151 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3152 // will be set TRUE. The caller must then handle the case specially, noting
3153 // that the IC_RESULT operand is not aopOp'd.
3154 #define AOP_OP_3_NOFATAL(ic, rc) \
3155 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3156 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3157 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3158 isOperandInFarSpace(IC_RESULT(ic))) \
3160 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3165 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3166 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3168 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3169 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3171 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3173 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3177 // aopOp the left & right operands of an ic.
3178 #define AOP_OP_2(ic) \
3179 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3180 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3182 // convienience macro.
3183 #define AOP_SET_LOCALS(ic) \
3184 left = IC_LEFT(ic); \
3185 right = IC_RIGHT(ic); \
3186 result = IC_RESULT(ic);
3189 // Given an integer value of pushedSize bytes on the stack,
3190 // adjust it to be resultSize bytes, either by discarding
3191 // the most significant bytes or by zero-padding.
3193 // On exit from this macro, pushedSize will have been adjusted to
3194 // equal resultSize, and ACC may be trashed.
3195 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3196 /* If the pushed data is bigger than the result, \
3197 * simply discard unused bytes. Icky, but works. \
3199 while (pushedSize > resultSize) \
3201 D (emitcode (";", "discarding unused result byte."););\
3202 emitcode ("pop", "acc"); \
3205 if (pushedSize < resultSize) \
3207 emitcode ("clr", "a"); \
3208 /* Conversly, we haven't pushed enough here. \
3209 * just zero-pad, and all is well. \
3211 while (pushedSize < resultSize) \
3213 emitcode("push", "acc"); \
3217 assert(pushedSize == resultSize);
3219 /*-----------------------------------------------------------------*/
3220 /* genPlus - generates code for addition */
3221 /*-----------------------------------------------------------------*/
3223 genPlus (iCode * ic)
3225 int size, offset = 0;
3226 bool pushResult = FALSE;
3229 D (emitcode (";", "genPlus "););
3231 /* special cases :- */
3233 AOP_OP_3_NOFATAL (ic, pushResult);
3236 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3241 /* if literal, literal on the right or
3242 if left requires ACC or right is already
3244 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3245 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3246 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3248 operand *t = IC_RIGHT (ic);
3249 IC_RIGHT (ic) = IC_LEFT (ic);
3251 emitcode (";", "Swapped plus args.");
3254 /* if both left & right are in bit
3256 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3257 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3263 /* if left in bit space & right literal */
3264 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3265 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3267 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3268 /* if result in bit space */
3269 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3271 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3272 emitcode ("cpl", "c");
3273 outBitC (IC_RESULT (ic));
3277 size = getDataSize (IC_RESULT (ic));
3278 _startLazyDPSEvaluation ();
3281 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3282 emitcode ("addc", "a,#00");
3283 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3285 _endLazyDPSEvaluation ();
3290 /* if I can do an increment instead
3291 of add then GOOD for ME */
3292 if (genPlusIncr (ic) == TRUE)
3294 emitcode (";", "did genPlusIncr");
3299 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3301 _startLazyDPSEvaluation ();
3304 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3306 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3308 emitcode ("add", "a,%s",
3309 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3311 emitcode ("addc", "a,%s",
3312 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3316 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3318 emitcode ("add", "a,%s",
3319 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3321 emitcode ("addc", "a,%s",
3322 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3326 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3330 emitcode ("push", "acc");
3334 _endLazyDPSEvaluation ();
3338 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3340 size = getDataSize (IC_LEFT (ic));
3341 rSize = getDataSize (IC_RESULT (ic));
3343 ADJUST_PUSHED_RESULT(size, rSize);
3345 _startLazyDPSEvaluation ();
3348 emitcode ("pop", "acc");
3349 aopPut (AOP (IC_RESULT (ic)), "a", size);
3351 _endLazyDPSEvaluation ();
3354 adjustArithmeticResult (ic);
3357 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3358 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3359 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3362 /*-----------------------------------------------------------------*/
3363 /* genMinusDec :- does subtraction with deccrement if possible */
3364 /*-----------------------------------------------------------------*/
3366 genMinusDec (iCode * ic)
3368 unsigned int icount;
3369 unsigned int size = getDataSize (IC_RESULT (ic));
3371 /* will try to generate an increment */
3372 /* if the right side is not a literal
3374 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3377 /* if the literal value of the right hand side
3378 is greater than 4 then it is not worth it */
3379 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3382 /* if decrement 16 bits in register */
3383 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3384 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3385 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3393 /* If the next instruction is a goto and the goto target
3394 * is <= 5 instructions previous to this, we can generate
3395 * jumps straight to that target.
3397 if (ic->next && ic->next->op == GOTO
3398 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3401 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3402 tlbl = IC_LABEL (ic->next);
3407 tlbl = newiTempLabel (NULL);
3411 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3412 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3413 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3414 IS_AOP_PREG (IC_RESULT (ic)))
3415 emitcode ("cjne", "%s,#0xff,%05d$"
3416 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3420 emitcode ("mov", "a,#0xff");
3421 emitcode ("cjne", "a,%s,%05d$"
3422 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3425 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3428 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3429 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3430 IS_AOP_PREG (IC_RESULT (ic)))
3431 emitcode ("cjne", "%s,#0xff,%05d$"
3432 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3436 emitcode ("cjne", "a,%s,%05d$"
3437 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3440 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3444 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3445 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3446 IS_AOP_PREG (IC_RESULT (ic)))
3447 emitcode ("cjne", "%s,#0xff,%05d$"
3448 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3452 emitcode ("cjne", "a,%s,%05d$"
3453 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3456 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3460 emitcode ("", "%05d$:", tlbl->key + 100);
3465 /* if the sizes are greater than 1 then we cannot */
3466 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3467 AOP_SIZE (IC_LEFT (ic)) > 1)
3470 /* we can if the aops of the left & result match or
3471 if they are in registers and the registers are the
3474 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3475 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3476 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3479 _startLazyDPSEvaluation ();
3482 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3484 _endLazyDPSEvaluation ();
3492 /*-----------------------------------------------------------------*/
3493 /* addSign - complete with sign */
3494 /*-----------------------------------------------------------------*/
3496 addSign (operand * result, int offset, int sign)
3498 int size = (getDataSize (result) - offset);
3503 emitcode ("rlc", "a");
3504 emitcode ("subb", "a,acc");
3506 aopPut (AOP (result), "a", offset++);
3510 aopPut (AOP (result), zero, offset++);
3514 /*-----------------------------------------------------------------*/
3515 /* genMinusBits - generates code for subtraction of two bits */
3516 /*-----------------------------------------------------------------*/
3518 genMinusBits (iCode * ic)
3520 symbol *lbl = newiTempLabel (NULL);
3522 D (emitcode (";", "genMinusBits ");
3525 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3527 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3528 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3529 emitcode ("cpl", "c");
3530 emitcode ("", "%05d$:", (lbl->key + 100));
3531 outBitC (IC_RESULT (ic));
3535 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3536 emitcode ("subb", "a,acc");
3537 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3538 emitcode ("inc", "a");
3539 emitcode ("", "%05d$:", (lbl->key + 100));
3540 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3541 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3545 /*-----------------------------------------------------------------*/
3546 /* genMinus - generates code for subtraction */
3547 /*-----------------------------------------------------------------*/
3549 genMinus (iCode * ic)
3551 int size, offset = 0;
3553 unsigned long lit = 0L;
3554 bool pushResult = FALSE;
3556 D (emitcode (";", "genMinus "););
3558 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3559 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3560 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3561 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3567 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3569 /* special cases :- */
3570 /* if both left & right are in bit space */
3571 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3572 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3578 /* if I can do an decrement instead
3579 of subtract then GOOD for ME */
3580 if (genMinusDec (ic) == TRUE)
3585 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3587 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3593 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3598 /* if literal, add a,#-lit, else normal subb */
3599 _startLazyDPSEvaluation ();
3602 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3603 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3604 emitcode ("subb", "a,%s",
3605 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3608 /* first add without previous c */
3610 emitcode ("add", "a,#0x%02x",
3611 (unsigned int) (lit & 0x0FFL));
3613 emitcode ("addc", "a,#0x%02x",
3614 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3619 emitcode ("push", "acc");
3623 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3627 _endLazyDPSEvaluation ();
3631 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3633 size = getDataSize (IC_LEFT (ic));
3634 rSize = getDataSize (IC_RESULT (ic));
3636 ADJUST_PUSHED_RESULT(size, rSize);
3638 _startLazyDPSEvaluation ();
3641 emitcode ("pop", "acc");
3642 aopPut (AOP (IC_RESULT (ic)), "a", size);
3644 _endLazyDPSEvaluation ();
3647 adjustArithmeticResult (ic);
3650 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3652 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3656 /*-----------------------------------------------------------------*/
3657 /* genMultbits :- multiplication of bits */
3658 /*-----------------------------------------------------------------*/
3660 genMultbits (operand * left,
3664 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3665 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3670 /*-----------------------------------------------------------------*/
3671 /* genMultOneByte : 8*8=8/16 bit multiplication */
3672 /*-----------------------------------------------------------------*/
3674 genMultOneByte (operand * left,
3678 sym_link *opetype = operandType (result);
3680 int size=AOP_SIZE(result);
3682 emitcode (";",__FUNCTION__);
3683 if (size<1 || size>2) {
3684 // this should never happen
3685 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3686 AOP_SIZE(result), __FUNCTION__, lineno);
3690 /* (if two literals: the value is computed before) */
3691 /* if one literal, literal on the right */
3692 if (AOP_TYPE (left) == AOP_LIT)
3697 emitcode (";", "swapped left and right");
3700 if (SPEC_USIGN(opetype)
3701 // ignore the sign of left and right, what else can we do?
3702 || (SPEC_USIGN(operandType(left)) &&
3703 SPEC_USIGN(operandType(right)))) {
3704 // just an unsigned 8*8=8/16 multiply
3705 //emitcode (";","unsigned");
3706 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3707 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3708 emitcode ("mul", "ab");
3709 aopPut (AOP (result), "a", 0);
3711 aopPut (AOP (result), "b", 1);
3716 // we have to do a signed multiply
3718 emitcode (";", "signed");
3719 emitcode ("clr", "F0"); // reset sign flag
3720 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3721 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3723 lbl=newiTempLabel(NULL);
3724 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3725 // left side is negative, 8-bit two's complement, this fails for -128
3726 emitcode ("setb", "F0"); // set sign flag
3727 emitcode ("cpl", "a");
3728 emitcode ("inc", "a");
3730 emitcode ("", "%05d$:", lbl->key+100);
3731 emitcode ("xch", "a,b");
3734 if (AOP_TYPE(right)==AOP_LIT) {
3735 /* AND literal negative */
3736 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3737 // two's complement for literal<0
3738 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3739 emitcode ("cpl", "a");
3740 emitcode ("inc", "a");
3743 lbl=newiTempLabel(NULL);
3744 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3745 // right side is negative, 8-bit two's complement
3746 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3747 emitcode ("cpl", "a");
3748 emitcode ("inc", "a");
3749 emitcode ("", "%05d$:", lbl->key+100);
3751 emitcode ("mul", "ab");
3753 lbl=newiTempLabel(NULL);
3754 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3755 // only ONE op was negative, we have to do a 8/16-bit two's complement
3756 emitcode ("cpl", "a"); // lsb
3758 emitcode ("inc", "a");
3760 emitcode ("add", "a,#1");
3761 emitcode ("xch", "a,b");
3762 emitcode ("cpl", "a"); // msb
3763 emitcode ("addc", "a,#0");
3764 emitcode ("xch", "a,b");
3767 emitcode ("", "%05d$:", lbl->key+100);
3768 aopPut (AOP (result), "a", 0);
3770 aopPut (AOP (result), "b", 1);
3774 /*-----------------------------------------------------------------*/
3775 /* genMult - generates code for multiplication */
3776 /*-----------------------------------------------------------------*/
3778 genMult (iCode * ic)
3780 operand *left = IC_LEFT (ic);
3781 operand *right = IC_RIGHT (ic);
3782 operand *result = IC_RESULT (ic);
3784 D (emitcode (";", "genMult "););
3786 /* assign the amsops */
3789 /* special cases first */
3791 if (AOP_TYPE (left) == AOP_CRY &&
3792 AOP_TYPE (right) == AOP_CRY)
3794 genMultbits (left, right, result);
3798 /* if both are of size == 1 */
3799 if (AOP_SIZE (left) == 1 &&
3800 AOP_SIZE (right) == 1)
3802 genMultOneByte (left, right, result);
3806 /* should have been converted to function call */
3810 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3811 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3812 freeAsmop (result, NULL, ic, TRUE);
3815 /*-----------------------------------------------------------------*/
3816 /* genDivbits :- division of bits */
3817 /*-----------------------------------------------------------------*/
3819 genDivbits (operand * left,
3826 /* the result must be bit */
3827 LOAD_AB_FOR_DIV (left, right, l);
3828 emitcode ("div", "ab");
3829 emitcode ("rrc", "a");
3830 aopPut (AOP (result), "c", 0);
3833 /*-----------------------------------------------------------------*/
3834 /* genDivOneByte : 8 bit division */
3835 /*-----------------------------------------------------------------*/
3837 genDivOneByte (operand * left,
3841 sym_link *opetype = operandType (result);
3846 size = AOP_SIZE (result) - 1;
3848 /* signed or unsigned */
3849 if (SPEC_USIGN (opetype))
3851 /* unsigned is easy */
3852 LOAD_AB_FOR_DIV (left, right, l);
3853 emitcode ("div", "ab");
3854 aopPut (AOP (result), "a", 0);
3856 aopPut (AOP (result), zero, offset++);
3860 /* signed is a little bit more difficult */
3862 /* save the signs of the operands */
3863 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3865 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3866 emitcode ("push", "acc"); /* save it on the stack */
3868 /* now sign adjust for both left & right */
3869 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3871 lbl = newiTempLabel (NULL);
3872 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3873 emitcode ("cpl", "a");
3874 emitcode ("inc", "a");
3875 emitcode ("", "%05d$:", (lbl->key + 100));
3876 emitcode ("mov", "b,a");
3878 /* sign adjust left side */
3879 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3882 lbl = newiTempLabel (NULL);
3883 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3884 emitcode ("cpl", "a");
3885 emitcode ("inc", "a");
3886 emitcode ("", "%05d$:", (lbl->key + 100));
3888 /* now the division */
3889 emitcode ("nop", "; workaround for DS80C390 div bug.");
3890 emitcode ("div", "ab");
3891 /* we are interested in the lower order
3893 emitcode ("mov", "b,a");
3894 lbl = newiTempLabel (NULL);
3895 emitcode ("pop", "acc");
3896 /* if there was an over flow we don't
3897 adjust the sign of the result */
3898 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3899 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3901 emitcode ("clr", "a");
3902 emitcode ("subb", "a,b");
3903 emitcode ("mov", "b,a");
3904 emitcode ("", "%05d$:", (lbl->key + 100));
3906 /* now we are done */
3907 aopPut (AOP (result), "b", 0);
3910 emitcode ("mov", "c,b.7");
3911 emitcode ("subb", "a,acc");
3914 aopPut (AOP (result), "a", offset++);
3918 /*-----------------------------------------------------------------*/
3919 /* genDiv - generates code for division */
3920 /*-----------------------------------------------------------------*/
3924 operand *left = IC_LEFT (ic);
3925 operand *right = IC_RIGHT (ic);
3926 operand *result = IC_RESULT (ic);
3928 D (emitcode (";", "genDiv ");
3931 /* assign the amsops */
3934 /* special cases first */
3936 if (AOP_TYPE (left) == AOP_CRY &&
3937 AOP_TYPE (right) == AOP_CRY)
3939 genDivbits (left, right, result);
3943 /* if both are of size == 1 */
3944 if (AOP_SIZE (left) == 1 &&
3945 AOP_SIZE (right) == 1)
3947 genDivOneByte (left, right, result);
3951 /* should have been converted to function call */
3954 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3955 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3956 freeAsmop (result, NULL, ic, TRUE);
3959 /*-----------------------------------------------------------------*/
3960 /* genModbits :- modulus of bits */
3961 /*-----------------------------------------------------------------*/
3963 genModbits (operand * left,
3970 /* the result must be bit */
3971 LOAD_AB_FOR_DIV (left, right, l);
3972 emitcode ("div", "ab");
3973 emitcode ("mov", "a,b");
3974 emitcode ("rrc", "a");
3975 aopPut (AOP (result), "c", 0);
3978 /*-----------------------------------------------------------------*/
3979 /* genModOneByte : 8 bit modulus */
3980 /*-----------------------------------------------------------------*/
3982 genModOneByte (operand * left,
3986 sym_link *opetype = operandType (result);
3990 /* signed or unsigned */
3991 if (SPEC_USIGN (opetype))
3993 /* unsigned is easy */
3994 LOAD_AB_FOR_DIV (left, right, l);
3995 emitcode ("div", "ab");
3996 aopPut (AOP (result), "b", 0);
4000 /* signed is a little bit more difficult */
4002 /* save the signs of the operands */
4003 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4006 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4007 emitcode ("push", "acc"); /* save it on the stack */
4009 /* now sign adjust for both left & right */
4010 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4013 lbl = newiTempLabel (NULL);
4014 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4015 emitcode ("cpl", "a");
4016 emitcode ("inc", "a");
4017 emitcode ("", "%05d$:", (lbl->key + 100));
4018 emitcode ("mov", "b,a");
4020 /* sign adjust left side */
4021 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4024 lbl = newiTempLabel (NULL);
4025 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4026 emitcode ("cpl", "a");
4027 emitcode ("inc", "a");
4028 emitcode ("", "%05d$:", (lbl->key + 100));
4030 /* now the multiplication */
4031 emitcode ("nop", "; workaround for DS80C390 div bug.");
4032 emitcode ("div", "ab");
4033 /* we are interested in the lower order
4035 lbl = newiTempLabel (NULL);
4036 emitcode ("pop", "acc");
4037 /* if there was an over flow we don't
4038 adjust the sign of the result */
4039 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4040 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4042 emitcode ("clr", "a");
4043 emitcode ("subb", "a,b");
4044 emitcode ("mov", "b,a");
4045 emitcode ("", "%05d$:", (lbl->key + 100));
4047 /* now we are done */
4048 aopPut (AOP (result), "b", 0);
4052 /*-----------------------------------------------------------------*/
4053 /* genMod - generates code for division */
4054 /*-----------------------------------------------------------------*/
4058 operand *left = IC_LEFT (ic);
4059 operand *right = IC_RIGHT (ic);
4060 operand *result = IC_RESULT (ic);
4062 D (emitcode (";", "genMod ");
4065 /* assign the amsops */
4068 /* special cases first */
4070 if (AOP_TYPE (left) == AOP_CRY &&
4071 AOP_TYPE (right) == AOP_CRY)
4073 genModbits (left, right, result);
4077 /* if both are of size == 1 */
4078 if (AOP_SIZE (left) == 1 &&
4079 AOP_SIZE (right) == 1)
4081 genModOneByte (left, right, result);
4085 /* should have been converted to function call */
4089 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4090 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4091 freeAsmop (result, NULL, ic, TRUE);
4094 /*-----------------------------------------------------------------*/
4095 /* genIfxJump :- will create a jump depending on the ifx */
4096 /*-----------------------------------------------------------------*/
4098 genIfxJump (iCode * ic, char *jval)
4101 symbol *tlbl = newiTempLabel (NULL);
4104 D (emitcode (";", "genIfxJump ");
4107 /* if true label then we jump if condition
4111 jlbl = IC_TRUE (ic);
4112 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4113 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4117 /* false label is present */
4118 jlbl = IC_FALSE (ic);
4119 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4120 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4122 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4123 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4125 emitcode (inst, "%05d$", tlbl->key + 100);
4126 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4127 emitcode ("", "%05d$:", tlbl->key + 100);
4129 /* mark the icode as generated */
4133 /*-----------------------------------------------------------------*/
4134 /* genCmp :- greater or less than comparison */
4135 /*-----------------------------------------------------------------*/
4137 genCmp (operand * left, operand * right,
4138 iCode * ic, iCode * ifx, int sign)
4140 int size, offset = 0;
4141 unsigned long lit = 0L;
4144 D (emitcode (";", "genCmp");
4147 result = IC_RESULT (ic);
4149 /* if left & right are bit variables */
4150 if (AOP_TYPE (left) == AOP_CRY &&
4151 AOP_TYPE (right) == AOP_CRY)
4153 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4154 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4158 /* subtract right from left if at the
4159 end the carry flag is set then we know that
4160 left is greater than right */
4161 size = max (AOP_SIZE (left), AOP_SIZE (right));
4163 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4164 if ((size == 1) && !sign &&
4165 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4167 symbol *lbl = newiTempLabel (NULL);
4168 emitcode ("cjne", "%s,%s,%05d$",
4169 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4170 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4172 emitcode ("", "%05d$:", lbl->key + 100);
4176 if (AOP_TYPE (right) == AOP_LIT)
4178 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4179 /* optimize if(x < 0) or if(x >= 0) */
4188 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4190 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4193 aopOp (result, ic, FALSE, FALSE);
4195 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4197 freeAsmop (result, NULL, ic, TRUE);
4198 genIfxJump (ifx, "acc.7");
4203 emitcode ("rlc", "a");
4205 goto release_freedLR;
4213 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4214 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4215 emitcode (";", "genCmp #2");
4216 if (sign && (size == 0))
4218 emitcode (";", "genCmp #3");
4219 emitcode ("xrl", "a,#0x80");
4220 if (AOP_TYPE (right) == AOP_LIT)
4222 unsigned long lit = (unsigned long)
4223 floatFromVal (AOP (right)->aopu.aop_lit);
4224 emitcode (";", "genCmp #3.1");
4225 emitcode ("subb", "a,#0x%02x",
4226 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4230 emitcode (";", "genCmp #3.2");
4231 if (AOP_NEEDSACC (right))
4233 emitcode ("push", "acc");
4235 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4236 FALSE, FALSE, FALSE));
4237 emitcode ("xrl", "b,#0x80");
4238 if (AOP_NEEDSACC (right))
4240 emitcode ("pop", "acc");
4242 emitcode ("subb", "a,b");
4249 emitcode (";", "genCmp #4");
4250 if (AOP_NEEDSACC (right))
4253 emitcode (";", "genCmp #4.1");
4254 emitcode ("xch", "a, b");
4255 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4256 emitcode ("xch", "a, b");
4261 emitcode (";", "genCmp #4.2");
4262 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4265 emitcode ("subb", "a,%s", s);
4272 /* Don't need the left & right operands any more; do need the result. */
4273 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4274 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4276 aopOp (result, ic, FALSE, FALSE);
4280 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4286 /* if the result is used in the next
4287 ifx conditional branch then generate
4288 code a little differently */
4291 genIfxJump (ifx, "c");
4297 /* leave the result in acc */
4299 freeAsmop (result, NULL, ic, TRUE);
4302 /*-----------------------------------------------------------------*/
4303 /* genCmpGt :- greater than comparison */
4304 /*-----------------------------------------------------------------*/
4306 genCmpGt (iCode * ic, iCode * ifx)
4308 operand *left, *right;
4309 sym_link *letype, *retype;
4312 D (emitcode (";", "genCmpGt ");
4315 left = IC_LEFT (ic);
4316 right = IC_RIGHT (ic);
4318 letype = getSpec (operandType (left));
4319 retype = getSpec (operandType (right));
4320 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4322 /* assign the left & right amsops */
4325 genCmp (right, left, ic, ifx, sign);
4328 /*-----------------------------------------------------------------*/
4329 /* genCmpLt - less than comparisons */
4330 /*-----------------------------------------------------------------*/
4332 genCmpLt (iCode * ic, iCode * ifx)
4334 operand *left, *right;
4335 sym_link *letype, *retype;
4338 D (emitcode (";", "genCmpLt "););
4340 left = IC_LEFT (ic);
4341 right = IC_RIGHT (ic);
4343 letype = getSpec (operandType (left));
4344 retype = getSpec (operandType (right));
4345 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4347 /* assign the left & right amsops */
4350 genCmp (left, right, ic, ifx, sign);
4353 /*-----------------------------------------------------------------*/
4354 /* gencjneshort - compare and jump if not equal */
4355 /*-----------------------------------------------------------------*/
4357 gencjneshort (operand * left, operand * right, symbol * lbl)
4359 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4361 unsigned long lit = 0L;
4363 D (emitcode (";", "gencjneshort");
4366 /* if the left side is a literal or
4367 if the right is in a pointer register and left
4369 if ((AOP_TYPE (left) == AOP_LIT) ||
4370 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4377 if (AOP_TYPE (right) == AOP_LIT)
4378 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4380 if (opIsGptr (left) || opIsGptr (right))
4382 /* We are comparing a generic pointer to something.
4383 * Exclude the generic type byte from the comparison.
4386 D (emitcode (";", "cjneshort: generic ptr special case.");
4391 /* if the right side is a literal then anything goes */
4392 if (AOP_TYPE (right) == AOP_LIT &&
4393 AOP_TYPE (left) != AOP_DIR)
4397 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4399 emitcode ("cjne", "a,%s,%05d$",
4400 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4406 /* if the right side is in a register or in direct space or
4407 if the left is a pointer register & right is not */
4408 else if (AOP_TYPE (right) == AOP_REG ||
4409 AOP_TYPE (right) == AOP_DIR ||
4410 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4411 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4415 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4416 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4417 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4418 emitcode ("jnz", "%05d$", lbl->key + 100);
4420 emitcode ("cjne", "a,%s,%05d$",
4421 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4428 /* right is a pointer reg need both a & b */
4431 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4432 if (strcmp (l, "b"))
4433 emitcode ("mov", "b,%s", l);
4434 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4435 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4441 /*-----------------------------------------------------------------*/
4442 /* gencjne - compare and jump if not equal */
4443 /*-----------------------------------------------------------------*/
4445 gencjne (operand * left, operand * right, symbol * lbl)
4447 symbol *tlbl = newiTempLabel (NULL);
4449 D (emitcode (";", "gencjne");
4452 gencjneshort (left, right, lbl);
4454 emitcode ("mov", "a,%s", one);
4455 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4456 emitcode ("", "%05d$:", lbl->key + 100);
4457 emitcode ("clr", "a");
4458 emitcode ("", "%05d$:", tlbl->key + 100);
4461 /*-----------------------------------------------------------------*/
4462 /* genCmpEq - generates code for equal to */
4463 /*-----------------------------------------------------------------*/
4465 genCmpEq (iCode * ic, iCode * ifx)
4467 operand *left, *right, *result;
4469 D (emitcode (";", "genCmpEq ");
4473 AOP_SET_LOCALS (ic);
4475 /* if literal, literal on the right or
4476 if the right is in a pointer register and left
4478 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4479 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4481 operand *t = IC_RIGHT (ic);
4482 IC_RIGHT (ic) = IC_LEFT (ic);
4486 if (ifx && /* !AOP_SIZE(result) */
4487 OP_SYMBOL (result) &&
4488 OP_SYMBOL (result)->regType == REG_CND)
4491 /* if they are both bit variables */
4492 if (AOP_TYPE (left) == AOP_CRY &&
4493 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4495 if (AOP_TYPE (right) == AOP_LIT)
4497 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4500 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4501 emitcode ("cpl", "c");
4505 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4509 emitcode ("clr", "c");
4511 /* AOP_TYPE(right) == AOP_CRY */
4515 symbol *lbl = newiTempLabel (NULL);
4516 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4517 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4518 emitcode ("cpl", "c");
4519 emitcode ("", "%05d$:", (lbl->key + 100));
4521 /* if true label then we jump if condition
4523 tlbl = newiTempLabel (NULL);
4526 emitcode ("jnc", "%05d$", tlbl->key + 100);
4527 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4531 emitcode ("jc", "%05d$", tlbl->key + 100);
4532 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4534 emitcode ("", "%05d$:", tlbl->key + 100);
4538 tlbl = newiTempLabel (NULL);
4539 gencjneshort (left, right, tlbl);
4542 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4543 emitcode ("", "%05d$:", tlbl->key + 100);
4547 symbol *lbl = newiTempLabel (NULL);
4548 emitcode ("sjmp", "%05d$", lbl->key + 100);
4549 emitcode ("", "%05d$:", tlbl->key + 100);
4550 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4551 emitcode ("", "%05d$:", lbl->key + 100);
4554 /* mark the icode as generated */
4557 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4558 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4562 /* if they are both bit variables */
4563 if (AOP_TYPE (left) == AOP_CRY &&
4564 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4566 if (AOP_TYPE (right) == AOP_LIT)
4568 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4571 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4572 emitcode ("cpl", "c");
4576 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4580 emitcode ("clr", "c");
4582 /* AOP_TYPE(right) == AOP_CRY */
4586 symbol *lbl = newiTempLabel (NULL);
4587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4588 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4589 emitcode ("cpl", "c");
4590 emitcode ("", "%05d$:", (lbl->key + 100));
4593 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4594 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4596 aopOp (result, ic, TRUE, FALSE);
4599 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4606 genIfxJump (ifx, "c");
4609 /* if the result is used in an arithmetic operation
4610 then put the result in place */
4615 gencjne (left, right, newiTempLabel (NULL));
4617 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 aopOp (result, ic, TRUE, FALSE);
4622 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4624 aopPut (AOP (result), "a", 0);
4629 genIfxJump (ifx, "a");
4632 /* if the result is used in an arithmetic operation
4633 then put the result in place */
4634 if (AOP_TYPE (result) != AOP_CRY)
4636 /* leave the result in acc */
4640 freeAsmop (result, NULL, ic, TRUE);
4643 /*-----------------------------------------------------------------*/
4644 /* ifxForOp - returns the icode containing the ifx for operand */
4645 /*-----------------------------------------------------------------*/
4647 ifxForOp (operand * op, iCode * ic)
4649 /* if true symbol then needs to be assigned */
4650 if (IS_TRUE_SYMOP (op))
4653 /* if this has register type condition and
4654 the next instruction is ifx with the same operand
4655 and live to of the operand is upto the ifx only then */
4657 ic->next->op == IFX &&
4658 IC_COND (ic->next)->key == op->key &&
4659 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4664 /*-----------------------------------------------------------------*/
4665 /* genAndOp - for && operation */
4666 /*-----------------------------------------------------------------*/
4668 genAndOp (iCode * ic)
4670 operand *left, *right, *result;
4673 D (emitcode (";", "genAndOp "););
4675 /* note here that && operations that are in an
4676 if statement are taken away by backPatchLabels
4677 only those used in arthmetic operations remain */
4679 AOP_SET_LOCALS (ic);
4681 /* if both are bit variables */
4682 if (AOP_TYPE (left) == AOP_CRY &&
4683 AOP_TYPE (right) == AOP_CRY)
4685 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4686 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4687 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4688 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4690 aopOp (result,ic,FALSE, FALSE);
4695 tlbl = newiTempLabel (NULL);
4697 emitcode ("jz", "%05d$", tlbl->key + 100);
4699 emitcode ("", "%05d$:", tlbl->key + 100);
4700 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4701 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4703 aopOp (result,ic,FALSE, FALSE);
4706 freeAsmop (result, NULL, ic, TRUE);
4710 /*-----------------------------------------------------------------*/
4711 /* genOrOp - for || operation */
4712 /*-----------------------------------------------------------------*/
4714 genOrOp (iCode * ic)
4716 operand *left, *right, *result;
4719 D (emitcode (";", "genOrOp "););
4721 /* note here that || operations that are in an
4722 if statement are taken away by backPatchLabels
4723 only those used in arthmetic operations remain */
4725 AOP_SET_LOCALS (ic);
4727 /* if both are bit variables */
4728 if (AOP_TYPE (left) == AOP_CRY &&
4729 AOP_TYPE (right) == AOP_CRY)
4731 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4732 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4733 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4736 aopOp (result,ic,FALSE, FALSE);
4742 tlbl = newiTempLabel (NULL);
4744 emitcode ("jnz", "%05d$", tlbl->key + 100);
4746 emitcode ("", "%05d$:", tlbl->key + 100);
4747 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 aopOp (result,ic,FALSE, FALSE);
4755 freeAsmop (result, NULL, ic, TRUE);
4758 /*-----------------------------------------------------------------*/
4759 /* isLiteralBit - test if lit == 2^n */
4760 /*-----------------------------------------------------------------*/
4762 isLiteralBit (unsigned long lit)
4764 unsigned long pw[32] =
4765 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4766 0x100L, 0x200L, 0x400L, 0x800L,
4767 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4768 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4769 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4770 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4771 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4774 for (idx = 0; idx < 32; idx++)
4780 /*-----------------------------------------------------------------*/
4781 /* continueIfTrue - */
4782 /*-----------------------------------------------------------------*/
4784 continueIfTrue (iCode * ic)
4787 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4791 /*-----------------------------------------------------------------*/
4793 /*-----------------------------------------------------------------*/
4795 jumpIfTrue (iCode * ic)
4798 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4802 /*-----------------------------------------------------------------*/
4803 /* jmpTrueOrFalse - */
4804 /*-----------------------------------------------------------------*/
4806 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4808 // ugly but optimized by peephole
4811 symbol *nlbl = newiTempLabel (NULL);
4812 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4813 emitcode ("", "%05d$:", tlbl->key + 100);
4814 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4815 emitcode ("", "%05d$:", nlbl->key + 100);
4819 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4820 emitcode ("", "%05d$:", tlbl->key + 100);
4825 // Generate code to perform a bit-wise logic operation
4826 // on two operands in far space (assumed to already have been
4827 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4828 // in far space. This requires pushing the result on the stack
4829 // then popping it into the result.
4831 genFarFarLogicOp(iCode *ic, char *logicOp)
4833 int size, resultSize, compSize;
4836 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4837 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4838 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4840 _startLazyDPSEvaluation();
4841 for (size = compSize; (size--); offset++)
4843 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4844 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4845 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4847 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4848 emitcode ("push", "acc");
4850 _endLazyDPSEvaluation();
4852 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4853 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4854 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4856 resultSize = AOP_SIZE(IC_RESULT(ic));
4858 ADJUST_PUSHED_RESULT(compSize, resultSize);
4860 _startLazyDPSEvaluation();
4863 emitcode ("pop", "acc");
4864 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4866 _endLazyDPSEvaluation();
4867 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4871 /*-----------------------------------------------------------------*/
4872 /* genAnd - code for and */
4873 /*-----------------------------------------------------------------*/
4875 genAnd (iCode * ic, iCode * ifx)
4877 operand *left, *right, *result;
4878 int size, offset = 0;
4879 unsigned long lit = 0L;
4884 D (emitcode (";", "genAnd "););
4886 AOP_OP_3_NOFATAL (ic, pushResult);
4887 AOP_SET_LOCALS (ic);
4891 genFarFarLogicOp(ic, "anl");
4896 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4898 AOP_TYPE (left), AOP_TYPE (right));
4899 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4901 AOP_SIZE (left), AOP_SIZE (right));
4904 /* if left is a literal & right is not then exchange them */
4905 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4906 AOP_NEEDSACC (left))
4908 operand *tmp = right;
4913 /* if result = right then exchange them */
4914 if (sameRegs (AOP (result), AOP (right)))
4916 operand *tmp = right;
4921 /* if right is bit then exchange them */
4922 if (AOP_TYPE (right) == AOP_CRY &&
4923 AOP_TYPE (left) != AOP_CRY)
4925 operand *tmp = right;
4929 if (AOP_TYPE (right) == AOP_LIT)
4930 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4932 size = AOP_SIZE (result);
4935 // result = bit & yy;
4936 if (AOP_TYPE (left) == AOP_CRY)
4938 // c = bit & literal;
4939 if (AOP_TYPE (right) == AOP_LIT)
4943 if (size && sameRegs (AOP (result), AOP (left)))
4946 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4951 if (size && (AOP_TYPE (result) == AOP_CRY))
4953 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4956 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4961 emitcode ("clr", "c");
4966 if (AOP_TYPE (right) == AOP_CRY)
4969 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4970 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4975 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4977 emitcode ("rrc", "a");
4978 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4986 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4987 genIfxJump (ifx, "c");
4991 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4992 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4993 if ((AOP_TYPE (right) == AOP_LIT) &&
4994 (AOP_TYPE (result) == AOP_CRY) &&
4995 (AOP_TYPE (left) != AOP_CRY))
4997 int posbit = isLiteralBit (lit);
5002 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5005 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5011 sprintf (buffer, "acc.%d", posbit & 0x07);
5012 genIfxJump (ifx, buffer);
5019 symbol *tlbl = newiTempLabel (NULL);
5020 int sizel = AOP_SIZE (left);
5022 emitcode ("setb", "c");
5025 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5027 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5029 if ((posbit = isLiteralBit (bytelit)) != 0)
5030 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5033 if (bytelit != 0x0FFL)
5034 emitcode ("anl", "a,%s",
5035 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5036 emitcode ("jnz", "%05d$", tlbl->key + 100);
5041 // bit = left & literal
5044 emitcode ("clr", "c");
5045 emitcode ("", "%05d$:", tlbl->key + 100);
5047 // if(left & literal)
5051 jmpTrueOrFalse (ifx, tlbl);
5059 /* if left is same as result */
5060 if (sameRegs (AOP (result), AOP (left)))
5062 for (; size--; offset++)
5064 if (AOP_TYPE (right) == AOP_LIT)
5066 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5068 else if (bytelit == 0)
5069 aopPut (AOP (result), zero, offset);
5070 else if (IS_AOP_PREG (result))
5072 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5073 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5074 aopPut (AOP (result), "a", offset);
5077 emitcode ("anl", "%s,%s",
5078 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5079 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5083 if (AOP_TYPE (left) == AOP_ACC)
5084 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5087 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5088 if (IS_AOP_PREG (result))
5090 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5091 aopPut (AOP (result), "a", offset);
5095 emitcode ("anl", "%s,a",
5096 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5103 // left & result in different registers
5104 if (AOP_TYPE (result) == AOP_CRY)
5107 // if(size), result in bit
5108 // if(!size && ifx), conditional oper: if(left & right)
5109 symbol *tlbl = newiTempLabel (NULL);
5110 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5112 emitcode ("setb", "c");
5115 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5116 emitcode ("anl", "a,%s",
5117 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5118 emitcode ("jnz", "%05d$", tlbl->key + 100);
5124 emitcode ("", "%05d$:", tlbl->key + 100);
5128 jmpTrueOrFalse (ifx, tlbl);
5132 for (; (size--); offset++)
5135 // result = left & right
5136 if (AOP_TYPE (right) == AOP_LIT)
5138 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5140 aopPut (AOP (result),
5141 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5145 else if (bytelit == 0)
5147 aopPut (AOP (result), zero, offset);
5150 D (emitcode (";", "better literal AND.");
5152 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5153 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5154 FALSE, FALSE, FALSE));
5159 // faster than result <- left, anl result,right
5160 // and better if result is SFR
5161 if (AOP_TYPE (left) == AOP_ACC)
5163 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5164 FALSE, FALSE, FALSE));
5168 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5169 emitcode ("anl", "a,%s",
5170 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5173 aopPut (AOP (result), "a", offset);
5179 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5180 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5181 freeAsmop (result, NULL, ic, TRUE);
5185 /*-----------------------------------------------------------------*/
5186 /* genOr - code for or */
5187 /*-----------------------------------------------------------------*/
5189 genOr (iCode * ic, iCode * ifx)
5191 operand *left, *right, *result;
5192 int size, offset = 0;
5193 unsigned long lit = 0L;
5196 D (emitcode (";", "genOr "););
5198 AOP_OP_3_NOFATAL (ic, pushResult);
5199 AOP_SET_LOCALS (ic);
5203 genFarFarLogicOp(ic, "orl");
5209 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5211 AOP_TYPE (left), AOP_TYPE (right));
5212 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5214 AOP_SIZE (left), AOP_SIZE (right));
5217 /* if left is a literal & right is not then exchange them */
5218 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5219 AOP_NEEDSACC (left))
5221 operand *tmp = right;
5226 /* if result = right then exchange them */
5227 if (sameRegs (AOP (result), AOP (right)))
5229 operand *tmp = right;
5234 /* if right is bit then exchange them */
5235 if (AOP_TYPE (right) == AOP_CRY &&
5236 AOP_TYPE (left) != AOP_CRY)
5238 operand *tmp = right;
5242 if (AOP_TYPE (right) == AOP_LIT)
5243 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5245 size = AOP_SIZE (result);
5249 if (AOP_TYPE (left) == AOP_CRY)
5251 if (AOP_TYPE (right) == AOP_LIT)
5253 // c = bit & literal;
5256 // lit != 0 => result = 1
5257 if (AOP_TYPE (result) == AOP_CRY)
5260 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5262 continueIfTrue (ifx);
5265 emitcode ("setb", "c");
5269 // lit == 0 => result = left
5270 if (size && sameRegs (AOP (result), AOP (left)))
5272 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5277 if (AOP_TYPE (right) == AOP_CRY)
5280 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5281 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5286 symbol *tlbl = newiTempLabel (NULL);
5287 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5288 emitcode ("setb", "c");
5289 emitcode ("jb", "%s,%05d$",
5290 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5292 emitcode ("jnz", "%05d$", tlbl->key + 100);
5293 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5295 jmpTrueOrFalse (ifx, tlbl);
5301 emitcode ("", "%05d$:", tlbl->key + 100);
5310 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5311 genIfxJump (ifx, "c");
5315 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5316 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5317 if ((AOP_TYPE (right) == AOP_LIT) &&
5318 (AOP_TYPE (result) == AOP_CRY) &&
5319 (AOP_TYPE (left) != AOP_CRY))
5325 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5327 continueIfTrue (ifx);
5332 // lit = 0, result = boolean(left)
5334 emitcode ("setb", "c");
5338 symbol *tlbl = newiTempLabel (NULL);
5339 emitcode ("jnz", "%05d$", tlbl->key + 100);
5341 emitcode ("", "%05d$:", tlbl->key + 100);
5345 genIfxJump (ifx, "a");
5353 /* if left is same as result */
5354 if (sameRegs (AOP (result), AOP (left)))
5356 for (; size--; offset++)
5358 if (AOP_TYPE (right) == AOP_LIT)
5360 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5366 if (IS_AOP_PREG (left))
5368 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5369 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5370 aopPut (AOP (result), "a", offset);
5374 emitcode ("orl", "%s,%s",
5375 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5376 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5382 if (AOP_TYPE (left) == AOP_ACC)
5384 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5388 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5389 if (IS_AOP_PREG (left))
5391 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5392 aopPut (AOP (result), "a", offset);
5396 emitcode ("orl", "%s,a",
5397 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5405 // left & result in different registers
5406 if (AOP_TYPE (result) == AOP_CRY)
5409 // if(size), result in bit
5410 // if(!size && ifx), conditional oper: if(left | right)
5411 symbol *tlbl = newiTempLabel (NULL);
5412 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5414 emitcode ("setb", "c");
5417 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5418 emitcode ("orl", "a,%s",
5419 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5420 emitcode ("jnz", "%05d$", tlbl->key + 100);
5426 emitcode ("", "%05d$:", tlbl->key + 100);
5430 jmpTrueOrFalse (ifx, tlbl);
5434 for (; (size--); offset++)
5437 // result = left & right
5438 if (AOP_TYPE (right) == AOP_LIT)
5440 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5442 aopPut (AOP (result),
5443 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5447 D (emitcode (";", "better literal OR.");
5449 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5450 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5451 FALSE, FALSE, FALSE));
5456 // faster than result <- left, anl result,right
5457 // and better if result is SFR
5458 if (AOP_TYPE (left) == AOP_ACC)
5460 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5461 FALSE, FALSE, FALSE));
5465 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5466 emitcode ("orl", "a,%s",
5467 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5470 aopPut (AOP (result), "a", offset);
5476 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5478 freeAsmop (result, NULL, ic, TRUE);
5481 /*-----------------------------------------------------------------*/
5482 /* genXor - code for xclusive or */
5483 /*-----------------------------------------------------------------*/
5485 genXor (iCode * ic, iCode * ifx)
5487 operand *left, *right, *result;
5488 int size, offset = 0;
5489 unsigned long lit = 0L;
5492 D (emitcode (";", "genXor "););
5494 AOP_OP_3_NOFATAL (ic, pushResult);
5495 AOP_SET_LOCALS (ic);
5499 genFarFarLogicOp(ic, "xrl");
5504 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5506 AOP_TYPE (left), AOP_TYPE (right));
5507 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5509 AOP_SIZE (left), AOP_SIZE (right));
5512 /* if left is a literal & right is not ||
5513 if left needs acc & right does not */
5514 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5515 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5517 operand *tmp = right;
5522 /* if result = right then exchange them */
5523 if (sameRegs (AOP (result), AOP (right)))
5525 operand *tmp = right;
5530 /* if right is bit then exchange them */
5531 if (AOP_TYPE (right) == AOP_CRY &&
5532 AOP_TYPE (left) != AOP_CRY)
5534 operand *tmp = right;
5538 if (AOP_TYPE (right) == AOP_LIT)
5539 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5541 size = AOP_SIZE (result);
5545 if (AOP_TYPE (left) == AOP_CRY)
5547 if (AOP_TYPE (right) == AOP_LIT)
5549 // c = bit & literal;
5552 // lit>>1 != 0 => result = 1
5553 if (AOP_TYPE (result) == AOP_CRY)
5556 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5558 continueIfTrue (ifx);
5561 emitcode ("setb", "c");
5568 // lit == 0, result = left
5569 if (size && sameRegs (AOP (result), AOP (left)))
5571 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5575 // lit == 1, result = not(left)
5576 if (size && sameRegs (AOP (result), AOP (left)))
5578 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5583 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5584 emitcode ("cpl", "c");
5593 symbol *tlbl = newiTempLabel (NULL);
5594 if (AOP_TYPE (right) == AOP_CRY)
5597 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5601 int sizer = AOP_SIZE (right);
5603 // if val>>1 != 0, result = 1
5604 emitcode ("setb", "c");
5607 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5609 // test the msb of the lsb
5610 emitcode ("anl", "a,#0xfe");
5611 emitcode ("jnz", "%05d$", tlbl->key + 100);
5615 emitcode ("rrc", "a");
5617 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5618 emitcode ("cpl", "c");
5619 emitcode ("", "%05d$:", (tlbl->key + 100));
5626 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5627 genIfxJump (ifx, "c");
5631 if (sameRegs (AOP (result), AOP (left)))
5633 /* if left is same as result */
5634 for (; size--; offset++)
5636 if (AOP_TYPE (right) == AOP_LIT)
5638 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5640 else if (IS_AOP_PREG (left))
5642 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5643 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5644 aopPut (AOP (result), "a", offset);
5647 emitcode ("xrl", "%s,%s",
5648 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5649 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5653 if (AOP_TYPE (left) == AOP_ACC)
5654 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5657 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5658 if (IS_AOP_PREG (left))
5660 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5661 aopPut (AOP (result), "a", offset);
5664 emitcode ("xrl", "%s,a",
5665 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5672 // left & result in different registers
5673 if (AOP_TYPE (result) == AOP_CRY)
5676 // if(size), result in bit
5677 // if(!size && ifx), conditional oper: if(left ^ right)
5678 symbol *tlbl = newiTempLabel (NULL);
5679 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5681 emitcode ("setb", "c");
5684 if ((AOP_TYPE (right) == AOP_LIT) &&
5685 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5687 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5691 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5692 emitcode ("xrl", "a,%s",
5693 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5695 emitcode ("jnz", "%05d$", tlbl->key + 100);
5701 emitcode ("", "%05d$:", tlbl->key + 100);
5705 jmpTrueOrFalse (ifx, tlbl);
5708 for (; (size--); offset++)
5711 // result = left & right
5712 if (AOP_TYPE (right) == AOP_LIT)
5714 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5716 aopPut (AOP (result),
5717 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5721 D (emitcode (";", "better literal XOR.");
5723 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5724 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5725 FALSE, FALSE, FALSE));
5729 // faster than result <- left, anl result,right
5730 // and better if result is SFR
5731 if (AOP_TYPE (left) == AOP_ACC)
5733 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5734 FALSE, FALSE, FALSE));
5738 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5739 emitcode ("xrl", "a,%s",
5740 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5743 aopPut (AOP (result), "a", offset);
5748 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5749 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5750 freeAsmop (result, NULL, ic, TRUE);
5753 /*-----------------------------------------------------------------*/
5754 /* genInline - write the inline code out */
5755 /*-----------------------------------------------------------------*/
5757 genInline (iCode * ic)
5759 char buffer[MAX_INLINEASM];
5763 D (emitcode (";", "genInline ");
5766 _G.inLine += (!options.asmpeep);
5767 strcpy (buffer, IC_INLINE (ic));
5769 /* emit each line as a code */
5794 /* emitcode("",buffer); */
5795 _G.inLine -= (!options.asmpeep);
5798 /*-----------------------------------------------------------------*/
5799 /* genRRC - rotate right with carry */
5800 /*-----------------------------------------------------------------*/
5804 operand *left, *result;
5805 int size, offset = 0;
5808 D (emitcode (";", "genRRC ");
5811 /* rotate right with carry */
5812 left = IC_LEFT (ic);
5813 result = IC_RESULT (ic);
5814 aopOp (left, ic, FALSE, FALSE);
5815 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5817 /* move it to the result */
5818 size = AOP_SIZE (result);
5822 _startLazyDPSEvaluation ();
5825 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5827 emitcode ("rrc", "a");
5828 if (AOP_SIZE (result) > 1)
5829 aopPut (AOP (result), "a", offset--);
5831 _endLazyDPSEvaluation ();
5833 /* now we need to put the carry into the
5834 highest order byte of the result */
5835 if (AOP_SIZE (result) > 1)
5837 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5840 emitcode ("mov", "acc.7,c");
5841 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5842 freeAsmop (left, NULL, ic, TRUE);
5843 freeAsmop (result, NULL, ic, TRUE);
5846 /*-----------------------------------------------------------------*/
5847 /* genRLC - generate code for rotate left with carry */
5848 /*-----------------------------------------------------------------*/
5852 operand *left, *result;
5853 int size, offset = 0;
5856 D (emitcode (";", "genRLC ");
5859 /* rotate right with carry */
5860 left = IC_LEFT (ic);
5861 result = IC_RESULT (ic);
5862 aopOp (left, ic, FALSE, FALSE);
5863 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5865 /* move it to the result */
5866 size = AOP_SIZE (result);
5870 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5872 emitcode ("add", "a,acc");
5873 if (AOP_SIZE (result) > 1)
5875 aopPut (AOP (result), "a", offset++);
5878 _startLazyDPSEvaluation ();
5881 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5883 emitcode ("rlc", "a");
5884 if (AOP_SIZE (result) > 1)
5885 aopPut (AOP (result), "a", offset++);
5887 _endLazyDPSEvaluation ();
5889 /* now we need to put the carry into the
5890 highest order byte of the result */
5891 if (AOP_SIZE (result) > 1)
5893 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5896 emitcode ("mov", "acc.0,c");
5897 aopPut (AOP (result), "a", 0);
5898 freeAsmop (left, NULL, ic, TRUE);
5899 freeAsmop (result, NULL, ic, TRUE);
5902 /*-----------------------------------------------------------------*/
5903 /* genGetHbit - generates code get highest order bit */
5904 /*-----------------------------------------------------------------*/
5906 genGetHbit (iCode * ic)
5908 operand *left, *result;
5909 left = IC_LEFT (ic);
5910 result = IC_RESULT (ic);
5911 aopOp (left, ic, FALSE, FALSE);
5912 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5914 D (emitcode (";", "genGetHbit ");
5917 /* get the highest order byte into a */
5918 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5919 if (AOP_TYPE (result) == AOP_CRY)
5921 emitcode ("rlc", "a");
5926 emitcode ("rl", "a");
5927 emitcode ("anl", "a,#0x01");
5932 freeAsmop (left, NULL, ic, TRUE);
5933 freeAsmop (result, NULL, ic, TRUE);
5936 /*-----------------------------------------------------------------*/
5937 /* AccRol - rotate left accumulator by known count */
5938 /*-----------------------------------------------------------------*/
5940 AccRol (int shCount)
5942 shCount &= 0x0007; // shCount : 0..7
5949 emitcode ("rl", "a");
5952 emitcode ("rl", "a");
5953 emitcode ("rl", "a");
5956 emitcode ("swap", "a");
5957 emitcode ("rr", "a");
5960 emitcode ("swap", "a");
5963 emitcode ("swap", "a");
5964 emitcode ("rl", "a");
5967 emitcode ("rr", "a");
5968 emitcode ("rr", "a");
5971 emitcode ("rr", "a");
5976 /*-----------------------------------------------------------------*/
5977 /* AccLsh - left shift accumulator by known count */
5978 /*-----------------------------------------------------------------*/
5980 AccLsh (int shCount)
5985 emitcode ("add", "a,acc");
5986 else if (shCount == 2)
5988 emitcode ("add", "a,acc");
5989 emitcode ("add", "a,acc");
5993 /* rotate left accumulator */
5995 /* and kill the lower order bits */
5996 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6001 /*-----------------------------------------------------------------*/
6002 /* AccRsh - right shift accumulator by known count */
6003 /*-----------------------------------------------------------------*/
6005 AccRsh (int shCount)
6012 emitcode ("rrc", "a");
6016 /* rotate right accumulator */
6017 AccRol (8 - shCount);
6018 /* and kill the higher order bits */
6019 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6026 /*-----------------------------------------------------------------*/
6027 /* AccSRsh - signed right shift accumulator by known count */
6028 /*-----------------------------------------------------------------*/
6030 AccSRsh (int shCount)
6037 emitcode ("mov", "c,acc.7");
6038 emitcode ("rrc", "a");
6040 else if (shCount == 2)
6042 emitcode ("mov", "c,acc.7");
6043 emitcode ("rrc", "a");
6044 emitcode ("mov", "c,acc.7");
6045 emitcode ("rrc", "a");
6049 tlbl = newiTempLabel (NULL);
6050 /* rotate right accumulator */
6051 AccRol (8 - shCount);
6052 /* and kill the higher order bits */
6053 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6054 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6055 emitcode ("orl", "a,#0x%02x",
6056 (unsigned char) ~SRMask[shCount]);
6057 emitcode ("", "%05d$:", tlbl->key + 100);
6065 /*-----------------------------------------------------------------*/
6066 /* shiftR1Left2Result - shift right one byte from left to result */
6067 /*-----------------------------------------------------------------*/
6069 shiftR1Left2Result (operand * left, int offl,
6070 operand * result, int offr,
6071 int shCount, int sign)
6073 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6074 /* shift right accumulator */
6079 aopPut (AOP (result), "a", offr);
6085 /*-----------------------------------------------------------------*/
6086 /* shiftL1Left2Result - shift left one byte from left to result */
6087 /*-----------------------------------------------------------------*/
6089 shiftL1Left2Result (operand * left, int offl,
6090 operand * result, int offr, int shCount)
6093 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6095 /* shift left accumulator */
6097 aopPut (AOP (result), "a", offr);
6103 /*-----------------------------------------------------------------*/
6104 /* movLeft2Result - move byte from left to result */
6105 /*-----------------------------------------------------------------*/
6107 movLeft2Result (operand * left, int offl,
6108 operand * result, int offr, int sign)
6111 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6113 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6115 if (*l == '@' && (IS_AOP_PREG (result)))
6117 emitcode ("mov", "a,%s", l);
6118 aopPut (AOP (result), "a", offr);
6123 aopPut (AOP (result), l, offr);
6126 /* MSB sign in acc.7 ! */
6127 if (getDataSize (left) == offl + 1)
6129 emitcode ("mov", "a,%s", l);
6130 aopPut (AOP (result), "a", offr);
6140 /*-----------------------------------------------------------------*/
6141 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6142 /*-----------------------------------------------------------------*/
6146 emitcode ("rrc", "a");
6147 emitcode ("xch", "a,%s", x);
6148 emitcode ("rrc", "a");
6149 emitcode ("xch", "a,%s", x);
6155 /*-----------------------------------------------------------------*/
6156 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6157 /*-----------------------------------------------------------------*/
6161 emitcode ("xch", "a,%s", x);
6162 emitcode ("rlc", "a");
6163 emitcode ("xch", "a,%s", x);
6164 emitcode ("rlc", "a");
6170 /*-----------------------------------------------------------------*/
6171 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6172 /*-----------------------------------------------------------------*/
6176 emitcode ("xch", "a,%s", x);
6177 emitcode ("add", "a,acc");
6178 emitcode ("xch", "a,%s", x);
6179 emitcode ("rlc", "a");
6185 /*-----------------------------------------------------------------*/
6186 /* AccAXLsh - left shift a:x by known count (0..7) */
6187 /*-----------------------------------------------------------------*/
6189 AccAXLsh (char *x, int shCount)
6204 case 5: // AAAAABBB:CCCCCDDD
6206 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6208 emitcode ("anl", "a,#0x%02x",
6209 SLMask[shCount]); // BBB00000:CCCCCDDD
6211 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6213 AccRol (shCount); // DDDCCCCC:BBB00000
6215 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6217 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6219 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6221 emitcode ("anl", "a,#0x%02x",
6222 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6224 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6226 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6229 case 6: // AAAAAABB:CCCCCCDD
6230 emitcode ("anl", "a,#0x%02x",
6231 SRMask[shCount]); // 000000BB:CCCCCCDD
6232 emitcode ("mov", "c,acc.0"); // c = B
6233 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6235 AccAXRrl1 (x); // BCCCCCCD:D000000B
6236 AccAXRrl1 (x); // BBCCCCCC:DD000000
6238 emitcode("rrc","a");
6239 emitcode("xch","a,%s", x);
6240 emitcode("rrc","a");
6241 emitcode("mov","c,acc.0"); //<< get correct bit
6242 emitcode("xch","a,%s", x);
6244 emitcode("rrc","a");
6245 emitcode("xch","a,%s", x);
6246 emitcode("rrc","a");
6247 emitcode("xch","a,%s", x);
6250 case 7: // a:x <<= 7
6252 emitcode ("anl", "a,#0x%02x",
6253 SRMask[shCount]); // 0000000B:CCCCCCCD
6255 emitcode ("mov", "c,acc.0"); // c = B
6257 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6259 AccAXRrl1 (x); // BCCCCCCC:D0000000
6270 /*-----------------------------------------------------------------*/
6271 /* AccAXRsh - right shift a:x known count (0..7) */
6272 /*-----------------------------------------------------------------*/
6274 AccAXRsh (char *x, int shCount)
6282 AccAXRrl1 (x); // 0->a:x
6287 AccAXRrl1 (x); // 0->a:x
6290 AccAXRrl1 (x); // 0->a:x
6295 case 5: // AAAAABBB:CCCCCDDD = a:x
6297 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6299 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6301 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6303 emitcode ("anl", "a,#0x%02x",
6304 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6306 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6308 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6310 emitcode ("anl", "a,#0x%02x",
6311 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6313 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6315 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6317 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6320 case 6: // AABBBBBB:CCDDDDDD
6322 emitcode ("mov", "c,acc.7");
6323 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6325 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6327 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6329 emitcode ("anl", "a,#0x%02x",
6330 SRMask[shCount]); // 000000AA:BBBBBBCC
6333 case 7: // ABBBBBBB:CDDDDDDD
6335 emitcode ("mov", "c,acc.7"); // c = A
6337 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6339 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6341 emitcode ("anl", "a,#0x%02x",
6342 SRMask[shCount]); // 0000000A:BBBBBBBC
6353 /*-----------------------------------------------------------------*/
6354 /* AccAXRshS - right shift signed a:x known count (0..7) */
6355 /*-----------------------------------------------------------------*/
6357 AccAXRshS (char *x, int shCount)
6365 emitcode ("mov", "c,acc.7");
6366 AccAXRrl1 (x); // s->a:x
6370 emitcode ("mov", "c,acc.7");
6371 AccAXRrl1 (x); // s->a:x
6373 emitcode ("mov", "c,acc.7");
6374 AccAXRrl1 (x); // s->a:x
6379 case 5: // AAAAABBB:CCCCCDDD = a:x
6381 tlbl = newiTempLabel (NULL);
6382 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6384 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6386 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6388 emitcode ("anl", "a,#0x%02x",
6389 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6391 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6393 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6395 emitcode ("anl", "a,#0x%02x",
6396 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6398 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6400 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6402 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6404 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6405 emitcode ("orl", "a,#0x%02x",
6406 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6408 emitcode ("", "%05d$:", tlbl->key + 100);
6409 break; // SSSSAAAA:BBBCCCCC
6411 case 6: // AABBBBBB:CCDDDDDD
6413 tlbl = newiTempLabel (NULL);
6414 emitcode ("mov", "c,acc.7");
6415 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6417 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6419 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6421 emitcode ("anl", "a,#0x%02x",
6422 SRMask[shCount]); // 000000AA:BBBBBBCC
6424 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6425 emitcode ("orl", "a,#0x%02x",
6426 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6428 emitcode ("", "%05d$:", tlbl->key + 100);
6430 case 7: // ABBBBBBB:CDDDDDDD
6432 tlbl = newiTempLabel (NULL);
6433 emitcode ("mov", "c,acc.7"); // c = A
6435 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6437 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6439 emitcode ("anl", "a,#0x%02x",
6440 SRMask[shCount]); // 0000000A:BBBBBBBC
6442 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6443 emitcode ("orl", "a,#0x%02x",
6444 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6446 emitcode ("", "%05d$:", tlbl->key + 100);
6456 /*-----------------------------------------------------------------*/
6457 /* shiftL2Left2Result - shift left two bytes from left to result */
6458 /*-----------------------------------------------------------------*/
6460 shiftL2Left2Result (operand * left, int offl,
6461 operand * result, int offr, int shCount)
6463 if (sameRegs (AOP (result), AOP (left)) &&
6464 ((offl + MSB16) == offr))
6466 /* don't crash result[offr] */
6467 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6468 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6472 movLeft2Result (left, offl, result, offr, 0);
6473 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6475 /* ax << shCount (x = lsb(result)) */
6476 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6477 aopPut (AOP (result), "a", offr + MSB16);
6483 /*-----------------------------------------------------------------*/
6484 /* shiftR2Left2Result - shift right two bytes from left to result */
6485 /*-----------------------------------------------------------------*/
6487 shiftR2Left2Result (operand * left, int offl,
6488 operand * result, int offr,
6489 int shCount, int sign)
6491 if (sameRegs (AOP (result), AOP (left)) &&
6492 ((offl + MSB16) == offr))
6494 /* don't crash result[offr] */
6495 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6496 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6500 movLeft2Result (left, offl, result, offr, 0);
6501 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6503 /* a:x >> shCount (x = lsb(result)) */
6505 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6507 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6508 if (getDataSize (result) > 1)
6509 aopPut (AOP (result), "a", offr + MSB16);
6515 /*-----------------------------------------------------------------*/
6516 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6517 /*-----------------------------------------------------------------*/
6519 shiftLLeftOrResult (operand * left, int offl,
6520 operand * result, int offr, int shCount)
6522 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6523 /* shift left accumulator */
6525 /* or with result */
6526 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6527 /* back to result */
6528 aopPut (AOP (result), "a", offr);
6534 /*-----------------------------------------------------------------*/
6535 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6536 /*-----------------------------------------------------------------*/
6538 shiftRLeftOrResult (operand * left, int offl,
6539 operand * result, int offr, int shCount)
6541 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6542 /* shift right accumulator */
6544 /* or with result */
6545 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6546 /* back to result */
6547 aopPut (AOP (result), "a", offr);
6553 /*-----------------------------------------------------------------*/
6554 /* genlshOne - left shift a one byte quantity by known count */
6555 /*-----------------------------------------------------------------*/
6557 genlshOne (operand * result, operand * left, int shCount)
6559 D (emitcode (";", "genlshOne ");
6561 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6567 /*-----------------------------------------------------------------*/
6568 /* genlshTwo - left shift two bytes by known amount != 0 */
6569 /*-----------------------------------------------------------------*/
6571 genlshTwo (operand * result, operand * left, int shCount)
6575 D (emitcode (";", "genlshTwo ");
6578 size = getDataSize (result);
6580 /* if shCount >= 8 */
6588 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6590 movLeft2Result (left, LSB, result, MSB16, 0);
6592 aopPut (AOP (result), zero, LSB);
6595 /* 1 <= shCount <= 7 */
6599 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6601 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6608 /*-----------------------------------------------------------------*/
6609 /* shiftLLong - shift left one long from left to result */
6610 /* offl = LSB or MSB16 */
6611 /*-----------------------------------------------------------------*/
6613 shiftLLong (operand * left, operand * result, int offr)
6616 int size = AOP_SIZE (result);
6618 if (size >= LSB + offr)
6620 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6622 emitcode ("add", "a,acc");
6623 if (sameRegs (AOP (left), AOP (result)) &&
6624 size >= MSB16 + offr && offr != LSB)
6625 emitcode ("xch", "a,%s",
6626 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6628 aopPut (AOP (result), "a", LSB + offr);
6631 if (size >= MSB16 + offr)
6633 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6635 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6638 emitcode ("rlc", "a");
6639 if (sameRegs (AOP (left), AOP (result)) &&
6640 size >= MSB24 + offr && offr != LSB)
6641 emitcode ("xch", "a,%s",
6642 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6644 aopPut (AOP (result), "a", MSB16 + offr);
6647 if (size >= MSB24 + offr)
6649 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6651 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6654 emitcode ("rlc", "a");
6655 if (sameRegs (AOP (left), AOP (result)) &&
6656 size >= MSB32 + offr && offr != LSB)
6657 emitcode ("xch", "a,%s",
6658 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6660 aopPut (AOP (result), "a", MSB24 + offr);
6663 if (size > MSB32 + offr)
6665 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6667 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6670 emitcode ("rlc", "a");
6671 aopPut (AOP (result), "a", MSB32 + offr);
6674 aopPut (AOP (result), zero, LSB);
6680 /*-----------------------------------------------------------------*/
6681 /* genlshFour - shift four byte by a known amount != 0 */
6682 /*-----------------------------------------------------------------*/
6684 genlshFour (operand * result, operand * left, int shCount)
6688 D (emitcode (";", "genlshFour ");
6691 size = AOP_SIZE (result);
6693 /* if shifting more that 3 bytes */
6698 /* lowest order of left goes to the highest
6699 order of the destination */
6700 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6702 movLeft2Result (left, LSB, result, MSB32, 0);
6703 aopPut (AOP (result), zero, LSB);
6704 aopPut (AOP (result), zero, MSB16);
6705 aopPut (AOP (result), zero, MSB24);
6709 /* more than two bytes */
6710 else if (shCount >= 16)
6712 /* lower order two bytes goes to higher order two bytes */
6714 /* if some more remaining */
6716 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6719 movLeft2Result (left, MSB16, result, MSB32, 0);
6720 movLeft2Result (left, LSB, result, MSB24, 0);
6722 aopPut (AOP (result), zero, MSB16);
6723 aopPut (AOP (result), zero, LSB);
6727 /* if more than 1 byte */
6728 else if (shCount >= 8)
6730 /* lower order three bytes goes to higher order three bytes */
6735 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6737 movLeft2Result (left, LSB, result, MSB16, 0);
6743 movLeft2Result (left, MSB24, result, MSB32, 0);
6744 movLeft2Result (left, MSB16, result, MSB24, 0);
6745 movLeft2Result (left, LSB, result, MSB16, 0);
6746 aopPut (AOP (result), zero, LSB);
6748 else if (shCount == 1)
6749 shiftLLong (left, result, MSB16);
6752 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6753 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6754 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6755 aopPut (AOP (result), zero, LSB);
6760 /* 1 <= shCount <= 7 */
6761 else if (shCount <= 2)
6763 shiftLLong (left, result, LSB);
6765 shiftLLong (result, result, LSB);
6767 /* 3 <= shCount <= 7, optimize */
6770 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6771 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6772 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6779 /*-----------------------------------------------------------------*/
6780 /* genLeftShiftLiteral - left shifting by known count */
6781 /*-----------------------------------------------------------------*/
6783 genLeftShiftLiteral (operand * left,
6788 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6791 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6794 freeAsmop (right, NULL, ic, TRUE);
6796 aopOp (left, ic, FALSE, FALSE);
6797 aopOp (result, ic, FALSE, TRUE);
6799 size = getSize (operandType (result));
6802 emitcode ("; shift left ", "result %d, left %d", size,
6806 /* I suppose that the left size >= result size */
6811 movLeft2Result (left, size, result, size, 0);
6815 else if (shCount >= (size * 8))
6817 aopPut (AOP (result), zero, size);
6823 genlshOne (result, left, shCount);
6827 case 3: /* bug: this is for generic pointers, I bet. */
6828 genlshTwo (result, left, shCount);
6832 genlshFour (result, left, shCount);
6836 freeAsmop (left, NULL, ic, TRUE);
6837 freeAsmop (result, NULL, ic, TRUE);
6841 /*-----------------------------------------------------------------*/
6842 /* genLeftShift - generates code for left shifting */
6843 /*-----------------------------------------------------------------*/
6845 genLeftShift (iCode * ic)
6847 operand *left, *right, *result;
6850 symbol *tlbl, *tlbl1;
6852 D (emitcode (";", "genLeftShift "););
6854 right = IC_RIGHT (ic);
6855 left = IC_LEFT (ic);
6856 result = IC_RESULT (ic);
6858 aopOp (right, ic, FALSE, FALSE);
6861 /* if the shift count is known then do it
6862 as efficiently as possible */
6863 if (AOP_TYPE (right) == AOP_LIT)
6865 genLeftShiftLiteral (left, right, result, ic);
6870 /* shift count is unknown then we have to form
6871 a loop get the loop count in B : Note: we take
6872 only the lower order byte since shifting
6873 more that 32 bits make no sense anyway, ( the
6874 largest size of an object can be only 32 bits ) */
6876 if (AOP_TYPE (right) == AOP_LIT)
6878 /* Really should be handled by genLeftShiftLiteral,
6879 * but since I'm too lazy to fix that today, at least we can make
6880 * some small improvement.
6882 emitcode("mov", "b,#0x%02x",
6883 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
6887 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6888 emitcode ("inc", "b");
6890 freeAsmop (right, NULL, ic, TRUE);
6891 aopOp (left, ic, FALSE, FALSE);
6892 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6894 /* now move the left to the result if they are not the
6896 if (!sameRegs (AOP (left), AOP (result)) &&
6897 AOP_SIZE (result) > 1)
6900 size = AOP_SIZE (result);
6902 _startLazyDPSEvaluation ();
6905 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6906 if (*l == '@' && (IS_AOP_PREG (result)))
6909 emitcode ("mov", "a,%s", l);
6910 aopPut (AOP (result), "a", offset);
6913 aopPut (AOP (result), l, offset);
6916 _endLazyDPSEvaluation ();
6919 tlbl = newiTempLabel (NULL);
6920 size = AOP_SIZE (result);
6922 tlbl1 = newiTempLabel (NULL);
6924 /* if it is only one byte then */
6927 symbol *tlbl1 = newiTempLabel (NULL);
6929 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6931 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6932 emitcode ("", "%05d$:", tlbl->key + 100);
6933 emitcode ("add", "a,acc");
6934 emitcode ("", "%05d$:", tlbl1->key + 100);
6935 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6936 aopPut (AOP (result), "a", 0);
6940 reAdjustPreg (AOP (result));
6942 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6943 emitcode ("", "%05d$:", tlbl->key + 100);
6944 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6946 emitcode ("add", "a,acc");
6947 aopPut (AOP (result), "a", offset++);
6948 _startLazyDPSEvaluation ();
6951 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6953 emitcode ("rlc", "a");
6954 aopPut (AOP (result), "a", offset++);
6956 _endLazyDPSEvaluation ();
6957 reAdjustPreg (AOP (result));
6959 emitcode ("", "%05d$:", tlbl1->key + 100);
6960 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6962 freeAsmop (left, NULL, ic, TRUE);
6963 freeAsmop (result, NULL, ic, TRUE);
6968 /*-----------------------------------------------------------------*/
6969 /* genrshOne - right shift a one byte quantity by known count */
6970 /*-----------------------------------------------------------------*/
6972 genrshOne (operand * result, operand * left,
6973 int shCount, int sign)
6975 D (emitcode (";", "genrshOne");
6977 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6983 /*-----------------------------------------------------------------*/
6984 /* genrshTwo - right shift two bytes by known amount != 0 */
6985 /*-----------------------------------------------------------------*/
6987 genrshTwo (operand * result, operand * left,
6988 int shCount, int sign)
6990 D (emitcode (";", "genrshTwo");
6993 /* if shCount >= 8 */
6998 shiftR1Left2Result (left, MSB16, result, LSB,
7001 movLeft2Result (left, MSB16, result, LSB, sign);
7002 addSign (result, MSB16, sign);
7005 /* 1 <= shCount <= 7 */
7007 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7013 /*-----------------------------------------------------------------*/
7014 /* shiftRLong - shift right one long from left to result */
7015 /* offl = LSB or MSB16 */
7016 /*-----------------------------------------------------------------*/
7018 shiftRLong (operand * left, int offl,
7019 operand * result, int sign)
7022 emitcode ("clr", "c");
7023 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7025 emitcode ("mov", "c,acc.7");
7026 emitcode ("rrc", "a");
7027 aopPut (AOP (result), "a", MSB32 - offl);
7029 /* add sign of "a" */
7030 addSign (result, MSB32, sign);
7032 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7033 emitcode ("rrc", "a");
7034 aopPut (AOP (result), "a", MSB24 - offl);
7036 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7037 emitcode ("rrc", "a");
7038 aopPut (AOP (result), "a", MSB16 - offl);
7042 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7043 emitcode ("rrc", "a");
7044 aopPut (AOP (result), "a", LSB);
7051 /*-----------------------------------------------------------------*/
7052 /* genrshFour - shift four byte by a known amount != 0 */
7053 /*-----------------------------------------------------------------*/
7055 genrshFour (operand * result, operand * left,
7056 int shCount, int sign)
7058 D (emitcode (";", "genrshFour");
7061 /* if shifting more that 3 bytes */
7066 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7068 movLeft2Result (left, MSB32, result, LSB, sign);
7069 addSign (result, MSB16, sign);
7071 else if (shCount >= 16)
7075 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7078 movLeft2Result (left, MSB24, result, LSB, 0);
7079 movLeft2Result (left, MSB32, result, MSB16, sign);
7081 addSign (result, MSB24, sign);
7083 else if (shCount >= 8)
7087 shiftRLong (left, MSB16, result, sign);
7088 else if (shCount == 0)
7090 movLeft2Result (left, MSB16, result, LSB, 0);
7091 movLeft2Result (left, MSB24, result, MSB16, 0);
7092 movLeft2Result (left, MSB32, result, MSB24, sign);
7093 addSign (result, MSB32, sign);
7097 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7098 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7099 /* the last shift is signed */
7100 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7101 addSign (result, MSB32, sign);
7105 { /* 1 <= shCount <= 7 */
7108 shiftRLong (left, LSB, result, sign);
7110 shiftRLong (result, LSB, result, sign);
7114 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7115 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7116 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7124 /*-----------------------------------------------------------------*/
7125 /* genRightShiftLiteral - right shifting by known count */
7126 /*-----------------------------------------------------------------*/
7128 genRightShiftLiteral (operand * left,
7134 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7137 D (emitcode (";", "genRightShiftLiteral");
7140 freeAsmop (right, NULL, ic, TRUE);
7142 aopOp (left, ic, FALSE, FALSE);
7143 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7146 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7150 size = getDataSize (left);
7151 /* test the LEFT size !!! */
7153 /* I suppose that the left size >= result size */
7156 size = getDataSize (result);
7158 movLeft2Result (left, size, result, size, 0);
7161 else if (shCount >= (size * 8))
7164 /* get sign in acc.7 */
7165 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7166 addSign (result, LSB, sign);
7173 genrshOne (result, left, shCount, sign);
7177 genrshTwo (result, left, shCount, sign);
7181 genrshFour (result, left, shCount, sign);
7187 freeAsmop (left, NULL, ic, TRUE);
7188 freeAsmop (result, NULL, ic, TRUE);
7193 /*-----------------------------------------------------------------*/
7194 /* genSignedRightShift - right shift of signed number */
7195 /*-----------------------------------------------------------------*/
7197 genSignedRightShift (iCode * ic)
7199 operand *right, *left, *result;
7202 symbol *tlbl, *tlbl1;
7204 D (emitcode (";", "genSignedRightShift "););
7206 /* we do it the hard way put the shift count in b
7207 and loop thru preserving the sign */
7209 right = IC_RIGHT (ic);
7210 left = IC_LEFT (ic);
7211 result = IC_RESULT (ic);
7213 aopOp (right, ic, FALSE, FALSE);
7216 if (AOP_TYPE (right) == AOP_LIT)
7218 genRightShiftLiteral (left, right, result, ic, 1);
7222 /* shift count is unknown then we have to form
7223 a loop get the loop count in B : Note: we take
7224 only the lower order byte since shifting
7225 more that 32 bits make no sense anyway, ( the
7226 largest size of an object can be only 32 bits ) */
7228 if (AOP_TYPE (right) == AOP_LIT)
7230 /* Really should be handled by genRightShiftLiteral,
7231 * but since I'm too lazy to fix that today, at least we can make
7232 * some small improvement.
7234 emitcode("mov", "b,#0x%02x",
7235 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7239 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7240 emitcode ("inc", "b");
7242 freeAsmop (right, NULL, ic, TRUE);
7243 aopOp (left, ic, FALSE, FALSE);
7244 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7246 /* now move the left to the result if they are not the
7248 if (!sameRegs (AOP (left), AOP (result)) &&
7249 AOP_SIZE (result) > 1)
7252 size = AOP_SIZE (result);
7254 _startLazyDPSEvaluation ();
7257 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7258 if (*l == '@' && IS_AOP_PREG (result))
7261 emitcode ("mov", "a,%s", l);
7262 aopPut (AOP (result), "a", offset);
7265 aopPut (AOP (result), l, offset);
7268 _endLazyDPSEvaluation ();
7271 /* mov the highest order bit to OVR */
7272 tlbl = newiTempLabel (NULL);
7273 tlbl1 = newiTempLabel (NULL);
7275 size = AOP_SIZE (result);
7277 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7278 emitcode ("rlc", "a");
7279 emitcode ("mov", "ov,c");
7280 /* if it is only one byte then */
7283 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7285 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7286 emitcode ("", "%05d$:", tlbl->key + 100);
7287 emitcode ("mov", "c,ov");
7288 emitcode ("rrc", "a");
7289 emitcode ("", "%05d$:", tlbl1->key + 100);
7290 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7291 aopPut (AOP (result), "a", 0);
7295 reAdjustPreg (AOP (result));
7296 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7297 emitcode ("", "%05d$:", tlbl->key + 100);
7298 emitcode ("mov", "c,ov");
7299 _startLazyDPSEvaluation ();
7302 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7304 emitcode ("rrc", "a");
7305 aopPut (AOP (result), "a", offset--);
7307 _endLazyDPSEvaluation ();
7308 reAdjustPreg (AOP (result));
7309 emitcode ("", "%05d$:", tlbl1->key + 100);
7310 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7313 freeAsmop (left, NULL, ic, TRUE);
7314 freeAsmop (result, NULL, ic, TRUE);
7317 /*-----------------------------------------------------------------*/
7318 /* genRightShift - generate code for right shifting */
7319 /*-----------------------------------------------------------------*/
7321 genRightShift (iCode * ic)
7323 operand *right, *left, *result;
7327 symbol *tlbl, *tlbl1;
7329 D (emitcode (";", "genRightShift "););
7331 /* if signed then we do it the hard way preserve the
7332 sign bit moving it inwards */
7333 retype = getSpec (operandType (IC_RESULT (ic)));
7335 if (!SPEC_USIGN (retype))
7337 genSignedRightShift (ic);
7341 /* signed & unsigned types are treated the same : i.e. the
7342 signed is NOT propagated inwards : quoting from the
7343 ANSI - standard : "for E1 >> E2, is equivalent to division
7344 by 2**E2 if unsigned or if it has a non-negative value,
7345 otherwise the result is implementation defined ", MY definition
7346 is that the sign does not get propagated */
7348 right = IC_RIGHT (ic);
7349 left = IC_LEFT (ic);
7350 result = IC_RESULT (ic);
7352 aopOp (right, ic, FALSE, FALSE);
7355 /* if the shift count is known then do it
7356 as efficiently as possible */
7357 if (AOP_TYPE (right) == AOP_LIT)
7359 genRightShiftLiteral (left, right, result, ic, 0);
7364 /* shift count is unknown then we have to form
7365 a loop get the loop count in B : Note: we take
7366 only the lower order byte since shifting
7367 more that 32 bits make no sense anyway, ( the
7368 largest size of an object can be only 32 bits ) */
7370 if (AOP_TYPE (right) == AOP_LIT)
7372 /* Really should be handled by genRightShiftLiteral,
7373 * but since I'm too lazy to fix that today, at least we can make
7374 * some small improvement.
7376 emitcode("mov", "b,#0x%02x",
7377 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7381 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7382 emitcode ("inc", "b");
7384 freeAsmop (right, NULL, ic, TRUE);
7385 aopOp (left, ic, FALSE, FALSE);
7386 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7388 /* now move the left to the result if they are not the
7390 if (!sameRegs (AOP (left), AOP (result)) &&
7391 AOP_SIZE (result) > 1)
7394 size = AOP_SIZE (result);
7396 _startLazyDPSEvaluation ();
7399 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7400 if (*l == '@' && IS_AOP_PREG (result))
7403 emitcode ("mov", "a,%s", l);
7404 aopPut (AOP (result), "a", offset);
7407 aopPut (AOP (result), l, offset);
7410 _endLazyDPSEvaluation ();
7413 tlbl = newiTempLabel (NULL);
7414 tlbl1 = newiTempLabel (NULL);
7415 size = AOP_SIZE (result);
7418 /* if it is only one byte then */
7421 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7423 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7424 emitcode ("", "%05d$:", tlbl->key + 100);
7426 emitcode ("rrc", "a");
7427 emitcode ("", "%05d$:", tlbl1->key + 100);
7428 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7429 aopPut (AOP (result), "a", 0);
7433 reAdjustPreg (AOP (result));
7434 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7435 emitcode ("", "%05d$:", tlbl->key + 100);
7437 _startLazyDPSEvaluation ();
7440 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7442 emitcode ("rrc", "a");
7443 aopPut (AOP (result), "a", offset--);
7445 _endLazyDPSEvaluation ();
7446 reAdjustPreg (AOP (result));
7448 emitcode ("", "%05d$:", tlbl1->key + 100);
7449 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7452 freeAsmop (left, NULL, ic, TRUE);
7453 freeAsmop (result, NULL, ic, TRUE);
7456 /*-----------------------------------------------------------------*/
7457 /* genUnpackBits - generates code for unpacking bits */
7458 /*-----------------------------------------------------------------*/
7460 genUnpackBits (operand * result, char *rname, int ptype)
7467 D (emitcode (";", "genUnpackBits ");
7470 etype = getSpec (operandType (result));
7472 /* read the first byte */
7478 emitcode ("mov", "a,@%s", rname);
7482 emitcode ("movx", "a,@%s", rname);
7486 emitcode ("movx", "a,@dptr");
7490 emitcode ("clr", "a");
7491 emitcode ("movc", "a", "@a+dptr");
7495 emitcode ("lcall", "__gptrget");
7499 /* if we have bitdisplacement then it fits */
7500 /* into this byte completely or if length is */
7501 /* less than a byte */
7502 if ((shCnt = SPEC_BSTR (etype)) ||
7503 (SPEC_BLEN (etype) <= 8))
7506 /* shift right acc */
7509 emitcode ("anl", "a,#0x%02x",
7510 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7511 aopPut (AOP (result), "a", offset);
7515 /* bit field did not fit in a byte */
7516 rlen = SPEC_BLEN (etype) - 8;
7517 aopPut (AOP (result), "a", offset++);
7526 emitcode ("inc", "%s", rname);
7527 emitcode ("mov", "a,@%s", rname);
7531 emitcode ("inc", "%s", rname);
7532 emitcode ("movx", "a,@%s", rname);
7536 emitcode ("inc", "dptr");
7537 emitcode ("movx", "a,@dptr");
7541 emitcode ("clr", "a");
7542 emitcode ("inc", "dptr");
7543 emitcode ("movc", "a", "@a+dptr");
7547 emitcode ("inc", "dptr");
7548 emitcode ("lcall", "__gptrget");
7553 /* if we are done */
7557 aopPut (AOP (result), "a", offset++);
7563 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7564 aopPut (AOP (result), "a", offset);
7571 /*-----------------------------------------------------------------*/
7572 /* genDataPointerGet - generates code when ptr offset is known */
7573 /*-----------------------------------------------------------------*/
7575 genDataPointerGet (operand * left,
7581 int size, offset = 0;
7582 aopOp (result, ic, TRUE, FALSE);
7584 /* get the string representation of the name */
7585 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7586 size = AOP_SIZE (result);
7587 _startLazyDPSEvaluation ();
7591 sprintf (buffer, "(%s + %d)", l + 1, offset);
7593 sprintf (buffer, "%s", l + 1);
7594 aopPut (AOP (result), buffer, offset++);
7596 _endLazyDPSEvaluation ();
7598 freeAsmop (left, NULL, ic, TRUE);
7599 freeAsmop (result, NULL, ic, TRUE);
7602 /*-----------------------------------------------------------------*/
7603 /* genNearPointerGet - emitcode for near pointer fetch */
7604 /*-----------------------------------------------------------------*/
7606 genNearPointerGet (operand * left,
7613 sym_link *rtype, *retype, *letype;
7614 sym_link *ltype = operandType (left);
7617 rtype = operandType (result);
7618 retype = getSpec (rtype);
7619 letype = getSpec (ltype);
7621 aopOp (left, ic, FALSE, FALSE);
7623 /* if left is rematerialisable and
7624 result is not bit variable type and
7625 the left is pointer to data space i.e
7626 lower 128 bytes of space */
7627 if (AOP_TYPE (left) == AOP_IMMD &&
7628 !IS_BITVAR (retype) &&
7629 !IS_BITVAR (letype) &&
7630 DCL_TYPE (ltype) == POINTER)
7632 genDataPointerGet (left, result, ic);
7636 /* if the value is already in a pointer register
7637 then don't need anything more */
7638 if (!AOP_INPREG (AOP (left)))
7640 /* otherwise get a free pointer register */
7642 preg = getFreePtr (ic, &aop, FALSE);
7643 emitcode ("mov", "%s,%s",
7645 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7649 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7651 freeAsmop (left, NULL, ic, TRUE);
7652 aopOp (result, ic, FALSE, FALSE);
7654 /* if bitfield then unpack the bits */
7655 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7656 genUnpackBits (result, rname, POINTER);
7659 /* we have can just get the values */
7660 int size = AOP_SIZE (result);
7665 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7668 emitcode ("mov", "a,@%s", rname);
7669 aopPut (AOP (result), "a", offset);
7673 sprintf (buffer, "@%s", rname);
7674 aopPut (AOP (result), buffer, offset);
7678 emitcode ("inc", "%s", rname);
7682 /* now some housekeeping stuff */
7685 /* we had to allocate for this iCode */
7686 freeAsmop (NULL, aop, ic, TRUE);
7690 /* we did not allocate which means left
7691 already in a pointer register, then
7692 if size > 0 && this could be used again
7693 we have to point it back to where it
7695 if (AOP_SIZE (result) > 1 &&
7696 !OP_SYMBOL (left)->remat &&
7697 (OP_SYMBOL (left)->liveTo > ic->seq ||
7700 int size = AOP_SIZE (result) - 1;
7702 emitcode ("dec", "%s", rname);
7707 freeAsmop (result, NULL, ic, TRUE);
7711 /*-----------------------------------------------------------------*/
7712 /* genPagedPointerGet - emitcode for paged pointer fetch */
7713 /*-----------------------------------------------------------------*/
7715 genPagedPointerGet (operand * left,
7722 sym_link *rtype, *retype, *letype;
7724 rtype = operandType (result);
7725 retype = getSpec (rtype);
7726 letype = getSpec (operandType (left));
7727 aopOp (left, ic, FALSE, FALSE);
7729 /* if the value is already in a pointer register
7730 then don't need anything more */
7731 if (!AOP_INPREG (AOP (left)))
7733 /* otherwise get a free pointer register */
7735 preg = getFreePtr (ic, &aop, FALSE);
7736 emitcode ("mov", "%s,%s",
7738 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7742 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7744 freeAsmop (left, NULL, ic, TRUE);
7745 aopOp (result, ic, FALSE, FALSE);
7747 /* if bitfield then unpack the bits */
7748 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7749 genUnpackBits (result, rname, PPOINTER);
7752 /* we have can just get the values */
7753 int size = AOP_SIZE (result);
7759 emitcode ("movx", "a,@%s", rname);
7760 aopPut (AOP (result), "a", offset);
7765 emitcode ("inc", "%s", rname);
7769 /* now some housekeeping stuff */
7772 /* we had to allocate for this iCode */
7773 freeAsmop (NULL, aop, ic, TRUE);
7777 /* we did not allocate which means left
7778 already in a pointer register, then
7779 if size > 0 && this could be used again
7780 we have to point it back to where it
7782 if (AOP_SIZE (result) > 1 &&
7783 !OP_SYMBOL (left)->remat &&
7784 (OP_SYMBOL (left)->liveTo > ic->seq ||
7787 int size = AOP_SIZE (result) - 1;
7789 emitcode ("dec", "%s", rname);
7794 freeAsmop (result, NULL, ic, TRUE);
7799 /*-----------------------------------------------------------------*/
7800 /* genFarPointerGet - gget value from far space */
7801 /*-----------------------------------------------------------------*/
7803 genFarPointerGet (operand * left,
7804 operand * result, iCode * ic)
7807 sym_link *retype = getSpec (operandType (result));
7808 sym_link *letype = getSpec (operandType (left));
7809 D (emitcode (";", "genFarPointerGet");
7812 aopOp (left, ic, FALSE, FALSE);
7814 /* if the operand is already in dptr
7815 then we do nothing else we move the value to dptr */
7816 if (AOP_TYPE (left) != AOP_STR)
7818 /* if this is remateriazable */
7819 if (AOP_TYPE (left) == AOP_IMMD)
7821 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7825 /* we need to get it byte by byte */
7826 _startLazyDPSEvaluation ();
7827 if (AOP_TYPE (left) != AOP_DPTR)
7829 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7830 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7831 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7835 /* We need to generate a load to DPTR indirect through DPTR. */
7836 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7838 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7839 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7840 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7841 emitcode ("pop", "dph");
7842 emitcode ("pop", "dpl");
7844 _endLazyDPSEvaluation ();
7847 /* so dptr know contains the address */
7848 freeAsmop (left, NULL, ic, TRUE);
7849 aopOp (result, ic, FALSE, TRUE);
7851 /* if bit then unpack */
7852 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7853 genUnpackBits (result, "dptr", FPOINTER);
7856 size = AOP_SIZE (result);
7859 _startLazyDPSEvaluation ();
7866 emitcode ("movx", "a,@dptr");
7868 emitcode ("inc", "dptr");
7870 aopPut (AOP (result), "a", offset++);
7872 _endLazyDPSEvaluation ();
7875 freeAsmop (result, NULL, ic, TRUE);
7878 /*-----------------------------------------------------------------*/
7879 /* emitcodePointerGet - gget value from code space */
7880 /*-----------------------------------------------------------------*/
7882 emitcodePointerGet (operand * left,
7883 operand * result, iCode * ic)
7886 sym_link *retype = getSpec (operandType (result));
7888 aopOp (left, ic, FALSE, FALSE);
7890 /* if the operand is already in dptr
7891 then we do nothing else we move the value to dptr */
7892 if (AOP_TYPE (left) != AOP_STR)
7894 /* if this is remateriazable */
7895 if (AOP_TYPE (left) == AOP_IMMD)
7897 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7900 { /* we need to get it byte by byte */
7901 _startLazyDPSEvaluation ();
7902 if (AOP_TYPE (left) != AOP_DPTR)
7904 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7905 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7906 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7910 /* We need to generate a load to DPTR indirect through DPTR. */
7911 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7913 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7914 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7915 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7916 emitcode ("pop", "dph");
7917 emitcode ("pop", "dpl");
7919 _endLazyDPSEvaluation ();
7922 /* so dptr know contains the address */
7923 freeAsmop (left, NULL, ic, TRUE);
7924 aopOp (result, ic, FALSE, TRUE);
7926 /* if bit then unpack */
7927 if (IS_BITVAR (retype))
7928 genUnpackBits (result, "dptr", CPOINTER);
7931 size = AOP_SIZE (result);
7934 _startLazyDPSEvaluation ();
7940 emitcode ("clr", "a");
7941 emitcode ("movc", "a,@a+dptr");
7943 emitcode ("inc", "dptr");
7944 aopPut (AOP (result), "a", offset++);
7946 _endLazyDPSEvaluation ();
7949 freeAsmop (result, NULL, ic, TRUE);
7952 /*-----------------------------------------------------------------*/
7953 /* genGenPointerGet - gget value from generic pointer space */
7954 /*-----------------------------------------------------------------*/
7956 genGenPointerGet (operand * left,
7957 operand * result, iCode * ic)
7960 sym_link *retype = getSpec (operandType (result));
7961 sym_link *letype = getSpec (operandType (left));
7963 D (emitcode (";", "genGenPointerGet "); );
7965 aopOp (left, ic, FALSE, TRUE);
7967 /* if the operand is already in dptr
7968 then we do nothing else we move the value to dptr */
7969 if (AOP_TYPE (left) != AOP_STR)
7971 /* if this is remateriazable */
7972 if (AOP_TYPE (left) == AOP_IMMD)
7974 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7975 emitcode ("mov", "b,#%d", pointerCode (retype));
7978 { /* we need to get it byte by byte */
7979 _startLazyDPSEvaluation ();
7980 if (AOP(left)->type==AOP_DPTR2) {
7982 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7985 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7986 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7989 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7990 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7993 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7994 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7996 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7997 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7998 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7999 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8001 _endLazyDPSEvaluation ();
8004 /* so dptr know contains the address */
8005 freeAsmop (left, NULL, ic, TRUE);
8006 aopOp (result, ic, FALSE, TRUE);
8008 /* if bit then unpack */
8009 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8010 genUnpackBits (result, "dptr", GPOINTER);
8013 size = AOP_SIZE (result);
8018 emitcode ("lcall", "__gptrget");
8019 aopPut (AOP (result), "a", offset++);
8021 emitcode ("inc", "dptr");
8025 freeAsmop (result, NULL, ic, TRUE);
8028 /*-----------------------------------------------------------------*/
8029 /* genPointerGet - generate code for pointer get */
8030 /*-----------------------------------------------------------------*/
8032 genPointerGet (iCode * ic)
8034 operand *left, *result;
8035 sym_link *type, *etype;
8038 D (emitcode (";", "genPointerGet ");
8041 left = IC_LEFT (ic);
8042 result = IC_RESULT (ic);
8044 /* depending on the type of pointer we need to
8045 move it to the correct pointer register */
8046 type = operandType (left);
8047 etype = getSpec (type);
8048 /* if left is of type of pointer then it is simple */
8049 if (IS_PTR (type) && !IS_FUNC (type->next))
8050 p_type = DCL_TYPE (type);
8053 /* we have to go by the storage class */
8054 p_type = PTR_TYPE (SPEC_OCLS (etype));
8057 /* now that we have the pointer type we assign
8058 the pointer values */
8064 genNearPointerGet (left, result, ic);
8068 genPagedPointerGet (left, result, ic);
8072 genFarPointerGet (left, result, ic);
8076 emitcodePointerGet (left, result, ic);
8080 genGenPointerGet (left, result, ic);
8086 /*-----------------------------------------------------------------*/
8087 /* genPackBits - generates code for packed bit storage */
8088 /*-----------------------------------------------------------------*/
8090 genPackBits (sym_link * etype,
8092 char *rname, int p_type)
8100 blen = SPEC_BLEN (etype);
8101 bstr = SPEC_BSTR (etype);
8103 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8106 /* if the bit lenth is less than or */
8107 /* it exactly fits a byte then */
8108 if (SPEC_BLEN (etype) <= 8)
8110 shCount = SPEC_BSTR (etype);
8112 /* shift left acc */
8115 if (SPEC_BLEN (etype) < 8)
8116 { /* if smaller than a byte */
8122 emitcode ("mov", "b,a");
8123 emitcode ("mov", "a,@%s", rname);
8127 emitcode ("mov", "b,a");
8128 emitcode ("movx", "a,@dptr");
8132 emitcode ("push", "b");
8133 emitcode ("push", "acc");
8134 emitcode ("lcall", "__gptrget");
8135 emitcode ("pop", "b");
8139 emitcode ("anl", "a,#0x%02x", (unsigned char)
8140 ((unsigned char) (0xFF << (blen + bstr)) |
8141 (unsigned char) (0xFF >> (8 - bstr))));
8142 emitcode ("orl", "a,b");
8143 if (p_type == GPOINTER)
8144 emitcode ("pop", "b");
8151 emitcode ("mov", "@%s,a", rname);
8155 emitcode ("movx", "@dptr,a");
8159 emitcode ("lcall", "__gptrput");
8164 if (SPEC_BLEN (etype) <= 8)
8167 emitcode ("inc", "%s", rname);
8168 rLen = SPEC_BLEN (etype);
8170 /* now generate for lengths greater than one byte */
8174 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8186 emitcode ("mov", "@%s,a", rname);
8189 emitcode ("mov", "@%s,%s", rname, l);
8194 emitcode ("movx", "@dptr,a");
8199 emitcode ("lcall", "__gptrput");
8202 emitcode ("inc", "%s", rname);
8207 /* last last was not complete */
8210 /* save the byte & read byte */
8214 emitcode ("mov", "b,a");
8215 emitcode ("mov", "a,@%s", rname);
8219 emitcode ("mov", "b,a");
8220 emitcode ("movx", "a,@dptr");
8224 emitcode ("push", "b");
8225 emitcode ("push", "acc");
8226 emitcode ("lcall", "__gptrget");
8227 emitcode ("pop", "b");
8231 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8232 emitcode ("orl", "a,b");
8235 if (p_type == GPOINTER)
8236 emitcode ("pop", "b");
8242 emitcode ("mov", "@%s,a", rname);
8246 emitcode ("movx", "@dptr,a");
8250 emitcode ("lcall", "__gptrput");
8254 /*-----------------------------------------------------------------*/
8255 /* genDataPointerSet - remat pointer to data space */
8256 /*-----------------------------------------------------------------*/
8258 genDataPointerSet (operand * right,
8262 int size, offset = 0;
8263 char *l, buffer[256];
8265 aopOp (right, ic, FALSE, FALSE);
8267 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8268 size = AOP_SIZE (right);
8272 sprintf (buffer, "(%s + %d)", l + 1, offset);
8274 sprintf (buffer, "%s", l + 1);
8275 emitcode ("mov", "%s,%s", buffer,
8276 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8279 freeAsmop (right, NULL, ic, TRUE);
8280 freeAsmop (result, NULL, ic, TRUE);
8283 /*-----------------------------------------------------------------*/
8284 /* genNearPointerSet - emitcode for near pointer put */
8285 /*-----------------------------------------------------------------*/
8287 genNearPointerSet (operand * right,
8294 sym_link *retype, *letype;
8295 sym_link *ptype = operandType (result);
8297 retype = getSpec (operandType (right));
8298 letype = getSpec (ptype);
8300 aopOp (result, ic, FALSE, FALSE);
8302 /* if the result is rematerializable &
8303 in data space & not a bit variable */
8304 if (AOP_TYPE (result) == AOP_IMMD &&
8305 DCL_TYPE (ptype) == POINTER &&
8306 !IS_BITVAR (retype) &&
8307 !IS_BITVAR (letype))
8309 genDataPointerSet (right, result, ic);
8313 /* if the value is already in a pointer register
8314 then don't need anything more */
8315 if (!AOP_INPREG (AOP (result)))
8317 /* otherwise get a free pointer register */
8319 preg = getFreePtr (ic, &aop, FALSE);
8320 emitcode ("mov", "%s,%s",
8322 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8326 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8328 freeAsmop (result, NULL, ic, TRUE);
8329 aopOp (right, ic, FALSE, FALSE);
8331 /* if bitfield then unpack the bits */
8332 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8333 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8336 /* we have can just get the values */
8337 int size = AOP_SIZE (right);
8342 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8346 emitcode ("mov", "@%s,a", rname);
8349 emitcode ("mov", "@%s,%s", rname, l);
8351 emitcode ("inc", "%s", rname);
8356 /* now some housekeeping stuff */
8359 /* we had to allocate for this iCode */
8360 freeAsmop (NULL, aop, ic, TRUE);
8364 /* we did not allocate which means left
8365 already in a pointer register, then
8366 if size > 0 && this could be used again
8367 we have to point it back to where it
8369 if (AOP_SIZE (right) > 1 &&
8370 !OP_SYMBOL (result)->remat &&
8371 (OP_SYMBOL (result)->liveTo > ic->seq ||
8374 int size = AOP_SIZE (right) - 1;
8376 emitcode ("dec", "%s", rname);
8381 freeAsmop (right, NULL, ic, TRUE);
8386 /*-----------------------------------------------------------------*/
8387 /* genPagedPointerSet - emitcode for Paged pointer put */
8388 /*-----------------------------------------------------------------*/
8390 genPagedPointerSet (operand * right,
8397 sym_link *retype, *letype;
8399 retype = getSpec (operandType (right));
8400 letype = getSpec (operandType (result));
8402 aopOp (result, ic, FALSE, FALSE);
8404 /* if the value is already in a pointer register
8405 then don't need anything more */
8406 if (!AOP_INPREG (AOP (result)))
8408 /* otherwise get a free pointer register */
8410 preg = getFreePtr (ic, &aop, FALSE);
8411 emitcode ("mov", "%s,%s",
8413 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8417 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8419 freeAsmop (result, NULL, ic, TRUE);
8420 aopOp (right, ic, FALSE, FALSE);
8422 /* if bitfield then unpack the bits */
8423 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8424 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8427 /* we have can just get the values */
8428 int size = AOP_SIZE (right);
8433 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8436 emitcode ("movx", "@%s,a", rname);
8439 emitcode ("inc", "%s", rname);
8445 /* now some housekeeping stuff */
8448 /* we had to allocate for this iCode */
8449 freeAsmop (NULL, aop, ic, TRUE);
8453 /* we did not allocate which means left
8454 already in a pointer register, then
8455 if size > 0 && this could be used again
8456 we have to point it back to where it
8458 if (AOP_SIZE (right) > 1 &&
8459 !OP_SYMBOL (result)->remat &&
8460 (OP_SYMBOL (result)->liveTo > ic->seq ||
8463 int size = AOP_SIZE (right) - 1;
8465 emitcode ("dec", "%s", rname);
8470 freeAsmop (right, NULL, ic, TRUE);
8475 /*-----------------------------------------------------------------*/
8476 /* genFarPointerSet - set value from far space */
8477 /*-----------------------------------------------------------------*/
8479 genFarPointerSet (operand * right,
8480 operand * result, iCode * ic)
8483 sym_link *retype = getSpec (operandType (right));
8484 sym_link *letype = getSpec (operandType (result));
8486 aopOp (result, ic, FALSE, FALSE);
8488 /* if the operand is already in dptr
8489 then we do nothing else we move the value to dptr */
8490 if (AOP_TYPE (result) != AOP_STR)
8492 /* if this is remateriazable */
8493 if (AOP_TYPE (result) == AOP_IMMD)
8494 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8497 /* we need to get it byte by byte */
8498 _startLazyDPSEvaluation ();
8499 if (AOP_TYPE (result) != AOP_DPTR)
8501 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8502 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8503 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8507 /* We need to generate a load to DPTR indirect through DPTR. */
8508 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8510 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8511 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8512 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8513 emitcode ("pop", "dph");
8514 emitcode ("pop", "dpl");
8516 _endLazyDPSEvaluation ();
8519 /* so dptr know contains the address */
8520 freeAsmop (result, NULL, ic, TRUE);
8521 aopOp (right, ic, FALSE, TRUE);
8523 /* if bit then unpack */
8524 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8525 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8528 size = AOP_SIZE (right);
8531 _startLazyDPSEvaluation ();
8534 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8540 emitcode ("movx", "@dptr,a");
8542 emitcode ("inc", "dptr");
8544 _endLazyDPSEvaluation ();
8547 freeAsmop (right, NULL, ic, TRUE);
8550 /*-----------------------------------------------------------------*/
8551 /* genGenPointerSet - set value from generic pointer space */
8552 /*-----------------------------------------------------------------*/
8554 genGenPointerSet (operand * right,
8555 operand * result, iCode * ic)
8558 sym_link *retype = getSpec (operandType (right));
8559 sym_link *letype = getSpec (operandType (result));
8561 aopOp (result, ic, FALSE, TRUE);
8563 /* if the operand is already in dptr
8564 then we do nothing else we move the value to dptr */
8565 if (AOP_TYPE (result) != AOP_STR)
8567 _startLazyDPSEvaluation ();
8568 /* if this is remateriazable */
8569 if (AOP_TYPE (result) == AOP_IMMD)
8571 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8572 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8575 { /* we need to get it byte by byte */
8576 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8577 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8578 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8579 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8581 _endLazyDPSEvaluation ();
8583 /* so dptr know contains the address */
8584 freeAsmop (result, NULL, ic, TRUE);
8585 aopOp (right, ic, FALSE, TRUE);
8587 /* if bit then unpack */
8588 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8589 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8592 size = AOP_SIZE (right);
8595 _startLazyDPSEvaluation ();
8598 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8604 emitcode ("lcall", "__gptrput");
8606 emitcode ("inc", "dptr");
8608 _endLazyDPSEvaluation ();
8611 freeAsmop (right, NULL, ic, TRUE);
8614 /*-----------------------------------------------------------------*/
8615 /* genPointerSet - stores the value into a pointer location */
8616 /*-----------------------------------------------------------------*/
8618 genPointerSet (iCode * ic)
8620 operand *right, *result;
8621 sym_link *type, *etype;
8624 D (emitcode (";", "genPointerSet ");
8627 right = IC_RIGHT (ic);
8628 result = IC_RESULT (ic);
8630 /* depending on the type of pointer we need to
8631 move it to the correct pointer register */
8632 type = operandType (result);
8633 etype = getSpec (type);
8634 /* if left is of type of pointer then it is simple */
8635 if (IS_PTR (type) && !IS_FUNC (type->next))
8637 p_type = DCL_TYPE (type);
8641 /* we have to go by the storage class */
8642 p_type = PTR_TYPE (SPEC_OCLS (etype));
8645 /* now that we have the pointer type we assign
8646 the pointer values */
8652 genNearPointerSet (right, result, ic);
8656 genPagedPointerSet (right, result, ic);
8660 genFarPointerSet (right, result, ic);
8664 genGenPointerSet (right, result, ic);
8670 /*-----------------------------------------------------------------*/
8671 /* genIfx - generate code for Ifx statement */
8672 /*-----------------------------------------------------------------*/
8674 genIfx (iCode * ic, iCode * popIc)
8676 operand *cond = IC_COND (ic);
8679 D (emitcode (";", "genIfx "););
8681 aopOp (cond, ic, FALSE, FALSE);
8683 /* get the value into acc */
8684 if (AOP_TYPE (cond) != AOP_CRY)
8688 /* the result is now in the accumulator */
8689 freeAsmop (cond, NULL, ic, TRUE);
8691 /* if there was something to be popped then do it */
8695 /* if the condition is a bit variable */
8696 if (isbit && IS_ITEMP (cond) &&
8698 genIfxJump (ic, SPIL_LOC (cond)->rname);
8699 else if (isbit && !IS_ITEMP (cond))
8700 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8702 genIfxJump (ic, "a");
8707 /*-----------------------------------------------------------------*/
8708 /* genAddrOf - generates code for address of */
8709 /*-----------------------------------------------------------------*/
8711 genAddrOf (iCode * ic)
8713 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8716 D (emitcode (";", "genAddrOf ");
8719 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8721 /* if the operand is on the stack then we
8722 need to get the stack offset of this
8726 /* if it has an offset then we need to compute
8730 emitcode ("mov", "a,_bp");
8731 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8732 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8736 /* we can just move _bp */
8737 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8739 /* fill the result with zero */
8740 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8743 if (options.stack10bit && size < (FPTRSIZE - 1))
8746 "*** warning: pointer to stack var truncated.\n");
8753 if (options.stack10bit && offset == 2)
8755 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8759 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8766 /* object not on stack then we need the name */
8767 size = AOP_SIZE (IC_RESULT (ic));
8772 char s[SDCC_NAME_MAX];
8774 sprintf (s, "#(%s >> %d)",
8778 sprintf (s, "#%s", sym->rname);
8779 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8783 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8787 /*-----------------------------------------------------------------*/
8788 /* genFarFarAssign - assignment when both are in far space */
8789 /*-----------------------------------------------------------------*/
8791 genFarFarAssign (operand * result, operand * right, iCode * ic)
8793 int size = AOP_SIZE (right);
8799 /* This is a net loss for size == 1, but a big gain
8802 D (emitcode (";", "genFarFarAssign (improved)");
8805 aopOp (result, ic, TRUE, TRUE);
8807 _startLazyDPSEvaluation ();
8810 aopPut (AOP (result),
8811 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8814 _endLazyDPSEvaluation ();
8815 freeAsmop (result, NULL, ic, FALSE);
8816 freeAsmop (right, NULL, ic, FALSE);
8820 D (emitcode (";", "genFarFarAssign ");
8823 /* first push the right side on to the stack */
8824 _startLazyDPSEvaluation ();
8827 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8829 emitcode ("push", "acc");
8832 freeAsmop (right, NULL, ic, FALSE);
8833 /* now assign DPTR to result */
8834 aopOp (result, ic, FALSE, FALSE);
8835 size = AOP_SIZE (result);
8838 emitcode ("pop", "acc");
8839 aopPut (AOP (result), "a", --offset);
8841 freeAsmop (result, NULL, ic, FALSE);
8842 _endLazyDPSEvaluation ();
8846 /*-----------------------------------------------------------------*/
8847 /* genAssign - generate code for assignment */
8848 /*-----------------------------------------------------------------*/
8850 genAssign (iCode * ic)
8852 operand *result, *right;
8854 unsigned long lit = 0L;
8856 D (emitcode (";", "genAssign ");
8859 result = IC_RESULT (ic);
8860 right = IC_RIGHT (ic);
8862 /* if they are the same */
8863 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8866 aopOp (right, ic, FALSE, FALSE);
8868 emitcode (";", "genAssign: resultIsFar = %s",
8869 isOperandInFarSpace (result) ?
8872 /* special case both in far space */
8873 if ((AOP_TYPE (right) == AOP_DPTR ||
8874 AOP_TYPE (right) == AOP_DPTR2) &&
8875 /* IS_TRUE_SYMOP(result) && */
8876 isOperandInFarSpace (result))
8878 genFarFarAssign (result, right, ic);
8882 aopOp (result, ic, TRUE, FALSE);
8884 /* if they are the same registers */
8885 if (sameRegs (AOP (right), AOP (result)))
8888 /* if the result is a bit */
8889 if (AOP_TYPE (result) == AOP_CRY)
8892 /* if the right size is a literal then
8893 we know what the value is */
8894 if (AOP_TYPE (right) == AOP_LIT)
8896 if (((int) operandLitValue (right)))
8897 aopPut (AOP (result), one, 0);
8899 aopPut (AOP (result), zero, 0);
8903 /* the right is also a bit variable */
8904 if (AOP_TYPE (right) == AOP_CRY)
8906 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8907 aopPut (AOP (result), "c", 0);
8913 aopPut (AOP (result), "a", 0);
8917 /* bit variables done */
8919 size = AOP_SIZE (result);
8921 if (AOP_TYPE (right) == AOP_LIT)
8922 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8925 (AOP_TYPE (result) != AOP_REG) &&
8926 (AOP_TYPE (right) == AOP_LIT) &&
8927 !IS_FLOAT (operandType (right)))
8929 D (emitcode (";", "Kevin's better literal load code");
8931 _startLazyDPSEvaluation ();
8932 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8934 aopPut (AOP (result),
8935 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8940 /* And now fill the rest with zeros. */
8943 emitcode ("clr", "a");
8947 aopPut (AOP (result), "a", offset++);
8949 _endLazyDPSEvaluation ();
8953 _startLazyDPSEvaluation ();
8956 aopPut (AOP (result),
8957 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8961 _endLazyDPSEvaluation ();
8965 freeAsmop (right, NULL, ic, FALSE);
8966 freeAsmop (result, NULL, ic, TRUE);
8969 /*-----------------------------------------------------------------*/
8970 /* genJumpTab - generates code for jump table */
8971 /*-----------------------------------------------------------------*/
8973 genJumpTab (iCode * ic)
8978 D (emitcode (";", "genJumpTab ");
8981 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8982 /* get the condition into accumulator */
8983 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8985 /* multiply by four! */
8986 emitcode ("add", "a,acc");
8987 emitcode ("add", "a,acc");
8988 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8990 jtab = newiTempLabel (NULL);
8991 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8992 emitcode ("jmp", "@a+dptr");
8993 emitcode ("", "%05d$:", jtab->key + 100);
8994 /* now generate the jump labels */
8995 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8996 jtab = setNextItem (IC_JTLABELS (ic)))
8997 emitcode ("ljmp", "%05d$", jtab->key + 100);
9001 /*-----------------------------------------------------------------*/
9002 /* genCast - gen code for casting */
9003 /*-----------------------------------------------------------------*/
9005 genCast (iCode * ic)
9007 operand *result = IC_RESULT (ic);
9008 sym_link *ctype = operandType (IC_LEFT (ic));
9009 sym_link *rtype = operandType (IC_RIGHT (ic));
9010 operand *right = IC_RIGHT (ic);
9013 D (emitcode (";", "genCast ");
9016 /* if they are equivalent then do nothing */
9017 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9020 aopOp (right, ic, FALSE, FALSE);
9021 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9023 /* if the result is a bit */
9024 if (AOP_TYPE (result) == AOP_CRY)
9026 /* if the right size is a literal then
9027 we know what the value is */
9028 if (AOP_TYPE (right) == AOP_LIT)
9030 if (((int) operandLitValue (right)))
9031 aopPut (AOP (result), one, 0);
9033 aopPut (AOP (result), zero, 0);
9038 /* the right is also a bit variable */
9039 if (AOP_TYPE (right) == AOP_CRY)
9041 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9042 aopPut (AOP (result), "c", 0);
9048 aopPut (AOP (result), "a", 0);
9052 /* if they are the same size : or less */
9053 if (AOP_SIZE (result) <= AOP_SIZE (right))
9056 /* if they are in the same place */
9057 if (sameRegs (AOP (right), AOP (result)))
9060 /* if they in different places then copy */
9061 size = AOP_SIZE (result);
9063 _startLazyDPSEvaluation ();
9066 aopPut (AOP (result),
9067 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9071 _endLazyDPSEvaluation ();
9076 /* if the result is of type pointer */
9081 sym_link *type = operandType (right);
9083 /* pointer to generic pointer */
9084 if (IS_GENPTR (ctype))
9090 p_type = DCL_TYPE (type);
9094 #if OLD_CAST_BEHAVIOR
9095 /* KV: we are converting a non-pointer type to
9096 * a generic pointer. This (ifdef'd out) code
9097 * says that the resulting generic pointer
9098 * should have the same class as the storage
9099 * location of the non-pointer variable.
9101 * For example, converting an int (which happens
9102 * to be stored in DATA space) to a pointer results
9103 * in a DATA generic pointer; if the original int
9104 * in XDATA space, so will be the resulting pointer.
9106 * I don't like that behavior, and thus this change:
9107 * all such conversions will be forced to XDATA and
9108 * throw a warning. If you want some non-XDATA
9109 * type, or you want to suppress the warning, you
9110 * must go through an intermediate cast, like so:
9112 * char _generic *gp = (char _xdata *)(intVar);
9114 sym_link *etype = getSpec (type);
9116 /* we have to go by the storage class */
9117 if (SPEC_OCLS (etype) != generic)
9119 p_type = PTR_TYPE (SPEC_OCLS (etype));
9124 /* Converting unknown class (i.e. register variable)
9125 * to generic pointer. This is not good, but
9126 * we'll make a guess (and throw a warning).
9129 werror (W_INT_TO_GEN_PTR_CAST);
9133 /* the first two bytes are known */
9134 size = GPTRSIZE - 1;
9136 _startLazyDPSEvaluation ();
9139 aopPut (AOP (result),
9140 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9144 _endLazyDPSEvaluation ();
9146 /* the last byte depending on type */
9164 /* this should never happen */
9165 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9166 "got unknown pointer type");
9169 aopPut (AOP (result), l, GPTRSIZE - 1);
9173 /* just copy the pointers */
9174 size = AOP_SIZE (result);
9176 _startLazyDPSEvaluation ();
9179 aopPut (AOP (result),
9180 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9184 _endLazyDPSEvaluation ();
9188 /* so we now know that the size of destination is greater
9189 than the size of the source */
9190 /* we move to result for the size of source */
9191 size = AOP_SIZE (right);
9193 _startLazyDPSEvaluation ();
9196 aopPut (AOP (result),
9197 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9201 _endLazyDPSEvaluation ();
9203 /* now depending on the sign of the source && destination */
9204 size = AOP_SIZE (result) - AOP_SIZE (right);
9205 /* if unsigned or not an integral type */
9206 /* also, if the source is a bit, we don't need to sign extend, because
9207 * it can't possibly have set the sign bit.
9209 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9213 aopPut (AOP (result), zero, offset++);
9218 /* we need to extend the sign :{ */
9219 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9220 FALSE, FALSE, TRUE);
9222 emitcode ("rlc", "a");
9223 emitcode ("subb", "a,acc");
9225 aopPut (AOP (result), "a", offset++);
9228 /* we are done hurray !!!! */
9231 freeAsmop (right, NULL, ic, TRUE);
9232 freeAsmop (result, NULL, ic, TRUE);
9236 /*-----------------------------------------------------------------*/
9237 /* genDjnz - generate decrement & jump if not zero instrucion */
9238 /*-----------------------------------------------------------------*/
9240 genDjnz (iCode * ic, iCode * ifx)
9246 /* if the if condition has a false label
9247 then we cannot save */
9251 /* if the minus is not of the form
9253 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9254 !IS_OP_LITERAL (IC_RIGHT (ic)))
9257 if (operandLitValue (IC_RIGHT (ic)) != 1)
9260 /* if the size of this greater than one then no
9262 if (getSize (operandType (IC_RESULT (ic))) > 1)
9265 /* otherwise we can save BIG */
9266 D(emitcode(";", "genDjnz"););
9268 lbl = newiTempLabel (NULL);
9269 lbl1 = newiTempLabel (NULL);
9271 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9273 if (AOP_NEEDSACC(IC_RESULT(ic)))
9275 /* If the result is accessed indirectly via
9276 * the accumulator, we must explicitly write
9277 * it back after the decrement.
9279 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9281 if (strcmp(rByte, "a"))
9283 /* Something is hopelessly wrong */
9284 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9285 __FILE__, __LINE__);
9286 /* We can just give up; the generated code will be inefficient,
9289 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9292 emitcode ("dec", "%s", rByte);
9293 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9294 emitcode ("jnz", "%05d$", lbl->key + 100);
9296 else if (IS_AOP_PREG (IC_RESULT (ic)))
9298 emitcode ("dec", "%s",
9299 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9300 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9301 emitcode ("jnz", "%05d$", lbl->key + 100);
9305 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9308 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9309 emitcode ("", "%05d$:", lbl->key + 100);
9310 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9311 emitcode ("", "%05d$:", lbl1->key + 100);
9313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9318 /*-----------------------------------------------------------------*/
9319 /* genReceive - generate code for a receive iCode */
9320 /*-----------------------------------------------------------------*/
9322 genReceive (iCode * ic)
9325 D (emitcode (";", "genReceive ");
9328 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9329 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9330 IS_TRUE_SYMOP (IC_RESULT (ic))))
9332 int size = getSize (operandType (IC_RESULT (ic)));
9333 int offset = fReturnSizeDS390 - size;
9336 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9337 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9340 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9341 size = AOP_SIZE (IC_RESULT (ic));
9345 emitcode ("pop", "acc");
9346 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9353 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9355 assignResultValue (IC_RESULT (ic));
9358 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9361 /*-----------------------------------------------------------------*/
9362 /* gen390Code - generate code for Dallas 390 based controllers */
9363 /*-----------------------------------------------------------------*/
9365 gen390Code (iCode * lic)
9370 lineHead = lineCurr = NULL;
9374 /* print the allocation information */
9376 printAllocInfo (currFunc, codeOutFile);
9378 /* if debug information required */
9379 if (options.debug && currFunc)
9381 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9383 if (IS_STATIC (currFunc->etype))
9384 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9386 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9389 /* stack pointer name */
9390 if (options.useXstack)
9396 for (ic = lic; ic; ic = ic->next)
9399 if (cln != ic->lineno)
9404 emitcode ("", "C$%s$%d$%d$%d ==.",
9405 FileBaseName (ic->filename), ic->lineno,
9406 ic->level, ic->block);
9409 emitcode (";", "%s %d", ic->filename, ic->lineno);
9412 /* if the result is marked as
9413 spilt and rematerializable or code for
9414 this has already been generated then
9416 if (resultRemat (ic) || ic->generated)
9419 /* depending on the operation */
9439 /* IPOP happens only when trying to restore a
9440 spilt live range, if there is an ifx statement
9441 following this pop then the if statement might
9442 be using some of the registers being popped which
9443 would destory the contents of the register so
9444 we need to check for this condition and handle it */
9446 ic->next->op == IFX &&
9447 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9448 genIfx (ic->next, ic);
9466 genEndFunction (ic);
9486 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9503 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9507 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9514 /* note these two are xlated by algebraic equivalence
9515 during parsing SDCC.y */
9516 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9517 "got '>=' or '<=' shouldn't have come here");
9521 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9533 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9537 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9541 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9568 case GET_VALUE_AT_ADDRESS:
9573 if (POINTER_SET (ic))
9600 addSet (&_G.sendSet, ic);
9609 /* now we are ready to call the
9610 peep hole optimizer */
9611 if (!options.nopeep)
9612 peepHole (&lineHead);
9614 /* now do the actual printing */
9615 printLine (lineHead, codeOutFile);