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 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6877 emitcode ("inc", "b");
6878 freeAsmop (right, NULL, ic, TRUE);
6879 aopOp (left, ic, FALSE, FALSE);
6880 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6882 /* now move the left to the result if they are not the
6884 if (!sameRegs (AOP (left), AOP (result)) &&
6885 AOP_SIZE (result) > 1)
6888 size = AOP_SIZE (result);
6890 _startLazyDPSEvaluation ();
6893 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6894 if (*l == '@' && (IS_AOP_PREG (result)))
6897 emitcode ("mov", "a,%s", l);
6898 aopPut (AOP (result), "a", offset);
6901 aopPut (AOP (result), l, offset);
6904 _endLazyDPSEvaluation ();
6907 tlbl = newiTempLabel (NULL);
6908 size = AOP_SIZE (result);
6910 tlbl1 = newiTempLabel (NULL);
6912 /* if it is only one byte then */
6915 symbol *tlbl1 = newiTempLabel (NULL);
6917 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6919 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6920 emitcode ("", "%05d$:", tlbl->key + 100);
6921 emitcode ("add", "a,acc");
6922 emitcode ("", "%05d$:", tlbl1->key + 100);
6923 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6924 aopPut (AOP (result), "a", 0);
6928 reAdjustPreg (AOP (result));
6930 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6931 emitcode ("", "%05d$:", tlbl->key + 100);
6932 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6934 emitcode ("add", "a,acc");
6935 aopPut (AOP (result), "a", offset++);
6936 _startLazyDPSEvaluation ();
6939 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6941 emitcode ("rlc", "a");
6942 aopPut (AOP (result), "a", offset++);
6944 _endLazyDPSEvaluation ();
6945 reAdjustPreg (AOP (result));
6947 emitcode ("", "%05d$:", tlbl1->key + 100);
6948 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6950 freeAsmop (left, NULL, ic, TRUE);
6951 freeAsmop (result, NULL, ic, TRUE);
6956 /*-----------------------------------------------------------------*/
6957 /* genrshOne - right shift a one byte quantity by known count */
6958 /*-----------------------------------------------------------------*/
6960 genrshOne (operand * result, operand * left,
6961 int shCount, int sign)
6963 D (emitcode (";", "genrshOne");
6965 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6971 /*-----------------------------------------------------------------*/
6972 /* genrshTwo - right shift two bytes by known amount != 0 */
6973 /*-----------------------------------------------------------------*/
6975 genrshTwo (operand * result, operand * left,
6976 int shCount, int sign)
6978 D (emitcode (";", "genrshTwo");
6981 /* if shCount >= 8 */
6986 shiftR1Left2Result (left, MSB16, result, LSB,
6989 movLeft2Result (left, MSB16, result, LSB, sign);
6990 addSign (result, MSB16, sign);
6993 /* 1 <= shCount <= 7 */
6995 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7001 /*-----------------------------------------------------------------*/
7002 /* shiftRLong - shift right one long from left to result */
7003 /* offl = LSB or MSB16 */
7004 /*-----------------------------------------------------------------*/
7006 shiftRLong (operand * left, int offl,
7007 operand * result, int sign)
7010 emitcode ("clr", "c");
7011 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7013 emitcode ("mov", "c,acc.7");
7014 emitcode ("rrc", "a");
7015 aopPut (AOP (result), "a", MSB32 - offl);
7017 /* add sign of "a" */
7018 addSign (result, MSB32, sign);
7020 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7021 emitcode ("rrc", "a");
7022 aopPut (AOP (result), "a", MSB24 - offl);
7024 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7025 emitcode ("rrc", "a");
7026 aopPut (AOP (result), "a", MSB16 - offl);
7030 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7031 emitcode ("rrc", "a");
7032 aopPut (AOP (result), "a", LSB);
7039 /*-----------------------------------------------------------------*/
7040 /* genrshFour - shift four byte by a known amount != 0 */
7041 /*-----------------------------------------------------------------*/
7043 genrshFour (operand * result, operand * left,
7044 int shCount, int sign)
7046 D (emitcode (";", "genrshFour");
7049 /* if shifting more that 3 bytes */
7054 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7056 movLeft2Result (left, MSB32, result, LSB, sign);
7057 addSign (result, MSB16, sign);
7059 else if (shCount >= 16)
7063 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7066 movLeft2Result (left, MSB24, result, LSB, 0);
7067 movLeft2Result (left, MSB32, result, MSB16, sign);
7069 addSign (result, MSB24, sign);
7071 else if (shCount >= 8)
7075 shiftRLong (left, MSB16, result, sign);
7076 else if (shCount == 0)
7078 movLeft2Result (left, MSB16, result, LSB, 0);
7079 movLeft2Result (left, MSB24, result, MSB16, 0);
7080 movLeft2Result (left, MSB32, result, MSB24, sign);
7081 addSign (result, MSB32, sign);
7085 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7086 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7087 /* the last shift is signed */
7088 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7089 addSign (result, MSB32, sign);
7093 { /* 1 <= shCount <= 7 */
7096 shiftRLong (left, LSB, result, sign);
7098 shiftRLong (result, LSB, result, sign);
7102 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7103 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7104 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7112 /*-----------------------------------------------------------------*/
7113 /* genRightShiftLiteral - right shifting by known count */
7114 /*-----------------------------------------------------------------*/
7116 genRightShiftLiteral (operand * left,
7122 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7125 D (emitcode (";", "genRightShiftLiteral");
7128 freeAsmop (right, NULL, ic, TRUE);
7130 aopOp (left, ic, FALSE, FALSE);
7131 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7134 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7138 size = getDataSize (left);
7139 /* test the LEFT size !!! */
7141 /* I suppose that the left size >= result size */
7144 size = getDataSize (result);
7146 movLeft2Result (left, size, result, size, 0);
7149 else if (shCount >= (size * 8))
7152 /* get sign in acc.7 */
7153 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7154 addSign (result, LSB, sign);
7161 genrshOne (result, left, shCount, sign);
7165 genrshTwo (result, left, shCount, sign);
7169 genrshFour (result, left, shCount, sign);
7175 freeAsmop (left, NULL, ic, TRUE);
7176 freeAsmop (result, NULL, ic, TRUE);
7181 /*-----------------------------------------------------------------*/
7182 /* genSignedRightShift - right shift of signed number */
7183 /*-----------------------------------------------------------------*/
7185 genSignedRightShift (iCode * ic)
7187 operand *right, *left, *result;
7190 symbol *tlbl, *tlbl1;
7192 D (emitcode (";", "genSignedRightShift ");
7195 /* we do it the hard way put the shift count in b
7196 and loop thru preserving the sign */
7198 right = IC_RIGHT (ic);
7199 left = IC_LEFT (ic);
7200 result = IC_RESULT (ic);
7202 aopOp (right, ic, FALSE, FALSE);
7205 if (AOP_TYPE (right) == AOP_LIT)
7207 genRightShiftLiteral (left, right, result, ic, 1);
7211 /* shift count is unknown then we have to form
7212 a loop get the loop count in B : Note: we take
7213 only the lower order byte since shifting
7214 more that 32 bits make no sense anyway, ( the
7215 largest size of an object can be only 32 bits ) */
7217 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7218 emitcode ("inc", "b");
7219 freeAsmop (right, NULL, ic, TRUE);
7220 aopOp (left, ic, FALSE, FALSE);
7221 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7223 /* now move the left to the result if they are not the
7225 if (!sameRegs (AOP (left), AOP (result)) &&
7226 AOP_SIZE (result) > 1)
7229 size = AOP_SIZE (result);
7231 _startLazyDPSEvaluation ();
7234 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7235 if (*l == '@' && IS_AOP_PREG (result))
7238 emitcode ("mov", "a,%s", l);
7239 aopPut (AOP (result), "a", offset);
7242 aopPut (AOP (result), l, offset);
7245 _endLazyDPSEvaluation ();
7248 /* mov the highest order bit to OVR */
7249 tlbl = newiTempLabel (NULL);
7250 tlbl1 = newiTempLabel (NULL);
7252 size = AOP_SIZE (result);
7254 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7255 emitcode ("rlc", "a");
7256 emitcode ("mov", "ov,c");
7257 /* if it is only one byte then */
7260 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7262 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7263 emitcode ("", "%05d$:", tlbl->key + 100);
7264 emitcode ("mov", "c,ov");
7265 emitcode ("rrc", "a");
7266 emitcode ("", "%05d$:", tlbl1->key + 100);
7267 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7268 aopPut (AOP (result), "a", 0);
7272 reAdjustPreg (AOP (result));
7273 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7274 emitcode ("", "%05d$:", tlbl->key + 100);
7275 emitcode ("mov", "c,ov");
7276 _startLazyDPSEvaluation ();
7279 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7281 emitcode ("rrc", "a");
7282 aopPut (AOP (result), "a", offset--);
7284 _endLazyDPSEvaluation ();
7285 reAdjustPreg (AOP (result));
7286 emitcode ("", "%05d$:", tlbl1->key + 100);
7287 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7290 freeAsmop (left, NULL, ic, TRUE);
7291 freeAsmop (result, NULL, ic, TRUE);
7294 /*-----------------------------------------------------------------*/
7295 /* genRightShift - generate code for right shifting */
7296 /*-----------------------------------------------------------------*/
7298 genRightShift (iCode * ic)
7300 operand *right, *left, *result;
7304 symbol *tlbl, *tlbl1;
7306 D (emitcode (";", "genRightShift ");
7309 /* if signed then we do it the hard way preserve the
7310 sign bit moving it inwards */
7311 retype = getSpec (operandType (IC_RESULT (ic)));
7313 if (!SPEC_USIGN (retype))
7315 genSignedRightShift (ic);
7319 /* signed & unsigned types are treated the same : i.e. the
7320 signed is NOT propagated inwards : quoting from the
7321 ANSI - standard : "for E1 >> E2, is equivalent to division
7322 by 2**E2 if unsigned or if it has a non-negative value,
7323 otherwise the result is implementation defined ", MY definition
7324 is that the sign does not get propagated */
7326 right = IC_RIGHT (ic);
7327 left = IC_LEFT (ic);
7328 result = IC_RESULT (ic);
7330 aopOp (right, ic, FALSE, FALSE);
7333 /* if the shift count is known then do it
7334 as efficiently as possible */
7335 if (AOP_TYPE (right) == AOP_LIT)
7337 genRightShiftLiteral (left, right, result, ic, 0);
7342 /* shift count is unknown then we have to form
7343 a loop get the loop count in B : Note: we take
7344 only the lower order byte since shifting
7345 more that 32 bits make no sense anyway, ( the
7346 largest size of an object can be only 32 bits ) */
7348 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7349 emitcode ("inc", "b");
7350 freeAsmop (right, NULL, ic, TRUE);
7351 aopOp (left, ic, FALSE, FALSE);
7352 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7354 /* now move the left to the result if they are not the
7356 if (!sameRegs (AOP (left), AOP (result)) &&
7357 AOP_SIZE (result) > 1)
7360 size = AOP_SIZE (result);
7362 _startLazyDPSEvaluation ();
7365 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7366 if (*l == '@' && IS_AOP_PREG (result))
7369 emitcode ("mov", "a,%s", l);
7370 aopPut (AOP (result), "a", offset);
7373 aopPut (AOP (result), l, offset);
7376 _endLazyDPSEvaluation ();
7379 tlbl = newiTempLabel (NULL);
7380 tlbl1 = newiTempLabel (NULL);
7381 size = AOP_SIZE (result);
7384 /* if it is only one byte then */
7387 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7389 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7390 emitcode ("", "%05d$:", tlbl->key + 100);
7392 emitcode ("rrc", "a");
7393 emitcode ("", "%05d$:", tlbl1->key + 100);
7394 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7395 aopPut (AOP (result), "a", 0);
7399 reAdjustPreg (AOP (result));
7400 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7401 emitcode ("", "%05d$:", tlbl->key + 100);
7403 _startLazyDPSEvaluation ();
7406 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7408 emitcode ("rrc", "a");
7409 aopPut (AOP (result), "a", offset--);
7411 _endLazyDPSEvaluation ();
7412 reAdjustPreg (AOP (result));
7414 emitcode ("", "%05d$:", tlbl1->key + 100);
7415 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7418 freeAsmop (left, NULL, ic, TRUE);
7419 freeAsmop (result, NULL, ic, TRUE);
7422 /*-----------------------------------------------------------------*/
7423 /* genUnpackBits - generates code for unpacking bits */
7424 /*-----------------------------------------------------------------*/
7426 genUnpackBits (operand * result, char *rname, int ptype)
7433 D (emitcode (";", "genUnpackBits ");
7436 etype = getSpec (operandType (result));
7438 /* read the first byte */
7444 emitcode ("mov", "a,@%s", rname);
7448 emitcode ("movx", "a,@%s", rname);
7452 emitcode ("movx", "a,@dptr");
7456 emitcode ("clr", "a");
7457 emitcode ("movc", "a", "@a+dptr");
7461 emitcode ("lcall", "__gptrget");
7465 /* if we have bitdisplacement then it fits */
7466 /* into this byte completely or if length is */
7467 /* less than a byte */
7468 if ((shCnt = SPEC_BSTR (etype)) ||
7469 (SPEC_BLEN (etype) <= 8))
7472 /* shift right acc */
7475 emitcode ("anl", "a,#0x%02x",
7476 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7477 aopPut (AOP (result), "a", offset);
7481 /* bit field did not fit in a byte */
7482 rlen = SPEC_BLEN (etype) - 8;
7483 aopPut (AOP (result), "a", offset++);
7492 emitcode ("inc", "%s", rname);
7493 emitcode ("mov", "a,@%s", rname);
7497 emitcode ("inc", "%s", rname);
7498 emitcode ("movx", "a,@%s", rname);
7502 emitcode ("inc", "dptr");
7503 emitcode ("movx", "a,@dptr");
7507 emitcode ("clr", "a");
7508 emitcode ("inc", "dptr");
7509 emitcode ("movc", "a", "@a+dptr");
7513 emitcode ("inc", "dptr");
7514 emitcode ("lcall", "__gptrget");
7519 /* if we are done */
7523 aopPut (AOP (result), "a", offset++);
7529 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7530 aopPut (AOP (result), "a", offset);
7537 /*-----------------------------------------------------------------*/
7538 /* genDataPointerGet - generates code when ptr offset is known */
7539 /*-----------------------------------------------------------------*/
7541 genDataPointerGet (operand * left,
7547 int size, offset = 0;
7548 aopOp (result, ic, TRUE, FALSE);
7550 /* get the string representation of the name */
7551 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7552 size = AOP_SIZE (result);
7553 _startLazyDPSEvaluation ();
7557 sprintf (buffer, "(%s + %d)", l + 1, offset);
7559 sprintf (buffer, "%s", l + 1);
7560 aopPut (AOP (result), buffer, offset++);
7562 _endLazyDPSEvaluation ();
7564 freeAsmop (left, NULL, ic, TRUE);
7565 freeAsmop (result, NULL, ic, TRUE);
7568 /*-----------------------------------------------------------------*/
7569 /* genNearPointerGet - emitcode for near pointer fetch */
7570 /*-----------------------------------------------------------------*/
7572 genNearPointerGet (operand * left,
7579 sym_link *rtype, *retype, *letype;
7580 sym_link *ltype = operandType (left);
7583 rtype = operandType (result);
7584 retype = getSpec (rtype);
7585 letype = getSpec (ltype);
7587 aopOp (left, ic, FALSE, FALSE);
7589 /* if left is rematerialisable and
7590 result is not bit variable type and
7591 the left is pointer to data space i.e
7592 lower 128 bytes of space */
7593 if (AOP_TYPE (left) == AOP_IMMD &&
7594 !IS_BITVAR (retype) &&
7595 !IS_BITVAR (letype) &&
7596 DCL_TYPE (ltype) == POINTER)
7598 genDataPointerGet (left, result, ic);
7602 /* if the value is already in a pointer register
7603 then don't need anything more */
7604 if (!AOP_INPREG (AOP (left)))
7606 /* otherwise get a free pointer register */
7608 preg = getFreePtr (ic, &aop, FALSE);
7609 emitcode ("mov", "%s,%s",
7611 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7615 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7617 freeAsmop (left, NULL, ic, TRUE);
7618 aopOp (result, ic, FALSE, FALSE);
7620 /* if bitfield then unpack the bits */
7621 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7622 genUnpackBits (result, rname, POINTER);
7625 /* we have can just get the values */
7626 int size = AOP_SIZE (result);
7631 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7634 emitcode ("mov", "a,@%s", rname);
7635 aopPut (AOP (result), "a", offset);
7639 sprintf (buffer, "@%s", rname);
7640 aopPut (AOP (result), buffer, offset);
7644 emitcode ("inc", "%s", rname);
7648 /* now some housekeeping stuff */
7651 /* we had to allocate for this iCode */
7652 freeAsmop (NULL, aop, ic, TRUE);
7656 /* we did not allocate which means left
7657 already in a pointer register, then
7658 if size > 0 && this could be used again
7659 we have to point it back to where it
7661 if (AOP_SIZE (result) > 1 &&
7662 !OP_SYMBOL (left)->remat &&
7663 (OP_SYMBOL (left)->liveTo > ic->seq ||
7666 int size = AOP_SIZE (result) - 1;
7668 emitcode ("dec", "%s", rname);
7673 freeAsmop (result, NULL, ic, TRUE);
7677 /*-----------------------------------------------------------------*/
7678 /* genPagedPointerGet - emitcode for paged pointer fetch */
7679 /*-----------------------------------------------------------------*/
7681 genPagedPointerGet (operand * left,
7688 sym_link *rtype, *retype, *letype;
7690 rtype = operandType (result);
7691 retype = getSpec (rtype);
7692 letype = getSpec (operandType (left));
7693 aopOp (left, ic, FALSE, FALSE);
7695 /* if the value is already in a pointer register
7696 then don't need anything more */
7697 if (!AOP_INPREG (AOP (left)))
7699 /* otherwise get a free pointer register */
7701 preg = getFreePtr (ic, &aop, FALSE);
7702 emitcode ("mov", "%s,%s",
7704 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7708 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7710 freeAsmop (left, NULL, ic, TRUE);
7711 aopOp (result, ic, FALSE, FALSE);
7713 /* if bitfield then unpack the bits */
7714 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7715 genUnpackBits (result, rname, PPOINTER);
7718 /* we have can just get the values */
7719 int size = AOP_SIZE (result);
7725 emitcode ("movx", "a,@%s", rname);
7726 aopPut (AOP (result), "a", offset);
7731 emitcode ("inc", "%s", rname);
7735 /* now some housekeeping stuff */
7738 /* we had to allocate for this iCode */
7739 freeAsmop (NULL, aop, ic, TRUE);
7743 /* we did not allocate which means left
7744 already in a pointer register, then
7745 if size > 0 && this could be used again
7746 we have to point it back to where it
7748 if (AOP_SIZE (result) > 1 &&
7749 !OP_SYMBOL (left)->remat &&
7750 (OP_SYMBOL (left)->liveTo > ic->seq ||
7753 int size = AOP_SIZE (result) - 1;
7755 emitcode ("dec", "%s", rname);
7760 freeAsmop (result, NULL, ic, TRUE);
7765 /*-----------------------------------------------------------------*/
7766 /* genFarPointerGet - gget value from far space */
7767 /*-----------------------------------------------------------------*/
7769 genFarPointerGet (operand * left,
7770 operand * result, iCode * ic)
7773 sym_link *retype = getSpec (operandType (result));
7774 sym_link *letype = getSpec (operandType (left));
7775 D (emitcode (";", "genFarPointerGet");
7778 aopOp (left, ic, FALSE, FALSE);
7780 /* if the operand is already in dptr
7781 then we do nothing else we move the value to dptr */
7782 if (AOP_TYPE (left) != AOP_STR)
7784 /* if this is remateriazable */
7785 if (AOP_TYPE (left) == AOP_IMMD)
7787 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7791 /* we need to get it byte by byte */
7792 _startLazyDPSEvaluation ();
7793 if (AOP_TYPE (left) != AOP_DPTR)
7795 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7796 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7797 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7801 /* We need to generate a load to DPTR indirect through DPTR. */
7802 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7804 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7805 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7806 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7807 emitcode ("pop", "dph");
7808 emitcode ("pop", "dpl");
7810 _endLazyDPSEvaluation ();
7813 /* so dptr know contains the address */
7814 freeAsmop (left, NULL, ic, TRUE);
7815 aopOp (result, ic, FALSE, TRUE);
7817 /* if bit then unpack */
7818 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7819 genUnpackBits (result, "dptr", FPOINTER);
7822 size = AOP_SIZE (result);
7825 _startLazyDPSEvaluation ();
7832 emitcode ("movx", "a,@dptr");
7834 emitcode ("inc", "dptr");
7836 aopPut (AOP (result), "a", offset++);
7838 _endLazyDPSEvaluation ();
7841 freeAsmop (result, NULL, ic, TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* emitcodePointerGet - gget value from code space */
7846 /*-----------------------------------------------------------------*/
7848 emitcodePointerGet (operand * left,
7849 operand * result, iCode * ic)
7852 sym_link *retype = getSpec (operandType (result));
7854 aopOp (left, ic, FALSE, FALSE);
7856 /* if the operand is already in dptr
7857 then we do nothing else we move the value to dptr */
7858 if (AOP_TYPE (left) != AOP_STR)
7860 /* if this is remateriazable */
7861 if (AOP_TYPE (left) == AOP_IMMD)
7863 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7866 { /* we need to get it byte by byte */
7867 _startLazyDPSEvaluation ();
7868 if (AOP_TYPE (left) != AOP_DPTR)
7870 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7871 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7872 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7876 /* We need to generate a load to DPTR indirect through DPTR. */
7877 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7879 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7880 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7881 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7882 emitcode ("pop", "dph");
7883 emitcode ("pop", "dpl");
7885 _endLazyDPSEvaluation ();
7888 /* so dptr know contains the address */
7889 freeAsmop (left, NULL, ic, TRUE);
7890 aopOp (result, ic, FALSE, TRUE);
7892 /* if bit then unpack */
7893 if (IS_BITVAR (retype))
7894 genUnpackBits (result, "dptr", CPOINTER);
7897 size = AOP_SIZE (result);
7900 _startLazyDPSEvaluation ();
7906 emitcode ("clr", "a");
7907 emitcode ("movc", "a,@a+dptr");
7909 emitcode ("inc", "dptr");
7910 aopPut (AOP (result), "a", offset++);
7912 _endLazyDPSEvaluation ();
7915 freeAsmop (result, NULL, ic, TRUE);
7918 /*-----------------------------------------------------------------*/
7919 /* genGenPointerGet - gget value from generic pointer space */
7920 /*-----------------------------------------------------------------*/
7922 genGenPointerGet (operand * left,
7923 operand * result, iCode * ic)
7926 sym_link *retype = getSpec (operandType (result));
7927 sym_link *letype = getSpec (operandType (left));
7929 D (emitcode (";", "genGenPointerGet "); );
7931 aopOp (left, ic, FALSE, TRUE);
7933 /* if the operand is already in dptr
7934 then we do nothing else we move the value to dptr */
7935 if (AOP_TYPE (left) != AOP_STR)
7937 /* if this is remateriazable */
7938 if (AOP_TYPE (left) == AOP_IMMD)
7940 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7941 emitcode ("mov", "b,#%d", pointerCode (retype));
7944 { /* we need to get it byte by byte */
7945 _startLazyDPSEvaluation ();
7946 if (AOP(left)->type==AOP_DPTR2) {
7948 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7951 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7952 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7955 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7956 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7959 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7960 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7962 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7963 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7964 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7965 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7967 _endLazyDPSEvaluation ();
7970 /* so dptr know contains the address */
7971 freeAsmop (left, NULL, ic, TRUE);
7972 aopOp (result, ic, FALSE, TRUE);
7974 /* if bit then unpack */
7975 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7976 genUnpackBits (result, "dptr", GPOINTER);
7979 size = AOP_SIZE (result);
7984 emitcode ("lcall", "__gptrget");
7985 aopPut (AOP (result), "a", offset++);
7987 emitcode ("inc", "dptr");
7991 freeAsmop (result, NULL, ic, TRUE);
7994 /*-----------------------------------------------------------------*/
7995 /* genPointerGet - generate code for pointer get */
7996 /*-----------------------------------------------------------------*/
7998 genPointerGet (iCode * ic)
8000 operand *left, *result;
8001 sym_link *type, *etype;
8004 D (emitcode (";", "genPointerGet ");
8007 left = IC_LEFT (ic);
8008 result = IC_RESULT (ic);
8010 /* depending on the type of pointer we need to
8011 move it to the correct pointer register */
8012 type = operandType (left);
8013 etype = getSpec (type);
8014 /* if left is of type of pointer then it is simple */
8015 if (IS_PTR (type) && !IS_FUNC (type->next))
8016 p_type = DCL_TYPE (type);
8019 /* we have to go by the storage class */
8020 p_type = PTR_TYPE (SPEC_OCLS (etype));
8023 /* now that we have the pointer type we assign
8024 the pointer values */
8030 genNearPointerGet (left, result, ic);
8034 genPagedPointerGet (left, result, ic);
8038 genFarPointerGet (left, result, ic);
8042 emitcodePointerGet (left, result, ic);
8046 genGenPointerGet (left, result, ic);
8052 /*-----------------------------------------------------------------*/
8053 /* genPackBits - generates code for packed bit storage */
8054 /*-----------------------------------------------------------------*/
8056 genPackBits (sym_link * etype,
8058 char *rname, int p_type)
8066 blen = SPEC_BLEN (etype);
8067 bstr = SPEC_BSTR (etype);
8069 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8072 /* if the bit lenth is less than or */
8073 /* it exactly fits a byte then */
8074 if (SPEC_BLEN (etype) <= 8)
8076 shCount = SPEC_BSTR (etype);
8078 /* shift left acc */
8081 if (SPEC_BLEN (etype) < 8)
8082 { /* if smaller than a byte */
8088 emitcode ("mov", "b,a");
8089 emitcode ("mov", "a,@%s", rname);
8093 emitcode ("mov", "b,a");
8094 emitcode ("movx", "a,@dptr");
8098 emitcode ("push", "b");
8099 emitcode ("push", "acc");
8100 emitcode ("lcall", "__gptrget");
8101 emitcode ("pop", "b");
8105 emitcode ("anl", "a,#0x%02x", (unsigned char)
8106 ((unsigned char) (0xFF << (blen + bstr)) |
8107 (unsigned char) (0xFF >> (8 - bstr))));
8108 emitcode ("orl", "a,b");
8109 if (p_type == GPOINTER)
8110 emitcode ("pop", "b");
8117 emitcode ("mov", "@%s,a", rname);
8121 emitcode ("movx", "@dptr,a");
8125 emitcode ("lcall", "__gptrput");
8130 if (SPEC_BLEN (etype) <= 8)
8133 emitcode ("inc", "%s", rname);
8134 rLen = SPEC_BLEN (etype);
8136 /* now generate for lengths greater than one byte */
8140 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8152 emitcode ("mov", "@%s,a", rname);
8155 emitcode ("mov", "@%s,%s", rname, l);
8160 emitcode ("movx", "@dptr,a");
8165 emitcode ("lcall", "__gptrput");
8168 emitcode ("inc", "%s", rname);
8173 /* last last was not complete */
8176 /* save the byte & read byte */
8180 emitcode ("mov", "b,a");
8181 emitcode ("mov", "a,@%s", rname);
8185 emitcode ("mov", "b,a");
8186 emitcode ("movx", "a,@dptr");
8190 emitcode ("push", "b");
8191 emitcode ("push", "acc");
8192 emitcode ("lcall", "__gptrget");
8193 emitcode ("pop", "b");
8197 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8198 emitcode ("orl", "a,b");
8201 if (p_type == GPOINTER)
8202 emitcode ("pop", "b");
8208 emitcode ("mov", "@%s,a", rname);
8212 emitcode ("movx", "@dptr,a");
8216 emitcode ("lcall", "__gptrput");
8220 /*-----------------------------------------------------------------*/
8221 /* genDataPointerSet - remat pointer to data space */
8222 /*-----------------------------------------------------------------*/
8224 genDataPointerSet (operand * right,
8228 int size, offset = 0;
8229 char *l, buffer[256];
8231 aopOp (right, ic, FALSE, FALSE);
8233 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8234 size = AOP_SIZE (right);
8238 sprintf (buffer, "(%s + %d)", l + 1, offset);
8240 sprintf (buffer, "%s", l + 1);
8241 emitcode ("mov", "%s,%s", buffer,
8242 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8245 freeAsmop (right, NULL, ic, TRUE);
8246 freeAsmop (result, NULL, ic, TRUE);
8249 /*-----------------------------------------------------------------*/
8250 /* genNearPointerSet - emitcode for near pointer put */
8251 /*-----------------------------------------------------------------*/
8253 genNearPointerSet (operand * right,
8260 sym_link *retype, *letype;
8261 sym_link *ptype = operandType (result);
8263 retype = getSpec (operandType (right));
8264 letype = getSpec (ptype);
8266 aopOp (result, ic, FALSE, FALSE);
8268 /* if the result is rematerializable &
8269 in data space & not a bit variable */
8270 if (AOP_TYPE (result) == AOP_IMMD &&
8271 DCL_TYPE (ptype) == POINTER &&
8272 !IS_BITVAR (retype) &&
8273 !IS_BITVAR (letype))
8275 genDataPointerSet (right, result, ic);
8279 /* if the value is already in a pointer register
8280 then don't need anything more */
8281 if (!AOP_INPREG (AOP (result)))
8283 /* otherwise get a free pointer register */
8285 preg = getFreePtr (ic, &aop, FALSE);
8286 emitcode ("mov", "%s,%s",
8288 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8292 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8294 freeAsmop (result, NULL, ic, TRUE);
8295 aopOp (right, ic, FALSE, FALSE);
8297 /* if bitfield then unpack the bits */
8298 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8299 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8302 /* we have can just get the values */
8303 int size = AOP_SIZE (right);
8308 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8312 emitcode ("mov", "@%s,a", rname);
8315 emitcode ("mov", "@%s,%s", rname, l);
8317 emitcode ("inc", "%s", rname);
8322 /* now some housekeeping stuff */
8325 /* we had to allocate for this iCode */
8326 freeAsmop (NULL, aop, ic, TRUE);
8330 /* we did not allocate which means left
8331 already in a pointer register, then
8332 if size > 0 && this could be used again
8333 we have to point it back to where it
8335 if (AOP_SIZE (right) > 1 &&
8336 !OP_SYMBOL (result)->remat &&
8337 (OP_SYMBOL (result)->liveTo > ic->seq ||
8340 int size = AOP_SIZE (right) - 1;
8342 emitcode ("dec", "%s", rname);
8347 freeAsmop (right, NULL, ic, TRUE);
8352 /*-----------------------------------------------------------------*/
8353 /* genPagedPointerSet - emitcode for Paged pointer put */
8354 /*-----------------------------------------------------------------*/
8356 genPagedPointerSet (operand * right,
8363 sym_link *retype, *letype;
8365 retype = getSpec (operandType (right));
8366 letype = getSpec (operandType (result));
8368 aopOp (result, ic, FALSE, FALSE);
8370 /* if the value is already in a pointer register
8371 then don't need anything more */
8372 if (!AOP_INPREG (AOP (result)))
8374 /* otherwise get a free pointer register */
8376 preg = getFreePtr (ic, &aop, FALSE);
8377 emitcode ("mov", "%s,%s",
8379 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8383 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8385 freeAsmop (result, NULL, ic, TRUE);
8386 aopOp (right, ic, FALSE, FALSE);
8388 /* if bitfield then unpack the bits */
8389 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8390 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8393 /* we have can just get the values */
8394 int size = AOP_SIZE (right);
8399 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8402 emitcode ("movx", "@%s,a", rname);
8405 emitcode ("inc", "%s", rname);
8411 /* now some housekeeping stuff */
8414 /* we had to allocate for this iCode */
8415 freeAsmop (NULL, aop, ic, TRUE);
8419 /* we did not allocate which means left
8420 already in a pointer register, then
8421 if size > 0 && this could be used again
8422 we have to point it back to where it
8424 if (AOP_SIZE (right) > 1 &&
8425 !OP_SYMBOL (result)->remat &&
8426 (OP_SYMBOL (result)->liveTo > ic->seq ||
8429 int size = AOP_SIZE (right) - 1;
8431 emitcode ("dec", "%s", rname);
8436 freeAsmop (right, NULL, ic, TRUE);
8441 /*-----------------------------------------------------------------*/
8442 /* genFarPointerSet - set value from far space */
8443 /*-----------------------------------------------------------------*/
8445 genFarPointerSet (operand * right,
8446 operand * result, iCode * ic)
8449 sym_link *retype = getSpec (operandType (right));
8450 sym_link *letype = getSpec (operandType (result));
8452 aopOp (result, ic, FALSE, FALSE);
8454 /* if the operand is already in dptr
8455 then we do nothing else we move the value to dptr */
8456 if (AOP_TYPE (result) != AOP_STR)
8458 /* if this is remateriazable */
8459 if (AOP_TYPE (result) == AOP_IMMD)
8460 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8463 /* we need to get it byte by byte */
8464 _startLazyDPSEvaluation ();
8465 if (AOP_TYPE (result) != AOP_DPTR)
8467 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8468 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8469 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8473 /* We need to generate a load to DPTR indirect through DPTR. */
8474 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8476 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8477 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8478 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8479 emitcode ("pop", "dph");
8480 emitcode ("pop", "dpl");
8482 _endLazyDPSEvaluation ();
8485 /* so dptr know contains the address */
8486 freeAsmop (result, NULL, ic, TRUE);
8487 aopOp (right, ic, FALSE, TRUE);
8489 /* if bit then unpack */
8490 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8491 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8494 size = AOP_SIZE (right);
8497 _startLazyDPSEvaluation ();
8500 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8506 emitcode ("movx", "@dptr,a");
8508 emitcode ("inc", "dptr");
8510 _endLazyDPSEvaluation ();
8513 freeAsmop (right, NULL, ic, TRUE);
8516 /*-----------------------------------------------------------------*/
8517 /* genGenPointerSet - set value from generic pointer space */
8518 /*-----------------------------------------------------------------*/
8520 genGenPointerSet (operand * right,
8521 operand * result, iCode * ic)
8524 sym_link *retype = getSpec (operandType (right));
8525 sym_link *letype = getSpec (operandType (result));
8527 aopOp (result, ic, FALSE, TRUE);
8529 /* if the operand is already in dptr
8530 then we do nothing else we move the value to dptr */
8531 if (AOP_TYPE (result) != AOP_STR)
8533 _startLazyDPSEvaluation ();
8534 /* if this is remateriazable */
8535 if (AOP_TYPE (result) == AOP_IMMD)
8537 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8538 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8541 { /* we need to get it byte by byte */
8542 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8543 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8544 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8545 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8547 _endLazyDPSEvaluation ();
8549 /* so dptr know contains the address */
8550 freeAsmop (result, NULL, ic, TRUE);
8551 aopOp (right, ic, FALSE, TRUE);
8553 /* if bit then unpack */
8554 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8555 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8558 size = AOP_SIZE (right);
8561 _startLazyDPSEvaluation ();
8564 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8570 emitcode ("lcall", "__gptrput");
8572 emitcode ("inc", "dptr");
8574 _endLazyDPSEvaluation ();
8577 freeAsmop (right, NULL, ic, TRUE);
8580 /*-----------------------------------------------------------------*/
8581 /* genPointerSet - stores the value into a pointer location */
8582 /*-----------------------------------------------------------------*/
8584 genPointerSet (iCode * ic)
8586 operand *right, *result;
8587 sym_link *type, *etype;
8590 D (emitcode (";", "genPointerSet ");
8593 right = IC_RIGHT (ic);
8594 result = IC_RESULT (ic);
8596 /* depending on the type of pointer we need to
8597 move it to the correct pointer register */
8598 type = operandType (result);
8599 etype = getSpec (type);
8600 /* if left is of type of pointer then it is simple */
8601 if (IS_PTR (type) && !IS_FUNC (type->next))
8603 p_type = DCL_TYPE (type);
8607 /* we have to go by the storage class */
8608 p_type = PTR_TYPE (SPEC_OCLS (etype));
8611 /* now that we have the pointer type we assign
8612 the pointer values */
8618 genNearPointerSet (right, result, ic);
8622 genPagedPointerSet (right, result, ic);
8626 genFarPointerSet (right, result, ic);
8630 genGenPointerSet (right, result, ic);
8636 /*-----------------------------------------------------------------*/
8637 /* genIfx - generate code for Ifx statement */
8638 /*-----------------------------------------------------------------*/
8640 genIfx (iCode * ic, iCode * popIc)
8642 operand *cond = IC_COND (ic);
8645 D (emitcode (";", "genIfx "););
8647 aopOp (cond, ic, FALSE, FALSE);
8649 /* get the value into acc */
8650 if (AOP_TYPE (cond) != AOP_CRY)
8654 /* the result is now in the accumulator */
8655 freeAsmop (cond, NULL, ic, TRUE);
8657 /* if there was something to be popped then do it */
8661 /* if the condition is a bit variable */
8662 if (isbit && IS_ITEMP (cond) &&
8664 genIfxJump (ic, SPIL_LOC (cond)->rname);
8665 else if (isbit && !IS_ITEMP (cond))
8666 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8668 genIfxJump (ic, "a");
8673 /*-----------------------------------------------------------------*/
8674 /* genAddrOf - generates code for address of */
8675 /*-----------------------------------------------------------------*/
8677 genAddrOf (iCode * ic)
8679 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8682 D (emitcode (";", "genAddrOf ");
8685 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8687 /* if the operand is on the stack then we
8688 need to get the stack offset of this
8692 /* if it has an offset then we need to compute
8696 emitcode ("mov", "a,_bp");
8697 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8698 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8702 /* we can just move _bp */
8703 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8705 /* fill the result with zero */
8706 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8709 if (options.stack10bit && size < (FPTRSIZE - 1))
8712 "*** warning: pointer to stack var truncated.\n");
8719 if (options.stack10bit && offset == 2)
8721 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8725 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8732 /* object not on stack then we need the name */
8733 size = AOP_SIZE (IC_RESULT (ic));
8738 char s[SDCC_NAME_MAX];
8740 sprintf (s, "#(%s >> %d)",
8744 sprintf (s, "#%s", sym->rname);
8745 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8749 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8753 /*-----------------------------------------------------------------*/
8754 /* genFarFarAssign - assignment when both are in far space */
8755 /*-----------------------------------------------------------------*/
8757 genFarFarAssign (operand * result, operand * right, iCode * ic)
8759 int size = AOP_SIZE (right);
8765 /* This is a net loss for size == 1, but a big gain
8768 D (emitcode (";", "genFarFarAssign (improved)");
8771 aopOp (result, ic, TRUE, TRUE);
8773 _startLazyDPSEvaluation ();
8776 aopPut (AOP (result),
8777 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8780 _endLazyDPSEvaluation ();
8781 freeAsmop (result, NULL, ic, FALSE);
8782 freeAsmop (right, NULL, ic, FALSE);
8786 D (emitcode (";", "genFarFarAssign ");
8789 /* first push the right side on to the stack */
8790 _startLazyDPSEvaluation ();
8793 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8795 emitcode ("push", "acc");
8798 freeAsmop (right, NULL, ic, FALSE);
8799 /* now assign DPTR to result */
8800 aopOp (result, ic, FALSE, FALSE);
8801 size = AOP_SIZE (result);
8804 emitcode ("pop", "acc");
8805 aopPut (AOP (result), "a", --offset);
8807 freeAsmop (result, NULL, ic, FALSE);
8808 _endLazyDPSEvaluation ();
8812 /*-----------------------------------------------------------------*/
8813 /* genAssign - generate code for assignment */
8814 /*-----------------------------------------------------------------*/
8816 genAssign (iCode * ic)
8818 operand *result, *right;
8820 unsigned long lit = 0L;
8822 D (emitcode (";", "genAssign ");
8825 result = IC_RESULT (ic);
8826 right = IC_RIGHT (ic);
8828 /* if they are the same */
8829 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8832 aopOp (right, ic, FALSE, FALSE);
8834 emitcode (";", "genAssign: resultIsFar = %s",
8835 isOperandInFarSpace (result) ?
8838 /* special case both in far space */
8839 if ((AOP_TYPE (right) == AOP_DPTR ||
8840 AOP_TYPE (right) == AOP_DPTR2) &&
8841 /* IS_TRUE_SYMOP(result) && */
8842 isOperandInFarSpace (result))
8844 genFarFarAssign (result, right, ic);
8848 aopOp (result, ic, TRUE, FALSE);
8850 /* if they are the same registers */
8851 if (sameRegs (AOP (right), AOP (result)))
8854 /* if the result is a bit */
8855 if (AOP_TYPE (result) == AOP_CRY)
8858 /* if the right size is a literal then
8859 we know what the value is */
8860 if (AOP_TYPE (right) == AOP_LIT)
8862 if (((int) operandLitValue (right)))
8863 aopPut (AOP (result), one, 0);
8865 aopPut (AOP (result), zero, 0);
8869 /* the right is also a bit variable */
8870 if (AOP_TYPE (right) == AOP_CRY)
8872 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8873 aopPut (AOP (result), "c", 0);
8879 aopPut (AOP (result), "a", 0);
8883 /* bit variables done */
8885 size = AOP_SIZE (result);
8887 if (AOP_TYPE (right) == AOP_LIT)
8888 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8891 (AOP_TYPE (result) != AOP_REG) &&
8892 (AOP_TYPE (right) == AOP_LIT) &&
8893 !IS_FLOAT (operandType (right)))
8895 D (emitcode (";", "Kevin's better literal load code");
8897 _startLazyDPSEvaluation ();
8898 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8900 aopPut (AOP (result),
8901 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8906 /* And now fill the rest with zeros. */
8909 emitcode ("clr", "a");
8913 aopPut (AOP (result), "a", offset++);
8915 _endLazyDPSEvaluation ();
8919 _startLazyDPSEvaluation ();
8922 aopPut (AOP (result),
8923 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8927 _endLazyDPSEvaluation ();
8931 freeAsmop (right, NULL, ic, FALSE);
8932 freeAsmop (result, NULL, ic, TRUE);
8935 /*-----------------------------------------------------------------*/
8936 /* genJumpTab - generates code for jump table */
8937 /*-----------------------------------------------------------------*/
8939 genJumpTab (iCode * ic)
8944 D (emitcode (";", "genJumpTab ");
8947 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8948 /* get the condition into accumulator */
8949 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8951 /* multiply by four! */
8952 emitcode ("add", "a,acc");
8953 emitcode ("add", "a,acc");
8954 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8956 jtab = newiTempLabel (NULL);
8957 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8958 emitcode ("jmp", "@a+dptr");
8959 emitcode ("", "%05d$:", jtab->key + 100);
8960 /* now generate the jump labels */
8961 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8962 jtab = setNextItem (IC_JTLABELS (ic)))
8963 emitcode ("ljmp", "%05d$", jtab->key + 100);
8967 /*-----------------------------------------------------------------*/
8968 /* genCast - gen code for casting */
8969 /*-----------------------------------------------------------------*/
8971 genCast (iCode * ic)
8973 operand *result = IC_RESULT (ic);
8974 sym_link *ctype = operandType (IC_LEFT (ic));
8975 sym_link *rtype = operandType (IC_RIGHT (ic));
8976 operand *right = IC_RIGHT (ic);
8979 D (emitcode (";", "genCast ");
8982 /* if they are equivalent then do nothing */
8983 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8986 aopOp (right, ic, FALSE, FALSE);
8987 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8989 /* if the result is a bit */
8990 if (AOP_TYPE (result) == AOP_CRY)
8992 /* if the right size is a literal then
8993 we know what the value is */
8994 if (AOP_TYPE (right) == AOP_LIT)
8996 if (((int) operandLitValue (right)))
8997 aopPut (AOP (result), one, 0);
8999 aopPut (AOP (result), zero, 0);
9004 /* the right is also a bit variable */
9005 if (AOP_TYPE (right) == AOP_CRY)
9007 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9008 aopPut (AOP (result), "c", 0);
9014 aopPut (AOP (result), "a", 0);
9018 /* if they are the same size : or less */
9019 if (AOP_SIZE (result) <= AOP_SIZE (right))
9022 /* if they are in the same place */
9023 if (sameRegs (AOP (right), AOP (result)))
9026 /* if they in different places then copy */
9027 size = AOP_SIZE (result);
9029 _startLazyDPSEvaluation ();
9032 aopPut (AOP (result),
9033 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9037 _endLazyDPSEvaluation ();
9042 /* if the result is of type pointer */
9047 sym_link *type = operandType (right);
9049 /* pointer to generic pointer */
9050 if (IS_GENPTR (ctype))
9056 p_type = DCL_TYPE (type);
9060 #if OLD_CAST_BEHAVIOR
9061 /* KV: we are converting a non-pointer type to
9062 * a generic pointer. This (ifdef'd out) code
9063 * says that the resulting generic pointer
9064 * should have the same class as the storage
9065 * location of the non-pointer variable.
9067 * For example, converting an int (which happens
9068 * to be stored in DATA space) to a pointer results
9069 * in a DATA generic pointer; if the original int
9070 * in XDATA space, so will be the resulting pointer.
9072 * I don't like that behavior, and thus this change:
9073 * all such conversions will be forced to XDATA and
9074 * throw a warning. If you want some non-XDATA
9075 * type, or you want to suppress the warning, you
9076 * must go through an intermediate cast, like so:
9078 * char _generic *gp = (char _xdata *)(intVar);
9080 sym_link *etype = getSpec (type);
9082 /* we have to go by the storage class */
9083 if (SPEC_OCLS (etype) != generic)
9085 p_type = PTR_TYPE (SPEC_OCLS (etype));
9090 /* Converting unknown class (i.e. register variable)
9091 * to generic pointer. This is not good, but
9092 * we'll make a guess (and throw a warning).
9095 werror (W_INT_TO_GEN_PTR_CAST);
9099 /* the first two bytes are known */
9100 size = GPTRSIZE - 1;
9102 _startLazyDPSEvaluation ();
9105 aopPut (AOP (result),
9106 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9110 _endLazyDPSEvaluation ();
9112 /* the last byte depending on type */
9130 /* this should never happen */
9131 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9132 "got unknown pointer type");
9135 aopPut (AOP (result), l, GPTRSIZE - 1);
9139 /* just copy the pointers */
9140 size = AOP_SIZE (result);
9142 _startLazyDPSEvaluation ();
9145 aopPut (AOP (result),
9146 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9150 _endLazyDPSEvaluation ();
9154 /* so we now know that the size of destination is greater
9155 than the size of the source */
9156 /* we move to result for the size of source */
9157 size = AOP_SIZE (right);
9159 _startLazyDPSEvaluation ();
9162 aopPut (AOP (result),
9163 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9167 _endLazyDPSEvaluation ();
9169 /* now depending on the sign of the source && destination */
9170 size = AOP_SIZE (result) - AOP_SIZE (right);
9171 /* if unsigned or not an integral type */
9172 /* also, if the source is a bit, we don't need to sign extend, because
9173 * it can't possibly have set the sign bit.
9175 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9179 aopPut (AOP (result), zero, offset++);
9184 /* we need to extend the sign :{ */
9185 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9186 FALSE, FALSE, TRUE);
9188 emitcode ("rlc", "a");
9189 emitcode ("subb", "a,acc");
9191 aopPut (AOP (result), "a", offset++);
9194 /* we are done hurray !!!! */
9197 freeAsmop (right, NULL, ic, TRUE);
9198 freeAsmop (result, NULL, ic, TRUE);
9202 /*-----------------------------------------------------------------*/
9203 /* genDjnz - generate decrement & jump if not zero instrucion */
9204 /*-----------------------------------------------------------------*/
9206 genDjnz (iCode * ic, iCode * ifx)
9212 /* if the if condition has a false label
9213 then we cannot save */
9217 /* if the minus is not of the form
9219 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9220 !IS_OP_LITERAL (IC_RIGHT (ic)))
9223 if (operandLitValue (IC_RIGHT (ic)) != 1)
9226 /* if the size of this greater than one then no
9228 if (getSize (operandType (IC_RESULT (ic))) > 1)
9231 /* otherwise we can save BIG */
9232 D(emitcode(";", "genDjnz"););
9234 lbl = newiTempLabel (NULL);
9235 lbl1 = newiTempLabel (NULL);
9237 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9239 if (AOP_NEEDSACC(IC_RESULT(ic)))
9241 /* If the result is accessed indirectly via
9242 * the accumulator, we must explicitly write
9243 * it back after the decrement.
9245 emitcode ("dec", "%s",
9246 aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, FALSE));
9247 aopPut(AOP(IC_RESULT(ic)), "acc", 0);
9248 emitcode ("jnz", "%05d$", lbl->key + 100);
9250 else if (IS_AOP_PREG (IC_RESULT (ic)))
9252 emitcode ("dec", "%s",
9253 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9254 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9255 emitcode ("jnz", "%05d$", lbl->key + 100);
9259 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9262 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9263 emitcode ("", "%05d$:", lbl->key + 100);
9264 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9265 emitcode ("", "%05d$:", lbl1->key + 100);
9267 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9272 /*-----------------------------------------------------------------*/
9273 /* genReceive - generate code for a receive iCode */
9274 /*-----------------------------------------------------------------*/
9276 genReceive (iCode * ic)
9279 D (emitcode (";", "genReceive ");
9282 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9283 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9284 IS_TRUE_SYMOP (IC_RESULT (ic))))
9286 int size = getSize (operandType (IC_RESULT (ic)));
9287 int offset = fReturnSizeDS390 - size;
9290 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9291 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9294 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9295 size = AOP_SIZE (IC_RESULT (ic));
9299 emitcode ("pop", "acc");
9300 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9307 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9309 assignResultValue (IC_RESULT (ic));
9312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9315 /*-----------------------------------------------------------------*/
9316 /* gen390Code - generate code for Dallas 390 based controllers */
9317 /*-----------------------------------------------------------------*/
9319 gen390Code (iCode * lic)
9324 lineHead = lineCurr = NULL;
9328 /* print the allocation information */
9330 printAllocInfo (currFunc, codeOutFile);
9332 /* if debug information required */
9333 if (options.debug && currFunc)
9335 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9337 if (IS_STATIC (currFunc->etype))
9338 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9340 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9343 /* stack pointer name */
9344 if (options.useXstack)
9350 for (ic = lic; ic; ic = ic->next)
9353 if (cln != ic->lineno)
9358 emitcode ("", "C$%s$%d$%d$%d ==.",
9359 FileBaseName (ic->filename), ic->lineno,
9360 ic->level, ic->block);
9363 emitcode (";", "%s %d", ic->filename, ic->lineno);
9366 /* if the result is marked as
9367 spilt and rematerializable or code for
9368 this has already been generated then
9370 if (resultRemat (ic) || ic->generated)
9373 /* depending on the operation */
9393 /* IPOP happens only when trying to restore a
9394 spilt live range, if there is an ifx statement
9395 following this pop then the if statement might
9396 be using some of the registers being popped which
9397 would destory the contents of the register so
9398 we need to check for this condition and handle it */
9400 ic->next->op == IFX &&
9401 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9402 genIfx (ic->next, ic);
9420 genEndFunction (ic);
9440 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9457 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9461 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9468 /* note these two are xlated by algebraic equivalence
9469 during parsing SDCC.y */
9470 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9471 "got '>=' or '<=' shouldn't have come here");
9475 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9487 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9491 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9495 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9522 case GET_VALUE_AT_ADDRESS:
9527 if (POINTER_SET (ic))
9554 addSet (&_G.sendSet, ic);
9563 /* now we are ready to call the
9564 peep hole optimizer */
9565 if (!options.nopeep)
9566 peepHole (&lineHead);
9568 /* now do the actual printing */
9569 printLine (lineHead, codeOutFile);