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;
1477 /* The generic part of a generic pointer should
1478 * not participate in it's truth value.
1480 * i.e. 0x10000000 is zero.
1482 if (opIsGptr (oper))
1484 D (emitcode (";", "toBoolean: generic ptr special case.");
1489 _startLazyDPSEvaluation ();
1490 if (AOP_NEEDSACC (oper))
1492 emitcode ("push", "b");
1493 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1497 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1501 if (AOP_NEEDSACC (oper))
1503 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1507 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1510 _endLazyDPSEvaluation ();
1512 if (AOP_NEEDSACC (oper))
1514 emitcode ("mov", "a,b");
1515 emitcode ("pop", "b");
1520 /*-----------------------------------------------------------------*/
1521 /* genNot - generate code for ! operation */
1522 /*-----------------------------------------------------------------*/
1527 sym_link *optype = operandType (IC_LEFT (ic));
1529 D (emitcode (";", "genNot ");
1532 /* assign asmOps to operand & result */
1533 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1534 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1536 /* if in bit space then a special case */
1537 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1539 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1540 emitcode ("cpl", "c");
1541 outBitC (IC_RESULT (ic));
1545 /* if type float then do float */
1546 if (IS_FLOAT (optype))
1548 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1552 toBoolean (IC_LEFT (ic));
1554 tlbl = newiTempLabel (NULL);
1555 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1556 emitcode ("", "%05d$:", tlbl->key + 100);
1557 outBitC (IC_RESULT (ic));
1560 /* release the aops */
1561 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1562 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1566 /*-----------------------------------------------------------------*/
1567 /* genCpl - generate code for complement */
1568 /*-----------------------------------------------------------------*/
1575 D (emitcode (";", "genCpl ");
1579 /* assign asmOps to operand & result */
1580 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1581 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1583 /* if both are in bit space then
1585 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1586 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1589 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1590 emitcode ("cpl", "c");
1591 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1595 size = AOP_SIZE (IC_RESULT (ic));
1596 _startLazyDPSEvaluation ();
1599 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1601 emitcode ("cpl", "a");
1602 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1604 _endLazyDPSEvaluation ();
1608 /* release the aops */
1609 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1610 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1613 /*-----------------------------------------------------------------*/
1614 /* genUminusFloat - unary minus for floating points */
1615 /*-----------------------------------------------------------------*/
1617 genUminusFloat (operand * op, operand * result)
1619 int size, offset = 0;
1621 /* for this we just need to flip the
1622 first it then copy the rest in place */
1623 D (emitcode (";", "genUminusFloat");
1626 _startLazyDPSEvaluation ();
1627 size = AOP_SIZE (op) - 1;
1628 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1631 emitcode ("cpl", "acc.7");
1632 aopPut (AOP (result), "a", 3);
1636 aopPut (AOP (result),
1637 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1641 _endLazyDPSEvaluation ();
1644 /*-----------------------------------------------------------------*/
1645 /* genUminus - unary minus code generation */
1646 /*-----------------------------------------------------------------*/
1648 genUminus (iCode * ic)
1651 sym_link *optype, *rtype;
1653 D (emitcode (";", "genUminus ");
1658 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1659 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1661 /* if both in bit space then special
1663 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1664 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1667 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1668 emitcode ("cpl", "c");
1669 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1673 optype = operandType (IC_LEFT (ic));
1674 rtype = operandType (IC_RESULT (ic));
1676 /* if float then do float stuff */
1677 if (IS_FLOAT (optype))
1679 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1683 /* otherwise subtract from zero */
1684 size = AOP_SIZE (IC_LEFT (ic));
1686 _startLazyDPSEvaluation ();
1689 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1690 if (!strcmp (l, "a"))
1694 emitcode ("cpl", "a");
1695 emitcode ("addc", "a,#0");
1701 emitcode ("clr", "a");
1702 emitcode ("subb", "a,%s", l);
1704 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1706 _endLazyDPSEvaluation ();
1708 /* if any remaining bytes in the result */
1709 /* we just need to propagate the sign */
1710 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1712 emitcode ("rlc", "a");
1713 emitcode ("subb", "a,acc");
1715 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1719 /* release the aops */
1720 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1724 /*-----------------------------------------------------------------*/
1725 /* saveRegisters - will look for a call and save the registers */
1726 /*-----------------------------------------------------------------*/
1728 saveRegisters (iCode * lic)
1736 for (ic = lic; ic; ic = ic->next)
1737 if (ic->op == CALL || ic->op == PCALL)
1742 fprintf (stderr, "found parameter push with no function call\n");
1746 /* if the registers have been saved already then
1748 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1751 /* find the registers in use at this time
1752 and push them away to safety */
1753 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1757 if (options.useXstack)
1759 if (bitVectBitValue (rsave, R0_IDX))
1760 emitcode ("mov", "b,r0");
1761 emitcode ("mov", "r0,%s", spname);
1762 for (i = 0; i < ds390_nRegs; i++)
1764 if (bitVectBitValue (rsave, i))
1767 emitcode ("mov", "a,b");
1769 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1770 emitcode ("movx", "@r0,a");
1771 emitcode ("inc", "r0");
1774 emitcode ("mov", "%s,r0", spname);
1775 if (bitVectBitValue (rsave, R0_IDX))
1776 emitcode ("mov", "r0,b");
1779 for (i = 0; i < ds390_nRegs; i++)
1781 if (bitVectBitValue (rsave, i))
1782 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1785 detype = getSpec (operandType (IC_LEFT (ic)));
1787 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1788 IS_ISR (currFunc->etype) &&
1791 saverbank (SPEC_BANK (detype), ic, TRUE);
1794 /*-----------------------------------------------------------------*/
1795 /* unsaveRegisters - pop the pushed registers */
1796 /*-----------------------------------------------------------------*/
1798 unsaveRegisters (iCode * ic)
1802 /* find the registers in use at this time
1803 and push them away to safety */
1804 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1807 if (options.useXstack)
1809 emitcode ("mov", "r0,%s", spname);
1810 for (i = ds390_nRegs; i >= 0; i--)
1812 if (bitVectBitValue (rsave, i))
1814 emitcode ("dec", "r0");
1815 emitcode ("movx", "a,@r0");
1817 emitcode ("mov", "b,a");
1819 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1823 emitcode ("mov", "%s,r0", spname);
1824 if (bitVectBitValue (rsave, R0_IDX))
1825 emitcode ("mov", "r0,b");
1828 for (i = ds390_nRegs; i >= 0; i--)
1830 if (bitVectBitValue (rsave, i))
1831 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1837 /*-----------------------------------------------------------------*/
1839 /*-----------------------------------------------------------------*/
1841 pushSide (operand * oper, int size)
1844 _startLazyDPSEvaluation ();
1847 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1848 if (AOP_TYPE (oper) != AOP_REG &&
1849 AOP_TYPE (oper) != AOP_DIR &&
1852 emitcode ("mov", "a,%s", l);
1853 emitcode ("push", "acc");
1856 emitcode ("push", "%s", l);
1858 _endLazyDPSEvaluation ();
1861 /*-----------------------------------------------------------------*/
1862 /* assignResultValue - */
1863 /*-----------------------------------------------------------------*/
1865 assignResultValue (operand * oper)
1868 int size = AOP_SIZE (oper);
1870 _startLazyDPSEvaluation ();
1873 aopPut (AOP (oper), fReturn[offset], offset);
1876 _endLazyDPSEvaluation ();
1880 /*-----------------------------------------------------------------*/
1881 /* genXpush - pushes onto the external stack */
1882 /*-----------------------------------------------------------------*/
1884 genXpush (iCode * ic)
1886 asmop *aop = newAsmop (0);
1888 int size, offset = 0;
1890 D (emitcode (";", "genXpush ");
1893 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1894 r = getFreePtr (ic, &aop, FALSE);
1897 emitcode ("mov", "%s,_spx", r->name);
1899 size = AOP_SIZE (IC_LEFT (ic));
1900 _startLazyDPSEvaluation ();
1904 char *l = aopGet (AOP (IC_LEFT (ic)),
1905 offset++, FALSE, FALSE, TRUE);
1907 emitcode ("movx", "@%s,a", r->name);
1908 emitcode ("inc", "%s", r->name);
1911 _endLazyDPSEvaluation ();
1914 emitcode ("mov", "_spx,%s", r->name);
1916 freeAsmop (NULL, aop, ic, TRUE);
1917 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1920 /*-----------------------------------------------------------------*/
1921 /* genIpush - genrate code for pushing this gets a little complex */
1922 /*-----------------------------------------------------------------*/
1924 genIpush (iCode * ic)
1926 int size, offset = 0;
1929 D (emitcode (";", "genIpush ");
1932 /* if this is not a parm push : ie. it is spill push
1933 and spill push is always done on the local stack */
1937 /* and the item is spilt then do nothing */
1938 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1941 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1942 size = AOP_SIZE (IC_LEFT (ic));
1943 /* push it on the stack */
1944 _startLazyDPSEvaluation ();
1947 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1953 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1955 _endLazyDPSEvaluation ();
1959 /* this is a paramter push: in this case we call
1960 the routine to find the call and save those
1961 registers that need to be saved */
1964 /* if use external stack then call the external
1965 stack pushing routine */
1966 if (options.useXstack)
1972 /* then do the push */
1973 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1975 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1976 size = AOP_SIZE (IC_LEFT (ic));
1978 _startLazyDPSEvaluation ();
1981 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1982 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1983 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1986 emitcode ("mov", "a,%s", l);
1987 emitcode ("push", "acc");
1990 emitcode ("push", "%s ;jwk genIpush", l);
1992 _endLazyDPSEvaluation ();
1994 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1997 /*-----------------------------------------------------------------*/
1998 /* genIpop - recover the registers: can happen only for spilling */
1999 /*-----------------------------------------------------------------*/
2001 genIpop (iCode * ic)
2005 D (emitcode (";", "genIpop ");
2009 /* if the temp was not pushed then */
2010 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2013 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014 size = AOP_SIZE (IC_LEFT (ic));
2015 offset = (size - 1);
2016 _startLazyDPSEvaluation ();
2019 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2020 FALSE, TRUE, TRUE));
2022 _endLazyDPSEvaluation ();
2024 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2027 /*-----------------------------------------------------------------*/
2028 /* unsaverbank - restores the resgister bank from stack */
2029 /*-----------------------------------------------------------------*/
2031 unsaverbank (int bank, iCode * ic, bool popPsw)
2039 if (options.useXstack)
2042 r = getFreePtr (ic, &aop, FALSE);
2045 emitcode ("mov", "%s,_spx", r->name);
2046 emitcode ("movx", "a,@%s", r->name);
2047 emitcode ("mov", "psw,a");
2048 emitcode ("dec", "%s", r->name);
2052 emitcode ("pop", "psw");
2055 for (i = (ds390_nRegs - 1); i >= 0; i--)
2057 if (options.useXstack)
2059 emitcode ("movx", "a,@%s", r->name);
2060 emitcode ("mov", "(%s+%d),a",
2061 regs390[i].base, 8 * bank + regs390[i].offset);
2062 emitcode ("dec", "%s", r->name);
2066 emitcode ("pop", "(%s+%d)",
2067 regs390[i].base, 8 * bank + regs390[i].offset);
2070 if (options.useXstack)
2073 emitcode ("mov", "_spx,%s", r->name);
2074 freeAsmop (NULL, aop, ic, TRUE);
2079 /*-----------------------------------------------------------------*/
2080 /* saverbank - saves an entire register bank on the stack */
2081 /*-----------------------------------------------------------------*/
2083 saverbank (int bank, iCode * ic, bool pushPsw)
2089 if (options.useXstack)
2093 r = getFreePtr (ic, &aop, FALSE);
2094 emitcode ("mov", "%s,_spx", r->name);
2098 for (i = 0; i < ds390_nRegs; i++)
2100 if (options.useXstack)
2102 emitcode ("inc", "%s", r->name);
2103 emitcode ("mov", "a,(%s+%d)",
2104 regs390[i].base, 8 * bank + regs390[i].offset);
2105 emitcode ("movx", "@%s,a", r->name);
2108 emitcode ("push", "(%s+%d)",
2109 regs390[i].base, 8 * bank + regs390[i].offset);
2114 if (options.useXstack)
2116 emitcode ("mov", "a,psw");
2117 emitcode ("movx", "@%s,a", r->name);
2118 emitcode ("inc", "%s", r->name);
2119 emitcode ("mov", "_spx,%s", r->name);
2120 freeAsmop (NULL, aop, ic, TRUE);
2124 emitcode ("push", "psw");
2126 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2132 /*-----------------------------------------------------------------*/
2133 /* genCall - generates a call statement */
2134 /*-----------------------------------------------------------------*/
2136 genCall (iCode * ic)
2140 D (emitcode (";", "genCall ");
2143 /* if caller saves & we have not saved then */
2147 /* if we are calling a function that is not using
2148 the same register bank then we need to save the
2149 destination registers on the stack */
2150 detype = getSpec (operandType (IC_LEFT (ic)));
2152 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2153 IS_ISR (currFunc->etype) &&
2156 saverbank (SPEC_BANK (detype), ic, TRUE);
2158 /* if send set is not empty the assign */
2163 for (sic = setFirstItem (_G.sendSet); sic;
2164 sic = setNextItem (_G.sendSet))
2166 int size, offset = 0;
2168 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2169 size = AOP_SIZE (IC_LEFT (sic));
2171 _startLazyDPSEvaluation ();
2174 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2175 FALSE, FALSE, TRUE);
2176 if (strcmp (l, fReturn[offset])) {
2179 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2185 _endLazyDPSEvaluation ();
2186 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2191 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2192 OP_SYMBOL (IC_LEFT (ic))->rname :
2193 OP_SYMBOL (IC_LEFT (ic))->name));
2195 /* if we need assign a result value */
2196 if ((IS_ITEMP (IC_RESULT (ic)) &&
2197 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2198 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2199 IS_TRUE_SYMOP (IC_RESULT (ic)))
2201 if (isOperandInFarSpace (IC_RESULT (ic))
2202 && getSize (operandType (IC_RESULT (ic))) <= 2)
2204 int size = getSize (operandType (IC_RESULT (ic)));
2206 /* Special case for 1 or 2 byte return in far space. */
2207 emitcode (";", "Kevin function call abuse #1");
2212 emitcode ("mov", "b,%s", fReturn[1]);
2215 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2216 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2220 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2222 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2227 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2230 assignResultValue (IC_RESULT (ic));
2232 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2236 /* adjust the stack for parameters if
2241 if (ic->parmBytes > 3)
2243 emitcode ("mov", "a,%s", spname);
2244 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2245 emitcode ("mov", "%s,a", spname);
2248 for (i = 0; i < ic->parmBytes; i++)
2249 emitcode ("dec", "%s", spname);
2253 /* if register bank was saved then pop them */
2255 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2257 /* if we hade saved some registers then unsave them */
2258 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2259 unsaveRegisters (ic);
2264 /*-----------------------------------------------------------------*/
2265 /* genPcall - generates a call by pointer statement */
2266 /*-----------------------------------------------------------------*/
2268 genPcall (iCode * ic)
2271 symbol *rlbl = newiTempLabel (NULL);
2273 D (emitcode (";", "genPcall ");
2277 /* if caller saves & we have not saved then */
2281 /* if we are calling a function that is not using
2282 the same register bank then we need to save the
2283 destination registers on the stack */
2284 detype = getSpec (operandType (IC_LEFT (ic)));
2286 IS_ISR (currFunc->etype) &&
2287 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2288 saverbank (SPEC_BANK (detype), ic, TRUE);
2291 /* push the return address on to the stack */
2292 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2293 emitcode ("push", "acc");
2294 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2295 emitcode ("push", "acc");
2297 if (options.model == MODEL_FLAT24)
2299 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2300 emitcode ("push", "acc");
2303 /* now push the calling address */
2304 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2306 pushSide (IC_LEFT (ic), FPTRSIZE);
2308 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2310 /* if send set is not empty the assign */
2315 for (sic = setFirstItem (_G.sendSet); sic;
2316 sic = setNextItem (_G.sendSet))
2318 int size, offset = 0;
2320 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2321 size = AOP_SIZE (IC_LEFT (sic));
2322 _startLazyDPSEvaluation ();
2325 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2326 FALSE, FALSE, TRUE);
2327 if (strcmp (l, fReturn[offset]))
2329 emitcode ("mov", "%s,%s",
2335 _endLazyDPSEvaluation ();
2336 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2341 emitcode ("ret", "");
2342 emitcode ("", "%05d$:", (rlbl->key + 100));
2345 /* if we need assign a result value */
2346 if ((IS_ITEMP (IC_RESULT (ic)) &&
2347 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2348 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2349 IS_TRUE_SYMOP (IC_RESULT (ic)))
2353 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2356 assignResultValue (IC_RESULT (ic));
2358 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2361 /* adjust the stack for parameters if
2366 if (ic->parmBytes > 3)
2368 emitcode ("mov", "a,%s", spname);
2369 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2370 emitcode ("mov", "%s,a", spname);
2373 for (i = 0; i < ic->parmBytes; i++)
2374 emitcode ("dec", "%s", spname);
2378 /* if register bank was saved then unsave them */
2380 (SPEC_BANK (currFunc->etype) !=
2381 SPEC_BANK (detype)))
2382 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2384 /* if we hade saved some registers then
2387 unsaveRegisters (ic);
2391 /*-----------------------------------------------------------------*/
2392 /* resultRemat - result is rematerializable */
2393 /*-----------------------------------------------------------------*/
2395 resultRemat (iCode * ic)
2397 if (SKIP_IC (ic) || ic->op == IFX)
2400 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2402 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2403 if (sym->remat && !POINTER_SET (ic))
2410 #if defined(__BORLANDC__) || defined(_MSC_VER)
2411 #define STRCASECMP stricmp
2413 #define STRCASECMP strcasecmp
2416 /*-----------------------------------------------------------------*/
2417 /* inExcludeList - return 1 if the string is in exclude Reg list */
2418 /*-----------------------------------------------------------------*/
2420 inExcludeList (char *s)
2424 if (options.excludeRegs[i] &&
2425 STRCASECMP (options.excludeRegs[i], "none") == 0)
2428 for (i = 0; options.excludeRegs[i]; i++)
2430 if (options.excludeRegs[i] &&
2431 STRCASECMP (s, options.excludeRegs[i]) == 0)
2437 /*-----------------------------------------------------------------*/
2438 /* genFunction - generated code for function entry */
2439 /*-----------------------------------------------------------------*/
2441 genFunction (iCode * ic)
2446 D (emitcode (";", "genFunction ");
2450 /* create the function header */
2451 emitcode (";", "-----------------------------------------");
2452 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2453 emitcode (";", "-----------------------------------------");
2455 emitcode ("", "%s:", sym->rname);
2456 fetype = getSpec (operandType (IC_LEFT (ic)));
2458 /* if critical function then turn interrupts off */
2459 if (SPEC_CRTCL (fetype))
2460 emitcode ("clr", "ea");
2462 /* here we need to generate the equates for the
2463 register bank if required */
2464 if (SPEC_BANK (fetype) != rbank)
2468 rbank = SPEC_BANK (fetype);
2469 for (i = 0; i < ds390_nRegs; i++)
2471 if (strcmp (regs390[i].base, "0") == 0)
2472 emitcode ("", "%s = 0x%02x",
2474 8 * rbank + regs390[i].offset);
2476 emitcode ("", "%s = %s + 0x%02x",
2479 8 * rbank + regs390[i].offset);
2483 /* if this is an interrupt service routine then
2484 save acc, b, dpl, dph */
2485 if (IS_ISR (sym->etype))
2488 if (!inExcludeList ("acc"))
2489 emitcode ("push", "acc");
2490 if (!inExcludeList ("b"))
2491 emitcode ("push", "b");
2492 if (!inExcludeList ("dpl"))
2493 emitcode ("push", "dpl");
2494 if (!inExcludeList ("dph"))
2495 emitcode ("push", "dph");
2496 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2498 emitcode ("push", "dpx");
2499 /* Make sure we're using standard DPTR */
2500 emitcode ("push", "dps");
2501 emitcode ("mov", "dps, #0x00");
2502 if (options.stack10bit)
2504 /* This ISR could conceivably use DPTR2. Better save it. */
2505 emitcode ("push", "dpl1");
2506 emitcode ("push", "dph1");
2507 emitcode ("push", "dpx1");
2508 emitcode ("push", DP2_RESULT_REG);
2511 /* if this isr has no bank i.e. is going to
2512 run with bank 0 , then we need to save more
2514 if (!SPEC_BANK (sym->etype))
2517 /* if this function does not call any other
2518 function then we can be economical and
2519 save only those registers that are used */
2524 /* if any registers used */
2527 /* save the registers used */
2528 for (i = 0; i < sym->regsUsed->size; i++)
2530 if (bitVectBitValue (sym->regsUsed, i) ||
2531 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2532 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2539 /* this function has a function call cannot
2540 determines register usage so we will have the
2542 saverbank (0, ic, FALSE);
2548 /* if callee-save to be used for this function
2549 then save the registers being used in this function */
2550 if (sym->calleeSave)
2554 /* if any registers used */
2557 /* save the registers used */
2558 for (i = 0; i < sym->regsUsed->size; i++)
2560 if (bitVectBitValue (sym->regsUsed, i) ||
2561 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2563 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2571 /* set the register bank to the desired value */
2572 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2574 emitcode ("push", "psw");
2575 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2578 if (IS_RENT (sym->etype) || options.stackAuto)
2581 if (options.useXstack)
2583 emitcode ("mov", "r0,%s", spname);
2584 emitcode ("mov", "a,_bp");
2585 emitcode ("movx", "@r0,a");
2586 emitcode ("inc", "%s", spname);
2590 /* set up the stack */
2591 emitcode ("push", "_bp"); /* save the callers stack */
2593 emitcode ("mov", "_bp,%s", spname);
2596 /* adjust the stack for the function */
2602 werror (W_STACK_OVERFLOW, sym->name);
2604 if (i > 3 && sym->recvSize < 4)
2607 emitcode ("mov", "a,sp");
2608 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2609 emitcode ("mov", "sp,a");
2614 emitcode ("inc", "sp");
2620 emitcode ("mov", "a,_spx");
2621 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2622 emitcode ("mov", "_spx,a");
2627 /*-----------------------------------------------------------------*/
2628 /* genEndFunction - generates epilogue for functions */
2629 /*-----------------------------------------------------------------*/
2631 genEndFunction (iCode * ic)
2633 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2635 D (emitcode (";", "genEndFunction ");
2638 if (IS_RENT (sym->etype) || options.stackAuto)
2640 emitcode ("mov", "%s,_bp", spname);
2643 /* if use external stack but some variables were
2644 added to the local stack then decrement the
2646 if (options.useXstack && sym->stack)
2648 emitcode ("mov", "a,sp");
2649 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2650 emitcode ("mov", "sp,a");
2654 if ((IS_RENT (sym->etype) || options.stackAuto))
2656 if (options.useXstack)
2658 emitcode ("mov", "r0,%s", spname);
2659 emitcode ("movx", "a,@r0");
2660 emitcode ("mov", "_bp,a");
2661 emitcode ("dec", "%s", spname);
2665 emitcode ("pop", "_bp");
2669 /* restore the register bank */
2670 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2671 emitcode ("pop", "psw");
2673 if (IS_ISR (sym->etype))
2676 /* now we need to restore the registers */
2677 /* if this isr has no bank i.e. is going to
2678 run with bank 0 , then we need to save more
2680 if (!SPEC_BANK (sym->etype))
2683 /* if this function does not call any other
2684 function then we can be economical and
2685 save only those registers that are used */
2690 /* if any registers used */
2693 /* save the registers used */
2694 for (i = sym->regsUsed->size; i >= 0; i--)
2696 if (bitVectBitValue (sym->regsUsed, i) ||
2697 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2698 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2705 /* this function has a function call cannot
2706 determines register usage so we will have the
2708 unsaverbank (0, ic, FALSE);
2712 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2714 if (options.stack10bit)
2716 emitcode ("pop", DP2_RESULT_REG);
2717 emitcode ("pop", "dpx1");
2718 emitcode ("pop", "dph1");
2719 emitcode ("pop", "dpl1");
2721 emitcode ("pop", "dps");
2722 emitcode ("pop", "dpx");
2724 if (!inExcludeList ("dph"))
2725 emitcode ("pop", "dph");
2726 if (!inExcludeList ("dpl"))
2727 emitcode ("pop", "dpl");
2728 if (!inExcludeList ("b"))
2729 emitcode ("pop", "b");
2730 if (!inExcludeList ("acc"))
2731 emitcode ("pop", "acc");
2733 if (SPEC_CRTCL (sym->etype))
2734 emitcode ("setb", "ea");
2736 /* if debug then send end of function */
2737 /* if (options.debug && currFunc) { */
2741 emitcode ("", "C$%s$%d$%d$%d ==.",
2742 FileBaseName (ic->filename), currFunc->lastLine,
2743 ic->level, ic->block);
2744 if (IS_STATIC (currFunc->etype))
2745 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2747 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2751 emitcode ("reti", "");
2755 if (SPEC_CRTCL (sym->etype))
2756 emitcode ("setb", "ea");
2758 if (sym->calleeSave)
2762 /* if any registers used */
2765 /* save the registers used */
2766 for (i = sym->regsUsed->size; i >= 0; i--)
2768 if (bitVectBitValue (sym->regsUsed, i) ||
2769 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2770 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2776 /* if debug then send end of function */
2780 emitcode ("", "C$%s$%d$%d$%d ==.",
2781 FileBaseName (ic->filename), currFunc->lastLine,
2782 ic->level, ic->block);
2783 if (IS_STATIC (currFunc->etype))
2784 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2786 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2790 emitcode ("ret", "");
2795 /*-----------------------------------------------------------------*/
2796 /* genRet - generate code for return statement */
2797 /*-----------------------------------------------------------------*/
2801 int size, offset = 0, pushed = 0;
2803 D (emitcode (";", "genRet ");
2806 /* if we have no return value then
2807 just generate the "ret" */
2811 /* we have something to return then
2812 move the return value into place */
2813 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2814 size = AOP_SIZE (IC_LEFT (ic));
2816 _startLazyDPSEvaluation ();
2820 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2822 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2823 FALSE, TRUE, FALSE);
2824 emitcode ("push", "%s", l);
2829 l = aopGet (AOP (IC_LEFT (ic)), offset,
2830 FALSE, FALSE, FALSE);
2831 if (strcmp (fReturn[offset], l))
2832 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2835 _endLazyDPSEvaluation ();
2842 if (strcmp (fReturn[pushed], "a"))
2843 emitcode ("pop", fReturn[pushed]);
2845 emitcode ("pop", "acc");
2848 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2851 /* generate a jump to the return label
2852 if the next is not the return statement */
2853 if (!(ic->next && ic->next->op == LABEL &&
2854 IC_LABEL (ic->next) == returnLabel))
2856 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2860 /*-----------------------------------------------------------------*/
2861 /* genLabel - generates a label */
2862 /*-----------------------------------------------------------------*/
2864 genLabel (iCode * ic)
2866 /* special case never generate */
2867 if (IC_LABEL (ic) == entryLabel)
2870 D (emitcode (";", "genLabel ");
2873 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2876 /*-----------------------------------------------------------------*/
2877 /* genGoto - generates a ljmp */
2878 /*-----------------------------------------------------------------*/
2880 genGoto (iCode * ic)
2882 D (emitcode (";", "genGoto ");
2884 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2887 /*-----------------------------------------------------------------*/
2888 /* findLabelBackwards: walks back through the iCode chain looking */
2889 /* for the given label. Returns number of iCode instructions */
2890 /* between that label and given ic. */
2891 /* Returns zero if label not found. */
2892 /*-----------------------------------------------------------------*/
2894 findLabelBackwards (iCode * ic, int key)
2903 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2905 /* printf("findLabelBackwards = %d\n", count); */
2913 /*-----------------------------------------------------------------*/
2914 /* genPlusIncr :- does addition with increment if possible */
2915 /*-----------------------------------------------------------------*/
2917 genPlusIncr (iCode * ic)
2919 unsigned int icount;
2920 unsigned int size = getDataSize (IC_RESULT (ic));
2922 /* will try to generate an increment */
2923 /* if the right side is not a literal
2925 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2928 /* if the literal value of the right hand side
2929 is greater than 4 then it is not worth it */
2930 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2933 /* if increment 16 bits in register */
2935 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2936 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2937 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2945 /* If the next instruction is a goto and the goto target
2946 * is <= 5 instructions previous to this, we can generate
2947 * jumps straight to that target.
2949 if (ic->next && ic->next->op == GOTO
2950 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2953 emitcode (";", "tail increment optimized (range %d)", labelRange);
2954 tlbl = IC_LABEL (ic->next);
2959 tlbl = newiTempLabel (NULL);
2962 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2963 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2964 IS_AOP_PREG (IC_RESULT (ic)))
2965 emitcode ("cjne", "%s,#0x00,%05d$"
2966 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2970 emitcode ("clr", "a");
2971 emitcode ("cjne", "a,%s,%05d$"
2972 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2976 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2979 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2980 IS_AOP_PREG (IC_RESULT (ic)))
2981 emitcode ("cjne", "%s,#0x00,%05d$"
2982 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2985 emitcode ("cjne", "a,%s,%05d$"
2986 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2989 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2993 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2994 IS_AOP_PREG (IC_RESULT (ic)))
2995 emitcode ("cjne", "%s,#0x00,%05d$"
2996 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3000 emitcode ("cjne", "a,%s,%05d$"
3001 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3004 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3009 emitcode ("", "%05d$:", tlbl->key + 100);
3014 /* if the sizes are greater than 1 then we cannot */
3015 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3016 AOP_SIZE (IC_LEFT (ic)) > 1)
3019 /* we can if the aops of the left & result match or
3020 if they are in registers and the registers are the
3023 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3024 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3025 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3030 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3031 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3032 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3037 _startLazyDPSEvaluation ();
3040 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3042 _endLazyDPSEvaluation ();
3051 /*-----------------------------------------------------------------*/
3052 /* outBitAcc - output a bit in acc */
3053 /*-----------------------------------------------------------------*/
3055 outBitAcc (operand * result)
3057 symbol *tlbl = newiTempLabel (NULL);
3058 /* if the result is a bit */
3059 if (AOP_TYPE (result) == AOP_CRY)
3061 aopPut (AOP (result), "a", 0);
3065 emitcode ("jz", "%05d$", tlbl->key + 100);
3066 emitcode ("mov", "a,%s", one);
3067 emitcode ("", "%05d$:", tlbl->key + 100);
3072 /*-----------------------------------------------------------------*/
3073 /* genPlusBits - generates code for addition of two bits */
3074 /*-----------------------------------------------------------------*/
3076 genPlusBits (iCode * ic)
3078 D (emitcode (";", "genPlusBits ");
3080 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3082 symbol *lbl = newiTempLabel (NULL);
3083 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3084 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3085 emitcode ("cpl", "c");
3086 emitcode ("", "%05d$:", (lbl->key + 100));
3087 outBitC (IC_RESULT (ic));
3091 emitcode ("clr", "a");
3092 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3093 emitcode ("rlc", "a");
3094 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3095 emitcode ("addc", "a,#0x00");
3096 outAcc (IC_RESULT (ic));
3101 adjustArithmeticResult (iCode * ic)
3103 if (opIsGptr (IC_RESULT (ic)) &&
3104 opIsGptr (IC_LEFT (ic)) &&
3105 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3107 aopPut (AOP (IC_RESULT (ic)),
3108 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3112 if (opIsGptr (IC_RESULT (ic)) &&
3113 opIsGptr (IC_RIGHT (ic)) &&
3114 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3116 aopPut (AOP (IC_RESULT (ic)),
3117 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3121 if (opIsGptr (IC_RESULT (ic)) &&
3122 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3123 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3124 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3125 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3128 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3129 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3133 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3134 // (because all three operands are in far space).
3135 #define AOP_OP_3(ic) \
3136 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3137 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3138 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3139 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3140 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3141 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3143 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3145 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3148 // Macro to aopOp all three operands of an ic. If this cannot be done,
3149 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3150 // will be set TRUE. The caller must then handle the case specially, noting
3151 // that the IC_RESULT operand is not aopOp'd.
3152 #define AOP_OP_3_NOFATAL(ic, rc) \
3153 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3154 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3155 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3156 isOperandInFarSpace(IC_RESULT(ic))) \
3158 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3163 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3164 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3166 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3167 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3169 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3171 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3175 // aopOp the left & right operands of an ic.
3176 #define AOP_OP_2(ic) \
3177 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3178 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3180 // convienience macro.
3181 #define AOP_SET_LOCALS(ic) \
3182 left = IC_LEFT(ic); \
3183 right = IC_RIGHT(ic); \
3184 result = IC_RESULT(ic);
3187 // Given an integer value of pushedSize bytes on the stack,
3188 // adjust it to be resultSize bytes, either by discarding
3189 // the most significant bytes or by zero-padding.
3191 // On exit from this macro, pushedSize will have been adjusted to
3192 // equal resultSize, and ACC may be trashed.
3193 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3194 /* If the pushed data is bigger than the result, \
3195 * simply discard unused bytes. Icky, but works. \
3197 while (pushedSize > resultSize) \
3199 D (emitcode (";", "discarding unused result byte."););\
3200 emitcode ("pop", "acc"); \
3203 if (pushedSize < resultSize) \
3205 emitcode ("clr", "a"); \
3206 /* Conversly, we haven't pushed enough here. \
3207 * just zero-pad, and all is well. \
3209 while (pushedSize < resultSize) \
3211 emitcode("push", "acc"); \
3215 assert(pushedSize == resultSize);
3217 /*-----------------------------------------------------------------*/
3218 /* genPlus - generates code for addition */
3219 /*-----------------------------------------------------------------*/
3221 genPlus (iCode * ic)
3223 int size, offset = 0;
3224 bool pushResult = FALSE;
3227 D (emitcode (";", "genPlus "););
3229 /* special cases :- */
3231 AOP_OP_3_NOFATAL (ic, pushResult);
3234 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3239 /* if literal, literal on the right or
3240 if left requires ACC or right is already
3242 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3243 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3244 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3246 operand *t = IC_RIGHT (ic);
3247 IC_RIGHT (ic) = IC_LEFT (ic);
3249 emitcode (";", "Swapped plus args.");
3252 /* if both left & right are in bit
3254 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3255 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3261 /* if left in bit space & right literal */
3262 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3263 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3265 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3266 /* if result in bit space */
3267 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3269 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3270 emitcode ("cpl", "c");
3271 outBitC (IC_RESULT (ic));
3275 size = getDataSize (IC_RESULT (ic));
3276 _startLazyDPSEvaluation ();
3279 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3280 emitcode ("addc", "a,#00");
3281 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3283 _endLazyDPSEvaluation ();
3288 /* if I can do an increment instead
3289 of add then GOOD for ME */
3290 if (genPlusIncr (ic) == TRUE)
3292 emitcode (";", "did genPlusIncr");
3297 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3299 _startLazyDPSEvaluation ();
3302 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3304 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3306 emitcode ("add", "a,%s",
3307 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3309 emitcode ("addc", "a,%s",
3310 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3314 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3316 emitcode ("add", "a,%s",
3317 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3319 emitcode ("addc", "a,%s",
3320 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3324 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3328 emitcode ("push", "acc");
3332 _endLazyDPSEvaluation ();
3336 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3338 size = getDataSize (IC_LEFT (ic));
3339 rSize = getDataSize (IC_RESULT (ic));
3341 ADJUST_PUSHED_RESULT(size, rSize);
3343 _startLazyDPSEvaluation ();
3346 emitcode ("pop", "acc");
3347 aopPut (AOP (IC_RESULT (ic)), "a", size);
3349 _endLazyDPSEvaluation ();
3352 adjustArithmeticResult (ic);
3355 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3356 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3357 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3360 /*-----------------------------------------------------------------*/
3361 /* genMinusDec :- does subtraction with deccrement if possible */
3362 /*-----------------------------------------------------------------*/
3364 genMinusDec (iCode * ic)
3366 unsigned int icount;
3367 unsigned int size = getDataSize (IC_RESULT (ic));
3369 /* will try to generate an increment */
3370 /* if the right side is not a literal
3372 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3375 /* if the literal value of the right hand side
3376 is greater than 4 then it is not worth it */
3377 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3380 /* if decrement 16 bits in register */
3381 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3382 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3383 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3391 /* If the next instruction is a goto and the goto target
3392 * is <= 5 instructions previous to this, we can generate
3393 * jumps straight to that target.
3395 if (ic->next && ic->next->op == GOTO
3396 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3399 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3400 tlbl = IC_LABEL (ic->next);
3405 tlbl = newiTempLabel (NULL);
3409 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3410 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3412 IS_AOP_PREG (IC_RESULT (ic)))
3413 emitcode ("cjne", "%s,#0xff,%05d$"
3414 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3418 emitcode ("mov", "a,#0xff");
3419 emitcode ("cjne", "a,%s,%05d$"
3420 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3423 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3426 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3427 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3428 IS_AOP_PREG (IC_RESULT (ic)))
3429 emitcode ("cjne", "%s,#0xff,%05d$"
3430 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3434 emitcode ("cjne", "a,%s,%05d$"
3435 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3438 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3443 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3444 IS_AOP_PREG (IC_RESULT (ic)))
3445 emitcode ("cjne", "%s,#0xff,%05d$"
3446 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3450 emitcode ("cjne", "a,%s,%05d$"
3451 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3454 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3458 emitcode ("", "%05d$:", tlbl->key + 100);
3463 /* if the sizes are greater than 1 then we cannot */
3464 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3465 AOP_SIZE (IC_LEFT (ic)) > 1)
3468 /* we can if the aops of the left & result match or
3469 if they are in registers and the registers are the
3472 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3473 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3474 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3477 _startLazyDPSEvaluation ();
3480 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3482 _endLazyDPSEvaluation ();
3490 /*-----------------------------------------------------------------*/
3491 /* addSign - complete with sign */
3492 /*-----------------------------------------------------------------*/
3494 addSign (operand * result, int offset, int sign)
3496 int size = (getDataSize (result) - offset);
3501 emitcode ("rlc", "a");
3502 emitcode ("subb", "a,acc");
3504 aopPut (AOP (result), "a", offset++);
3508 aopPut (AOP (result), zero, offset++);
3512 /*-----------------------------------------------------------------*/
3513 /* genMinusBits - generates code for subtraction of two bits */
3514 /*-----------------------------------------------------------------*/
3516 genMinusBits (iCode * ic)
3518 symbol *lbl = newiTempLabel (NULL);
3520 D (emitcode (";", "genMinusBits ");
3523 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3525 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3526 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3527 emitcode ("cpl", "c");
3528 emitcode ("", "%05d$:", (lbl->key + 100));
3529 outBitC (IC_RESULT (ic));
3533 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3534 emitcode ("subb", "a,acc");
3535 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3536 emitcode ("inc", "a");
3537 emitcode ("", "%05d$:", (lbl->key + 100));
3538 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3539 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3543 /*-----------------------------------------------------------------*/
3544 /* genMinus - generates code for subtraction */
3545 /*-----------------------------------------------------------------*/
3547 genMinus (iCode * ic)
3549 int size, offset = 0;
3551 unsigned long lit = 0L;
3552 bool pushResult = FALSE;
3554 D (emitcode (";", "genMinus "););
3556 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3557 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3558 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3559 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3565 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3567 /* special cases :- */
3568 /* if both left & right are in bit space */
3569 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3570 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3576 /* if I can do an decrement instead
3577 of subtract then GOOD for ME */
3578 if (genMinusDec (ic) == TRUE)
3583 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3585 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3591 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3596 /* if literal, add a,#-lit, else normal subb */
3597 _startLazyDPSEvaluation ();
3600 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3601 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3602 emitcode ("subb", "a,%s",
3603 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3606 /* first add without previous c */
3608 emitcode ("add", "a,#0x%02x",
3609 (unsigned int) (lit & 0x0FFL));
3611 emitcode ("addc", "a,#0x%02x",
3612 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3617 emitcode ("push", "acc");
3621 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3625 _endLazyDPSEvaluation ();
3629 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3631 size = getDataSize (IC_LEFT (ic));
3632 rSize = getDataSize (IC_RESULT (ic));
3634 ADJUST_PUSHED_RESULT(size, rSize);
3636 _startLazyDPSEvaluation ();
3639 emitcode ("pop", "acc");
3640 aopPut (AOP (IC_RESULT (ic)), "a", size);
3642 _endLazyDPSEvaluation ();
3645 adjustArithmeticResult (ic);
3648 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3649 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3650 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3654 /*-----------------------------------------------------------------*/
3655 /* genMultbits :- multiplication of bits */
3656 /*-----------------------------------------------------------------*/
3658 genMultbits (operand * left,
3662 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3663 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3668 /*-----------------------------------------------------------------*/
3669 /* genMultOneByte : 8*8=8/16 bit multiplication */
3670 /*-----------------------------------------------------------------*/
3672 genMultOneByte (operand * left,
3676 sym_link *opetype = operandType (result);
3678 int size=AOP_SIZE(result);
3680 emitcode (";",__FUNCTION__);
3681 if (size<1 || size>2) {
3682 // this should never happen
3683 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3684 AOP_SIZE(result), __FUNCTION__, lineno);
3688 /* (if two literals: the value is computed before) */
3689 /* if one literal, literal on the right */
3690 if (AOP_TYPE (left) == AOP_LIT)
3695 emitcode (";", "swapped left and right");
3698 if (SPEC_USIGN(opetype)
3699 // ignore the sign of left and right, what else can we do?
3700 || (SPEC_USIGN(operandType(left)) &&
3701 SPEC_USIGN(operandType(right)))) {
3702 // just an unsigned 8*8=8/16 multiply
3703 //emitcode (";","unsigned");
3704 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3705 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3706 emitcode ("mul", "ab");
3707 aopPut (AOP (result), "a", 0);
3709 aopPut (AOP (result), "b", 1);
3714 // we have to do a signed multiply
3716 emitcode (";", "signed");
3717 emitcode ("clr", "F0"); // reset sign flag
3718 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3719 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3721 lbl=newiTempLabel(NULL);
3722 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3723 // left side is negative, 8-bit two's complement, this fails for -128
3724 emitcode ("setb", "F0"); // set sign flag
3725 emitcode ("cpl", "a");
3726 emitcode ("inc", "a");
3728 emitcode ("", "%05d$:", lbl->key+100);
3729 emitcode ("xch", "a,b");
3732 if (AOP_TYPE(right)==AOP_LIT) {
3733 /* AND literal negative */
3734 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3735 // two's complement for literal<0
3736 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3737 emitcode ("cpl", "a");
3738 emitcode ("inc", "a");
3741 lbl=newiTempLabel(NULL);
3742 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3743 // right side is negative, 8-bit two's complement
3744 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3745 emitcode ("cpl", "a");
3746 emitcode ("inc", "a");
3747 emitcode ("", "%05d$:", lbl->key+100);
3749 emitcode ("mul", "ab");
3751 lbl=newiTempLabel(NULL);
3752 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3753 // only ONE op was negative, we have to do a 8/16-bit two's complement
3754 emitcode ("cpl", "a"); // lsb
3756 emitcode ("inc", "a");
3758 emitcode ("add", "a,#1");
3759 emitcode ("xch", "a,b");
3760 emitcode ("cpl", "a"); // msb
3761 emitcode ("addc", "a,#0");
3762 emitcode ("xch", "a,b");
3765 emitcode ("", "%05d$:", lbl->key+100);
3766 aopPut (AOP (result), "a", 0);
3768 aopPut (AOP (result), "b", 1);
3772 /*-----------------------------------------------------------------*/
3773 /* genMult - generates code for multiplication */
3774 /*-----------------------------------------------------------------*/
3776 genMult (iCode * ic)
3778 operand *left = IC_LEFT (ic);
3779 operand *right = IC_RIGHT (ic);
3780 operand *result = IC_RESULT (ic);
3782 D (emitcode (";", "genMult "););
3784 /* assign the amsops */
3787 /* special cases first */
3789 if (AOP_TYPE (left) == AOP_CRY &&
3790 AOP_TYPE (right) == AOP_CRY)
3792 genMultbits (left, right, result);
3796 /* if both are of size == 1 */
3797 if (AOP_SIZE (left) == 1 &&
3798 AOP_SIZE (right) == 1)
3800 genMultOneByte (left, right, result);
3804 /* should have been converted to function call */
3808 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3809 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3810 freeAsmop (result, NULL, ic, TRUE);
3813 /*-----------------------------------------------------------------*/
3814 /* genDivbits :- division of bits */
3815 /*-----------------------------------------------------------------*/
3817 genDivbits (operand * left,
3824 /* the result must be bit */
3825 LOAD_AB_FOR_DIV (left, right, l);
3826 emitcode ("div", "ab");
3827 emitcode ("rrc", "a");
3828 aopPut (AOP (result), "c", 0);
3831 /*-----------------------------------------------------------------*/
3832 /* genDivOneByte : 8 bit division */
3833 /*-----------------------------------------------------------------*/
3835 genDivOneByte (operand * left,
3839 sym_link *opetype = operandType (result);
3844 size = AOP_SIZE (result) - 1;
3846 /* signed or unsigned */
3847 if (SPEC_USIGN (opetype))
3849 /* unsigned is easy */
3850 LOAD_AB_FOR_DIV (left, right, l);
3851 emitcode ("div", "ab");
3852 aopPut (AOP (result), "a", 0);
3854 aopPut (AOP (result), zero, offset++);
3858 /* signed is a little bit more difficult */
3860 /* save the signs of the operands */
3861 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3863 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3864 emitcode ("push", "acc"); /* save it on the stack */
3866 /* now sign adjust for both left & right */
3867 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3869 lbl = newiTempLabel (NULL);
3870 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3871 emitcode ("cpl", "a");
3872 emitcode ("inc", "a");
3873 emitcode ("", "%05d$:", (lbl->key + 100));
3874 emitcode ("mov", "b,a");
3876 /* sign adjust left side */
3877 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3880 lbl = newiTempLabel (NULL);
3881 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3882 emitcode ("cpl", "a");
3883 emitcode ("inc", "a");
3884 emitcode ("", "%05d$:", (lbl->key + 100));
3886 /* now the division */
3887 emitcode ("nop", "; workaround for DS80C390 div bug.");
3888 emitcode ("div", "ab");
3889 /* we are interested in the lower order
3891 emitcode ("mov", "b,a");
3892 lbl = newiTempLabel (NULL);
3893 emitcode ("pop", "acc");
3894 /* if there was an over flow we don't
3895 adjust the sign of the result */
3896 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3897 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3899 emitcode ("clr", "a");
3900 emitcode ("subb", "a,b");
3901 emitcode ("mov", "b,a");
3902 emitcode ("", "%05d$:", (lbl->key + 100));
3904 /* now we are done */
3905 aopPut (AOP (result), "b", 0);
3908 emitcode ("mov", "c,b.7");
3909 emitcode ("subb", "a,acc");
3912 aopPut (AOP (result), "a", offset++);
3916 /*-----------------------------------------------------------------*/
3917 /* genDiv - generates code for division */
3918 /*-----------------------------------------------------------------*/
3922 operand *left = IC_LEFT (ic);
3923 operand *right = IC_RIGHT (ic);
3924 operand *result = IC_RESULT (ic);
3926 D (emitcode (";", "genDiv ");
3929 /* assign the amsops */
3932 /* special cases first */
3934 if (AOP_TYPE (left) == AOP_CRY &&
3935 AOP_TYPE (right) == AOP_CRY)
3937 genDivbits (left, right, result);
3941 /* if both are of size == 1 */
3942 if (AOP_SIZE (left) == 1 &&
3943 AOP_SIZE (right) == 1)
3945 genDivOneByte (left, right, result);
3949 /* should have been converted to function call */
3952 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3954 freeAsmop (result, NULL, ic, TRUE);
3957 /*-----------------------------------------------------------------*/
3958 /* genModbits :- modulus of bits */
3959 /*-----------------------------------------------------------------*/
3961 genModbits (operand * left,
3968 /* the result must be bit */
3969 LOAD_AB_FOR_DIV (left, right, l);
3970 emitcode ("div", "ab");
3971 emitcode ("mov", "a,b");
3972 emitcode ("rrc", "a");
3973 aopPut (AOP (result), "c", 0);
3976 /*-----------------------------------------------------------------*/
3977 /* genModOneByte : 8 bit modulus */
3978 /*-----------------------------------------------------------------*/
3980 genModOneByte (operand * left,
3984 sym_link *opetype = operandType (result);
3988 /* signed or unsigned */
3989 if (SPEC_USIGN (opetype))
3991 /* unsigned is easy */
3992 LOAD_AB_FOR_DIV (left, right, l);
3993 emitcode ("div", "ab");
3994 aopPut (AOP (result), "b", 0);
3998 /* signed is a little bit more difficult */
4000 /* save the signs of the operands */
4001 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4004 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4005 emitcode ("push", "acc"); /* save it on the stack */
4007 /* now sign adjust for both left & right */
4008 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4011 lbl = newiTempLabel (NULL);
4012 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4013 emitcode ("cpl", "a");
4014 emitcode ("inc", "a");
4015 emitcode ("", "%05d$:", (lbl->key + 100));
4016 emitcode ("mov", "b,a");
4018 /* sign adjust left side */
4019 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4022 lbl = newiTempLabel (NULL);
4023 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4024 emitcode ("cpl", "a");
4025 emitcode ("inc", "a");
4026 emitcode ("", "%05d$:", (lbl->key + 100));
4028 /* now the multiplication */
4029 emitcode ("nop", "; workaround for DS80C390 div bug.");
4030 emitcode ("div", "ab");
4031 /* we are interested in the lower order
4033 lbl = newiTempLabel (NULL);
4034 emitcode ("pop", "acc");
4035 /* if there was an over flow we don't
4036 adjust the sign of the result */
4037 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4038 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4040 emitcode ("clr", "a");
4041 emitcode ("subb", "a,b");
4042 emitcode ("mov", "b,a");
4043 emitcode ("", "%05d$:", (lbl->key + 100));
4045 /* now we are done */
4046 aopPut (AOP (result), "b", 0);
4050 /*-----------------------------------------------------------------*/
4051 /* genMod - generates code for division */
4052 /*-----------------------------------------------------------------*/
4056 operand *left = IC_LEFT (ic);
4057 operand *right = IC_RIGHT (ic);
4058 operand *result = IC_RESULT (ic);
4060 D (emitcode (";", "genMod ");
4063 /* assign the amsops */
4066 /* special cases first */
4068 if (AOP_TYPE (left) == AOP_CRY &&
4069 AOP_TYPE (right) == AOP_CRY)
4071 genModbits (left, right, result);
4075 /* if both are of size == 1 */
4076 if (AOP_SIZE (left) == 1 &&
4077 AOP_SIZE (right) == 1)
4079 genModOneByte (left, right, result);
4083 /* should have been converted to function call */
4087 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4088 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4089 freeAsmop (result, NULL, ic, TRUE);
4092 /*-----------------------------------------------------------------*/
4093 /* genIfxJump :- will create a jump depending on the ifx */
4094 /*-----------------------------------------------------------------*/
4096 genIfxJump (iCode * ic, char *jval)
4099 symbol *tlbl = newiTempLabel (NULL);
4102 D (emitcode (";", "genIfxJump ");
4105 /* if true label then we jump if condition
4109 jlbl = IC_TRUE (ic);
4110 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4111 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4115 /* false label is present */
4116 jlbl = IC_FALSE (ic);
4117 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4118 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4120 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4121 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4123 emitcode (inst, "%05d$", tlbl->key + 100);
4124 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4125 emitcode ("", "%05d$:", tlbl->key + 100);
4127 /* mark the icode as generated */
4131 /*-----------------------------------------------------------------*/
4132 /* genCmp :- greater or less than comparison */
4133 /*-----------------------------------------------------------------*/
4135 genCmp (operand * left, operand * right,
4136 iCode * ic, iCode * ifx, int sign)
4138 int size, offset = 0;
4139 unsigned long lit = 0L;
4142 D (emitcode (";", "genCmp");
4145 result = IC_RESULT (ic);
4147 /* if left & right are bit variables */
4148 if (AOP_TYPE (left) == AOP_CRY &&
4149 AOP_TYPE (right) == AOP_CRY)
4151 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4152 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4156 /* subtract right from left if at the
4157 end the carry flag is set then we know that
4158 left is greater than right */
4159 size = max (AOP_SIZE (left), AOP_SIZE (right));
4161 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4162 if ((size == 1) && !sign &&
4163 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4165 symbol *lbl = newiTempLabel (NULL);
4166 emitcode ("cjne", "%s,%s,%05d$",
4167 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4168 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4170 emitcode ("", "%05d$:", lbl->key + 100);
4174 if (AOP_TYPE (right) == AOP_LIT)
4176 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4177 /* optimize if(x < 0) or if(x >= 0) */
4186 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4188 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4189 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191 aopOp (result, ic, FALSE, FALSE);
4193 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4195 freeAsmop (result, NULL, ic, TRUE);
4196 genIfxJump (ifx, "acc.7");
4201 emitcode ("rlc", "a");
4203 goto release_freedLR;
4211 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4212 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4213 emitcode (";", "genCmp #2");
4214 if (sign && (size == 0))
4216 emitcode (";", "genCmp #3");
4217 emitcode ("xrl", "a,#0x80");
4218 if (AOP_TYPE (right) == AOP_LIT)
4220 unsigned long lit = (unsigned long)
4221 floatFromVal (AOP (right)->aopu.aop_lit);
4222 emitcode (";", "genCmp #3.1");
4223 emitcode ("subb", "a,#0x%02x",
4224 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4228 emitcode (";", "genCmp #3.2");
4229 if (AOP_NEEDSACC (right))
4231 emitcode ("push", "acc");
4233 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4234 FALSE, FALSE, FALSE));
4235 emitcode ("xrl", "b,#0x80");
4236 if (AOP_NEEDSACC (right))
4238 emitcode ("pop", "acc");
4240 emitcode ("subb", "a,b");
4247 emitcode (";", "genCmp #4");
4248 if (AOP_NEEDSACC (right))
4251 emitcode (";", "genCmp #4.1");
4252 emitcode ("xch", "a, b");
4253 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4254 emitcode ("xch", "a, b");
4259 emitcode (";", "genCmp #4.2");
4260 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4263 emitcode ("subb", "a,%s", s);
4270 /* Don't need the left & right operands any more; do need the result. */
4271 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4272 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4274 aopOp (result, ic, FALSE, FALSE);
4278 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4284 /* if the result is used in the next
4285 ifx conditional branch then generate
4286 code a little differently */
4289 genIfxJump (ifx, "c");
4295 /* leave the result in acc */
4297 freeAsmop (result, NULL, ic, TRUE);
4300 /*-----------------------------------------------------------------*/
4301 /* genCmpGt :- greater than comparison */
4302 /*-----------------------------------------------------------------*/
4304 genCmpGt (iCode * ic, iCode * ifx)
4306 operand *left, *right;
4307 sym_link *letype, *retype;
4310 D (emitcode (";", "genCmpGt ");
4313 left = IC_LEFT (ic);
4314 right = IC_RIGHT (ic);
4316 letype = getSpec (operandType (left));
4317 retype = getSpec (operandType (right));
4318 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4320 /* assign the left & right amsops */
4323 genCmp (right, left, ic, ifx, sign);
4326 /*-----------------------------------------------------------------*/
4327 /* genCmpLt - less than comparisons */
4328 /*-----------------------------------------------------------------*/
4330 genCmpLt (iCode * ic, iCode * ifx)
4332 operand *left, *right;
4333 sym_link *letype, *retype;
4336 D (emitcode (";", "genCmpLt "););
4338 left = IC_LEFT (ic);
4339 right = IC_RIGHT (ic);
4341 letype = getSpec (operandType (left));
4342 retype = getSpec (operandType (right));
4343 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4345 /* assign the left & right amsops */
4348 genCmp (left, right, ic, ifx, sign);
4351 /*-----------------------------------------------------------------*/
4352 /* gencjneshort - compare and jump if not equal */
4353 /*-----------------------------------------------------------------*/
4355 gencjneshort (operand * left, operand * right, symbol * lbl)
4357 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4359 unsigned long lit = 0L;
4361 D (emitcode (";", "gencjneshort");
4364 /* if the left side is a literal or
4365 if the right is in a pointer register and left
4367 if ((AOP_TYPE (left) == AOP_LIT) ||
4368 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4375 if (AOP_TYPE (right) == AOP_LIT)
4376 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4378 if (opIsGptr (left) || opIsGptr (right))
4380 /* We are comparing a generic pointer to something.
4381 * Exclude the generic type byte from the comparison.
4384 D (emitcode (";", "cjneshort: generic ptr special case.");
4389 /* if the right side is a literal then anything goes */
4390 if (AOP_TYPE (right) == AOP_LIT &&
4391 AOP_TYPE (left) != AOP_DIR)
4395 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4397 emitcode ("cjne", "a,%s,%05d$",
4398 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4404 /* if the right side is in a register or in direct space or
4405 if the left is a pointer register & right is not */
4406 else if (AOP_TYPE (right) == AOP_REG ||
4407 AOP_TYPE (right) == AOP_DIR ||
4408 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4409 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4413 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4414 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4415 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4416 emitcode ("jnz", "%05d$", lbl->key + 100);
4418 emitcode ("cjne", "a,%s,%05d$",
4419 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4426 /* right is a pointer reg need both a & b */
4429 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4430 if (strcmp (l, "b"))
4431 emitcode ("mov", "b,%s", l);
4432 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4433 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4439 /*-----------------------------------------------------------------*/
4440 /* gencjne - compare and jump if not equal */
4441 /*-----------------------------------------------------------------*/
4443 gencjne (operand * left, operand * right, symbol * lbl)
4445 symbol *tlbl = newiTempLabel (NULL);
4447 D (emitcode (";", "gencjne");
4450 gencjneshort (left, right, lbl);
4452 emitcode ("mov", "a,%s", one);
4453 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4454 emitcode ("", "%05d$:", lbl->key + 100);
4455 emitcode ("clr", "a");
4456 emitcode ("", "%05d$:", tlbl->key + 100);
4459 /*-----------------------------------------------------------------*/
4460 /* genCmpEq - generates code for equal to */
4461 /*-----------------------------------------------------------------*/
4463 genCmpEq (iCode * ic, iCode * ifx)
4465 operand *left, *right, *result;
4467 D (emitcode (";", "genCmpEq ");
4471 AOP_SET_LOCALS (ic);
4473 /* if literal, literal on the right or
4474 if the right is in a pointer register and left
4476 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4477 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4479 operand *t = IC_RIGHT (ic);
4480 IC_RIGHT (ic) = IC_LEFT (ic);
4484 if (ifx && /* !AOP_SIZE(result) */
4485 OP_SYMBOL (result) &&
4486 OP_SYMBOL (result)->regType == REG_CND)
4489 /* if they are both bit variables */
4490 if (AOP_TYPE (left) == AOP_CRY &&
4491 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4493 if (AOP_TYPE (right) == AOP_LIT)
4495 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4498 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4499 emitcode ("cpl", "c");
4503 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4507 emitcode ("clr", "c");
4509 /* AOP_TYPE(right) == AOP_CRY */
4513 symbol *lbl = newiTempLabel (NULL);
4514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4515 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4516 emitcode ("cpl", "c");
4517 emitcode ("", "%05d$:", (lbl->key + 100));
4519 /* if true label then we jump if condition
4521 tlbl = newiTempLabel (NULL);
4524 emitcode ("jnc", "%05d$", tlbl->key + 100);
4525 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4529 emitcode ("jc", "%05d$", tlbl->key + 100);
4530 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4532 emitcode ("", "%05d$:", tlbl->key + 100);
4536 tlbl = newiTempLabel (NULL);
4537 gencjneshort (left, right, tlbl);
4540 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4541 emitcode ("", "%05d$:", tlbl->key + 100);
4545 symbol *lbl = newiTempLabel (NULL);
4546 emitcode ("sjmp", "%05d$", lbl->key + 100);
4547 emitcode ("", "%05d$:", tlbl->key + 100);
4548 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4549 emitcode ("", "%05d$:", lbl->key + 100);
4552 /* mark the icode as generated */
4555 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4556 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4560 /* if they are both bit variables */
4561 if (AOP_TYPE (left) == AOP_CRY &&
4562 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4564 if (AOP_TYPE (right) == AOP_LIT)
4566 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4569 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4570 emitcode ("cpl", "c");
4574 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4578 emitcode ("clr", "c");
4580 /* AOP_TYPE(right) == AOP_CRY */
4584 symbol *lbl = newiTempLabel (NULL);
4585 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4586 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4587 emitcode ("cpl", "c");
4588 emitcode ("", "%05d$:", (lbl->key + 100));
4591 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4592 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4594 aopOp (result, ic, TRUE, FALSE);
4597 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4604 genIfxJump (ifx, "c");
4607 /* if the result is used in an arithmetic operation
4608 then put the result in place */
4613 gencjne (left, right, newiTempLabel (NULL));
4615 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618 aopOp (result, ic, TRUE, FALSE);
4620 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4622 aopPut (AOP (result), "a", 0);
4627 genIfxJump (ifx, "a");
4630 /* if the result is used in an arithmetic operation
4631 then put the result in place */
4632 if (AOP_TYPE (result) != AOP_CRY)
4634 /* leave the result in acc */
4638 freeAsmop (result, NULL, ic, TRUE);
4641 /*-----------------------------------------------------------------*/
4642 /* ifxForOp - returns the icode containing the ifx for operand */
4643 /*-----------------------------------------------------------------*/
4645 ifxForOp (operand * op, iCode * ic)
4647 /* if true symbol then needs to be assigned */
4648 if (IS_TRUE_SYMOP (op))
4651 /* if this has register type condition and
4652 the next instruction is ifx with the same operand
4653 and live to of the operand is upto the ifx only then */
4655 ic->next->op == IFX &&
4656 IC_COND (ic->next)->key == op->key &&
4657 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4662 /*-----------------------------------------------------------------*/
4663 /* genAndOp - for && operation */
4664 /*-----------------------------------------------------------------*/
4666 genAndOp (iCode * ic)
4668 operand *left, *right, *result;
4671 D (emitcode (";", "genAndOp "););
4673 /* note here that && operations that are in an
4674 if statement are taken away by backPatchLabels
4675 only those used in arthmetic operations remain */
4677 AOP_SET_LOCALS (ic);
4679 /* if both are bit variables */
4680 if (AOP_TYPE (left) == AOP_CRY &&
4681 AOP_TYPE (right) == AOP_CRY)
4683 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4684 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4685 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4686 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4688 aopOp (result,ic,FALSE, FALSE);
4693 tlbl = newiTempLabel (NULL);
4695 emitcode ("jz", "%05d$", tlbl->key + 100);
4697 emitcode ("", "%05d$:", tlbl->key + 100);
4698 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4699 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4701 aopOp (result,ic,FALSE, FALSE);
4704 freeAsmop (result, NULL, ic, TRUE);
4708 /*-----------------------------------------------------------------*/
4709 /* genOrOp - for || operation */
4710 /*-----------------------------------------------------------------*/
4712 genOrOp (iCode * ic)
4714 operand *left, *right, *result;
4717 D (emitcode (";", "genOrOp "););
4719 /* note here that || operations that are in an
4720 if statement are taken away by backPatchLabels
4721 only those used in arthmetic operations remain */
4723 AOP_SET_LOCALS (ic);
4725 /* if both are bit variables */
4726 if (AOP_TYPE (left) == AOP_CRY &&
4727 AOP_TYPE (right) == AOP_CRY)
4729 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4730 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4731 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4732 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734 aopOp (result,ic,FALSE, FALSE);
4740 tlbl = newiTempLabel (NULL);
4742 emitcode ("jnz", "%05d$", tlbl->key + 100);
4744 emitcode ("", "%05d$:", tlbl->key + 100);
4745 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4746 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748 aopOp (result,ic,FALSE, FALSE);
4753 freeAsmop (result, NULL, ic, TRUE);
4756 /*-----------------------------------------------------------------*/
4757 /* isLiteralBit - test if lit == 2^n */
4758 /*-----------------------------------------------------------------*/
4760 isLiteralBit (unsigned long lit)
4762 unsigned long pw[32] =
4763 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4764 0x100L, 0x200L, 0x400L, 0x800L,
4765 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4766 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4767 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4768 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4769 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4772 for (idx = 0; idx < 32; idx++)
4778 /*-----------------------------------------------------------------*/
4779 /* continueIfTrue - */
4780 /*-----------------------------------------------------------------*/
4782 continueIfTrue (iCode * ic)
4785 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4789 /*-----------------------------------------------------------------*/
4791 /*-----------------------------------------------------------------*/
4793 jumpIfTrue (iCode * ic)
4796 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4800 /*-----------------------------------------------------------------*/
4801 /* jmpTrueOrFalse - */
4802 /*-----------------------------------------------------------------*/
4804 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4806 // ugly but optimized by peephole
4809 symbol *nlbl = newiTempLabel (NULL);
4810 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4811 emitcode ("", "%05d$:", tlbl->key + 100);
4812 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4813 emitcode ("", "%05d$:", nlbl->key + 100);
4817 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4818 emitcode ("", "%05d$:", tlbl->key + 100);
4823 // Generate code to perform a bit-wise logic operation
4824 // on two operands in far space (assumed to already have been
4825 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4826 // in far space. This requires pushing the result on the stack
4827 // then popping it into the result.
4829 genFarFarLogicOp(iCode *ic, char *logicOp)
4831 int size, resultSize, compSize;
4834 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4835 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4836 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4838 _startLazyDPSEvaluation();
4839 for (size = compSize; (size--); offset++)
4841 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4842 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4843 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4845 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4846 emitcode ("push", "acc");
4848 _endLazyDPSEvaluation();
4850 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4851 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4852 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4854 resultSize = AOP_SIZE(IC_RESULT(ic));
4856 ADJUST_PUSHED_RESULT(compSize, resultSize);
4858 _startLazyDPSEvaluation();
4861 emitcode ("pop", "acc");
4862 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4864 _endLazyDPSEvaluation();
4865 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4869 /*-----------------------------------------------------------------*/
4870 /* genAnd - code for and */
4871 /*-----------------------------------------------------------------*/
4873 genAnd (iCode * ic, iCode * ifx)
4875 operand *left, *right, *result;
4876 int size, offset = 0;
4877 unsigned long lit = 0L;
4882 D (emitcode (";", "genAnd "););
4884 AOP_OP_3_NOFATAL (ic, pushResult);
4885 AOP_SET_LOCALS (ic);
4889 genFarFarLogicOp(ic, "anl");
4894 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4896 AOP_TYPE (left), AOP_TYPE (right));
4897 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4899 AOP_SIZE (left), AOP_SIZE (right));
4902 /* if left is a literal & right is not then exchange them */
4903 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4904 AOP_NEEDSACC (left))
4906 operand *tmp = right;
4911 /* if result = right then exchange them */
4912 if (sameRegs (AOP (result), AOP (right)))
4914 operand *tmp = right;
4919 /* if right is bit then exchange them */
4920 if (AOP_TYPE (right) == AOP_CRY &&
4921 AOP_TYPE (left) != AOP_CRY)
4923 operand *tmp = right;
4927 if (AOP_TYPE (right) == AOP_LIT)
4928 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4930 size = AOP_SIZE (result);
4933 // result = bit & yy;
4934 if (AOP_TYPE (left) == AOP_CRY)
4936 // c = bit & literal;
4937 if (AOP_TYPE (right) == AOP_LIT)
4941 if (size && sameRegs (AOP (result), AOP (left)))
4944 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4949 if (size && (AOP_TYPE (result) == AOP_CRY))
4951 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4954 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4959 emitcode ("clr", "c");
4964 if (AOP_TYPE (right) == AOP_CRY)
4967 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4968 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4973 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4975 emitcode ("rrc", "a");
4976 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4984 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4985 genIfxJump (ifx, "c");
4989 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4990 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4991 if ((AOP_TYPE (right) == AOP_LIT) &&
4992 (AOP_TYPE (result) == AOP_CRY) &&
4993 (AOP_TYPE (left) != AOP_CRY))
4995 int posbit = isLiteralBit (lit);
5000 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5003 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5009 sprintf (buffer, "acc.%d", posbit & 0x07);
5010 genIfxJump (ifx, buffer);
5017 symbol *tlbl = newiTempLabel (NULL);
5018 int sizel = AOP_SIZE (left);
5020 emitcode ("setb", "c");
5023 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5025 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5027 if ((posbit = isLiteralBit (bytelit)) != 0)
5028 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5031 if (bytelit != 0x0FFL)
5032 emitcode ("anl", "a,%s",
5033 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5034 emitcode ("jnz", "%05d$", tlbl->key + 100);
5039 // bit = left & literal
5042 emitcode ("clr", "c");
5043 emitcode ("", "%05d$:", tlbl->key + 100);
5045 // if(left & literal)
5049 jmpTrueOrFalse (ifx, tlbl);
5057 /* if left is same as result */
5058 if (sameRegs (AOP (result), AOP (left)))
5060 for (; size--; offset++)
5062 if (AOP_TYPE (right) == AOP_LIT)
5064 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5066 else if (bytelit == 0)
5067 aopPut (AOP (result), zero, offset);
5068 else if (IS_AOP_PREG (result))
5070 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5071 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5072 aopPut (AOP (result), "a", offset);
5075 emitcode ("anl", "%s,%s",
5076 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5077 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5081 if (AOP_TYPE (left) == AOP_ACC)
5082 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5085 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5086 if (IS_AOP_PREG (result))
5088 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5089 aopPut (AOP (result), "a", offset);
5093 emitcode ("anl", "%s,a",
5094 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5101 // left & result in different registers
5102 if (AOP_TYPE (result) == AOP_CRY)
5105 // if(size), result in bit
5106 // if(!size && ifx), conditional oper: if(left & right)
5107 symbol *tlbl = newiTempLabel (NULL);
5108 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5110 emitcode ("setb", "c");
5113 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5114 emitcode ("anl", "a,%s",
5115 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5116 emitcode ("jnz", "%05d$", tlbl->key + 100);
5122 emitcode ("", "%05d$:", tlbl->key + 100);
5126 jmpTrueOrFalse (ifx, tlbl);
5130 for (; (size--); offset++)
5133 // result = left & right
5134 if (AOP_TYPE (right) == AOP_LIT)
5136 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5138 aopPut (AOP (result),
5139 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5143 else if (bytelit == 0)
5145 aopPut (AOP (result), zero, offset);
5148 D (emitcode (";", "better literal AND.");
5150 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5151 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5152 FALSE, FALSE, FALSE));
5157 // faster than result <- left, anl result,right
5158 // and better if result is SFR
5159 if (AOP_TYPE (left) == AOP_ACC)
5161 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5162 FALSE, FALSE, FALSE));
5166 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5167 emitcode ("anl", "a,%s",
5168 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5171 aopPut (AOP (result), "a", offset);
5177 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5178 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5179 freeAsmop (result, NULL, ic, TRUE);
5183 /*-----------------------------------------------------------------*/
5184 /* genOr - code for or */
5185 /*-----------------------------------------------------------------*/
5187 genOr (iCode * ic, iCode * ifx)
5189 operand *left, *right, *result;
5190 int size, offset = 0;
5191 unsigned long lit = 0L;
5194 D (emitcode (";", "genOr "););
5196 AOP_OP_3_NOFATAL (ic, pushResult);
5197 AOP_SET_LOCALS (ic);
5201 genFarFarLogicOp(ic, "orl");
5207 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5209 AOP_TYPE (left), AOP_TYPE (right));
5210 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5212 AOP_SIZE (left), AOP_SIZE (right));
5215 /* if left is a literal & right is not then exchange them */
5216 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5217 AOP_NEEDSACC (left))
5219 operand *tmp = right;
5224 /* if result = right then exchange them */
5225 if (sameRegs (AOP (result), AOP (right)))
5227 operand *tmp = right;
5232 /* if right is bit then exchange them */
5233 if (AOP_TYPE (right) == AOP_CRY &&
5234 AOP_TYPE (left) != AOP_CRY)
5236 operand *tmp = right;
5240 if (AOP_TYPE (right) == AOP_LIT)
5241 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5243 size = AOP_SIZE (result);
5247 if (AOP_TYPE (left) == AOP_CRY)
5249 if (AOP_TYPE (right) == AOP_LIT)
5251 // c = bit & literal;
5254 // lit != 0 => result = 1
5255 if (AOP_TYPE (result) == AOP_CRY)
5258 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5260 continueIfTrue (ifx);
5263 emitcode ("setb", "c");
5267 // lit == 0 => result = left
5268 if (size && sameRegs (AOP (result), AOP (left)))
5270 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5275 if (AOP_TYPE (right) == AOP_CRY)
5278 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5279 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5284 symbol *tlbl = newiTempLabel (NULL);
5285 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5286 emitcode ("setb", "c");
5287 emitcode ("jb", "%s,%05d$",
5288 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5290 emitcode ("jnz", "%05d$", tlbl->key + 100);
5291 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5293 jmpTrueOrFalse (ifx, tlbl);
5299 emitcode ("", "%05d$:", tlbl->key + 100);
5308 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5309 genIfxJump (ifx, "c");
5313 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5314 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5315 if ((AOP_TYPE (right) == AOP_LIT) &&
5316 (AOP_TYPE (result) == AOP_CRY) &&
5317 (AOP_TYPE (left) != AOP_CRY))
5323 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5325 continueIfTrue (ifx);
5330 // lit = 0, result = boolean(left)
5332 emitcode ("setb", "c");
5336 symbol *tlbl = newiTempLabel (NULL);
5337 emitcode ("jnz", "%05d$", tlbl->key + 100);
5339 emitcode ("", "%05d$:", tlbl->key + 100);
5343 genIfxJump (ifx, "a");
5351 /* if left is same as result */
5352 if (sameRegs (AOP (result), AOP (left)))
5354 for (; size--; offset++)
5356 if (AOP_TYPE (right) == AOP_LIT)
5358 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5364 if (IS_AOP_PREG (left))
5366 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5367 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5368 aopPut (AOP (result), "a", offset);
5372 emitcode ("orl", "%s,%s",
5373 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5374 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5380 if (AOP_TYPE (left) == AOP_ACC)
5382 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5386 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5387 if (IS_AOP_PREG (left))
5389 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5390 aopPut (AOP (result), "a", offset);
5394 emitcode ("orl", "%s,a",
5395 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5403 // left & result in different registers
5404 if (AOP_TYPE (result) == AOP_CRY)
5407 // if(size), result in bit
5408 // if(!size && ifx), conditional oper: if(left | right)
5409 symbol *tlbl = newiTempLabel (NULL);
5410 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5412 emitcode ("setb", "c");
5415 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5416 emitcode ("orl", "a,%s",
5417 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5418 emitcode ("jnz", "%05d$", tlbl->key + 100);
5424 emitcode ("", "%05d$:", tlbl->key + 100);
5428 jmpTrueOrFalse (ifx, tlbl);
5432 for (; (size--); offset++)
5435 // result = left & right
5436 if (AOP_TYPE (right) == AOP_LIT)
5438 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5440 aopPut (AOP (result),
5441 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5445 D (emitcode (";", "better literal OR.");
5447 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5448 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5449 FALSE, FALSE, FALSE));
5454 // faster than result <- left, anl result,right
5455 // and better if result is SFR
5456 if (AOP_TYPE (left) == AOP_ACC)
5458 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5459 FALSE, FALSE, FALSE));
5463 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5464 emitcode ("orl", "a,%s",
5465 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5468 aopPut (AOP (result), "a", offset);
5474 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5475 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476 freeAsmop (result, NULL, ic, TRUE);
5479 /*-----------------------------------------------------------------*/
5480 /* genXor - code for xclusive or */
5481 /*-----------------------------------------------------------------*/
5483 genXor (iCode * ic, iCode * ifx)
5485 operand *left, *right, *result;
5486 int size, offset = 0;
5487 unsigned long lit = 0L;
5490 D (emitcode (";", "genXor "););
5492 AOP_OP_3_NOFATAL (ic, pushResult);
5493 AOP_SET_LOCALS (ic);
5497 genFarFarLogicOp(ic, "xrl");
5502 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5504 AOP_TYPE (left), AOP_TYPE (right));
5505 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5507 AOP_SIZE (left), AOP_SIZE (right));
5510 /* if left is a literal & right is not ||
5511 if left needs acc & right does not */
5512 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5513 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5515 operand *tmp = right;
5520 /* if result = right then exchange them */
5521 if (sameRegs (AOP (result), AOP (right)))
5523 operand *tmp = right;
5528 /* if right is bit then exchange them */
5529 if (AOP_TYPE (right) == AOP_CRY &&
5530 AOP_TYPE (left) != AOP_CRY)
5532 operand *tmp = right;
5536 if (AOP_TYPE (right) == AOP_LIT)
5537 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5539 size = AOP_SIZE (result);
5543 if (AOP_TYPE (left) == AOP_CRY)
5545 if (AOP_TYPE (right) == AOP_LIT)
5547 // c = bit & literal;
5550 // lit>>1 != 0 => result = 1
5551 if (AOP_TYPE (result) == AOP_CRY)
5554 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5556 continueIfTrue (ifx);
5559 emitcode ("setb", "c");
5566 // lit == 0, result = left
5567 if (size && sameRegs (AOP (result), AOP (left)))
5569 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5573 // lit == 1, result = not(left)
5574 if (size && sameRegs (AOP (result), AOP (left)))
5576 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5581 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5582 emitcode ("cpl", "c");
5591 symbol *tlbl = newiTempLabel (NULL);
5592 if (AOP_TYPE (right) == AOP_CRY)
5595 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5599 int sizer = AOP_SIZE (right);
5601 // if val>>1 != 0, result = 1
5602 emitcode ("setb", "c");
5605 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5607 // test the msb of the lsb
5608 emitcode ("anl", "a,#0xfe");
5609 emitcode ("jnz", "%05d$", tlbl->key + 100);
5613 emitcode ("rrc", "a");
5615 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5616 emitcode ("cpl", "c");
5617 emitcode ("", "%05d$:", (tlbl->key + 100));
5624 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5625 genIfxJump (ifx, "c");
5629 if (sameRegs (AOP (result), AOP (left)))
5631 /* if left is same as result */
5632 for (; size--; offset++)
5634 if (AOP_TYPE (right) == AOP_LIT)
5636 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5638 else if (IS_AOP_PREG (left))
5640 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5641 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5642 aopPut (AOP (result), "a", offset);
5645 emitcode ("xrl", "%s,%s",
5646 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5647 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5651 if (AOP_TYPE (left) == AOP_ACC)
5652 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5655 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5656 if (IS_AOP_PREG (left))
5658 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5659 aopPut (AOP (result), "a", offset);
5662 emitcode ("xrl", "%s,a",
5663 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5670 // left & result in different registers
5671 if (AOP_TYPE (result) == AOP_CRY)
5674 // if(size), result in bit
5675 // if(!size && ifx), conditional oper: if(left ^ right)
5676 symbol *tlbl = newiTempLabel (NULL);
5677 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5679 emitcode ("setb", "c");
5682 if ((AOP_TYPE (right) == AOP_LIT) &&
5683 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5685 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5689 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5690 emitcode ("xrl", "a,%s",
5691 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5693 emitcode ("jnz", "%05d$", tlbl->key + 100);
5699 emitcode ("", "%05d$:", tlbl->key + 100);
5703 jmpTrueOrFalse (ifx, tlbl);
5706 for (; (size--); offset++)
5709 // result = left & right
5710 if (AOP_TYPE (right) == AOP_LIT)
5712 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5714 aopPut (AOP (result),
5715 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5719 D (emitcode (";", "better literal XOR.");
5721 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5722 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5723 FALSE, FALSE, FALSE));
5727 // faster than result <- left, anl result,right
5728 // and better if result is SFR
5729 if (AOP_TYPE (left) == AOP_ACC)
5731 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5732 FALSE, FALSE, FALSE));
5736 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5737 emitcode ("xrl", "a,%s",
5738 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5741 aopPut (AOP (result), "a", offset);
5746 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5747 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5748 freeAsmop (result, NULL, ic, TRUE);
5751 /*-----------------------------------------------------------------*/
5752 /* genInline - write the inline code out */
5753 /*-----------------------------------------------------------------*/
5755 genInline (iCode * ic)
5757 char buffer[MAX_INLINEASM];
5761 D (emitcode (";", "genInline ");
5764 _G.inLine += (!options.asmpeep);
5765 strcpy (buffer, IC_INLINE (ic));
5767 /* emit each line as a code */
5792 /* emitcode("",buffer); */
5793 _G.inLine -= (!options.asmpeep);
5796 /*-----------------------------------------------------------------*/
5797 /* genRRC - rotate right with carry */
5798 /*-----------------------------------------------------------------*/
5802 operand *left, *result;
5803 int size, offset = 0;
5806 D (emitcode (";", "genRRC ");
5809 /* rotate right with carry */
5810 left = IC_LEFT (ic);
5811 result = IC_RESULT (ic);
5812 aopOp (left, ic, FALSE, FALSE);
5813 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5815 /* move it to the result */
5816 size = AOP_SIZE (result);
5820 _startLazyDPSEvaluation ();
5823 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5825 emitcode ("rrc", "a");
5826 if (AOP_SIZE (result) > 1)
5827 aopPut (AOP (result), "a", offset--);
5829 _endLazyDPSEvaluation ();
5831 /* now we need to put the carry into the
5832 highest order byte of the result */
5833 if (AOP_SIZE (result) > 1)
5835 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5838 emitcode ("mov", "acc.7,c");
5839 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5840 freeAsmop (left, NULL, ic, TRUE);
5841 freeAsmop (result, NULL, ic, TRUE);
5844 /*-----------------------------------------------------------------*/
5845 /* genRLC - generate code for rotate left with carry */
5846 /*-----------------------------------------------------------------*/
5850 operand *left, *result;
5851 int size, offset = 0;
5854 D (emitcode (";", "genRLC ");
5857 /* rotate right with carry */
5858 left = IC_LEFT (ic);
5859 result = IC_RESULT (ic);
5860 aopOp (left, ic, FALSE, FALSE);
5861 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5863 /* move it to the result */
5864 size = AOP_SIZE (result);
5868 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5870 emitcode ("add", "a,acc");
5871 if (AOP_SIZE (result) > 1)
5873 aopPut (AOP (result), "a", offset++);
5876 _startLazyDPSEvaluation ();
5879 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5881 emitcode ("rlc", "a");
5882 if (AOP_SIZE (result) > 1)
5883 aopPut (AOP (result), "a", offset++);
5885 _endLazyDPSEvaluation ();
5887 /* now we need to put the carry into the
5888 highest order byte of the result */
5889 if (AOP_SIZE (result) > 1)
5891 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5894 emitcode ("mov", "acc.0,c");
5895 aopPut (AOP (result), "a", 0);
5896 freeAsmop (left, NULL, ic, TRUE);
5897 freeAsmop (result, NULL, ic, TRUE);
5900 /*-----------------------------------------------------------------*/
5901 /* genGetHbit - generates code get highest order bit */
5902 /*-----------------------------------------------------------------*/
5904 genGetHbit (iCode * ic)
5906 operand *left, *result;
5907 left = IC_LEFT (ic);
5908 result = IC_RESULT (ic);
5909 aopOp (left, ic, FALSE, FALSE);
5910 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5912 D (emitcode (";", "genGetHbit ");
5915 /* get the highest order byte into a */
5916 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5917 if (AOP_TYPE (result) == AOP_CRY)
5919 emitcode ("rlc", "a");
5924 emitcode ("rl", "a");
5925 emitcode ("anl", "a,#0x01");
5930 freeAsmop (left, NULL, ic, TRUE);
5931 freeAsmop (result, NULL, ic, TRUE);
5934 /*-----------------------------------------------------------------*/
5935 /* AccRol - rotate left accumulator by known count */
5936 /*-----------------------------------------------------------------*/
5938 AccRol (int shCount)
5940 shCount &= 0x0007; // shCount : 0..7
5947 emitcode ("rl", "a");
5950 emitcode ("rl", "a");
5951 emitcode ("rl", "a");
5954 emitcode ("swap", "a");
5955 emitcode ("rr", "a");
5958 emitcode ("swap", "a");
5961 emitcode ("swap", "a");
5962 emitcode ("rl", "a");
5965 emitcode ("rr", "a");
5966 emitcode ("rr", "a");
5969 emitcode ("rr", "a");
5974 /*-----------------------------------------------------------------*/
5975 /* AccLsh - left shift accumulator by known count */
5976 /*-----------------------------------------------------------------*/
5978 AccLsh (int shCount)
5983 emitcode ("add", "a,acc");
5984 else if (shCount == 2)
5986 emitcode ("add", "a,acc");
5987 emitcode ("add", "a,acc");
5991 /* rotate left accumulator */
5993 /* and kill the lower order bits */
5994 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5999 /*-----------------------------------------------------------------*/
6000 /* AccRsh - right shift accumulator by known count */
6001 /*-----------------------------------------------------------------*/
6003 AccRsh (int shCount)
6010 emitcode ("rrc", "a");
6014 /* rotate right accumulator */
6015 AccRol (8 - shCount);
6016 /* and kill the higher order bits */
6017 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6024 /*-----------------------------------------------------------------*/
6025 /* AccSRsh - signed right shift accumulator by known count */
6026 /*-----------------------------------------------------------------*/
6028 AccSRsh (int shCount)
6035 emitcode ("mov", "c,acc.7");
6036 emitcode ("rrc", "a");
6038 else if (shCount == 2)
6040 emitcode ("mov", "c,acc.7");
6041 emitcode ("rrc", "a");
6042 emitcode ("mov", "c,acc.7");
6043 emitcode ("rrc", "a");
6047 tlbl = newiTempLabel (NULL);
6048 /* rotate right accumulator */
6049 AccRol (8 - shCount);
6050 /* and kill the higher order bits */
6051 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6052 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6053 emitcode ("orl", "a,#0x%02x",
6054 (unsigned char) ~SRMask[shCount]);
6055 emitcode ("", "%05d$:", tlbl->key + 100);
6063 /*-----------------------------------------------------------------*/
6064 /* shiftR1Left2Result - shift right one byte from left to result */
6065 /*-----------------------------------------------------------------*/
6067 shiftR1Left2Result (operand * left, int offl,
6068 operand * result, int offr,
6069 int shCount, int sign)
6071 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6072 /* shift right accumulator */
6077 aopPut (AOP (result), "a", offr);
6083 /*-----------------------------------------------------------------*/
6084 /* shiftL1Left2Result - shift left one byte from left to result */
6085 /*-----------------------------------------------------------------*/
6087 shiftL1Left2Result (operand * left, int offl,
6088 operand * result, int offr, int shCount)
6091 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6093 /* shift left accumulator */
6095 aopPut (AOP (result), "a", offr);
6101 /*-----------------------------------------------------------------*/
6102 /* movLeft2Result - move byte from left to result */
6103 /*-----------------------------------------------------------------*/
6105 movLeft2Result (operand * left, int offl,
6106 operand * result, int offr, int sign)
6109 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6111 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6113 if (*l == '@' && (IS_AOP_PREG (result)))
6115 emitcode ("mov", "a,%s", l);
6116 aopPut (AOP (result), "a", offr);
6121 aopPut (AOP (result), l, offr);
6124 /* MSB sign in acc.7 ! */
6125 if (getDataSize (left) == offl + 1)
6127 emitcode ("mov", "a,%s", l);
6128 aopPut (AOP (result), "a", offr);
6138 /*-----------------------------------------------------------------*/
6139 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6140 /*-----------------------------------------------------------------*/
6144 emitcode ("rrc", "a");
6145 emitcode ("xch", "a,%s", x);
6146 emitcode ("rrc", "a");
6147 emitcode ("xch", "a,%s", x);
6153 /*-----------------------------------------------------------------*/
6154 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6155 /*-----------------------------------------------------------------*/
6159 emitcode ("xch", "a,%s", x);
6160 emitcode ("rlc", "a");
6161 emitcode ("xch", "a,%s", x);
6162 emitcode ("rlc", "a");
6168 /*-----------------------------------------------------------------*/
6169 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6170 /*-----------------------------------------------------------------*/
6174 emitcode ("xch", "a,%s", x);
6175 emitcode ("add", "a,acc");
6176 emitcode ("xch", "a,%s", x);
6177 emitcode ("rlc", "a");
6183 /*-----------------------------------------------------------------*/
6184 /* AccAXLsh - left shift a:x by known count (0..7) */
6185 /*-----------------------------------------------------------------*/
6187 AccAXLsh (char *x, int shCount)
6202 case 5: // AAAAABBB:CCCCCDDD
6204 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6206 emitcode ("anl", "a,#0x%02x",
6207 SLMask[shCount]); // BBB00000:CCCCCDDD
6209 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6211 AccRol (shCount); // DDDCCCCC:BBB00000
6213 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6215 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6217 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6219 emitcode ("anl", "a,#0x%02x",
6220 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6222 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6224 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6227 case 6: // AAAAAABB:CCCCCCDD
6228 emitcode ("anl", "a,#0x%02x",
6229 SRMask[shCount]); // 000000BB:CCCCCCDD
6230 emitcode ("mov", "c,acc.0"); // c = B
6231 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6233 AccAXRrl1 (x); // BCCCCCCD:D000000B
6234 AccAXRrl1 (x); // BBCCCCCC:DD000000
6236 emitcode("rrc","a");
6237 emitcode("xch","a,%s", x);
6238 emitcode("rrc","a");
6239 emitcode("mov","c,acc.0"); //<< get correct bit
6240 emitcode("xch","a,%s", x);
6242 emitcode("rrc","a");
6243 emitcode("xch","a,%s", x);
6244 emitcode("rrc","a");
6245 emitcode("xch","a,%s", x);
6248 case 7: // a:x <<= 7
6250 emitcode ("anl", "a,#0x%02x",
6251 SRMask[shCount]); // 0000000B:CCCCCCCD
6253 emitcode ("mov", "c,acc.0"); // c = B
6255 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6257 AccAXRrl1 (x); // BCCCCCCC:D0000000
6268 /*-----------------------------------------------------------------*/
6269 /* AccAXRsh - right shift a:x known count (0..7) */
6270 /*-----------------------------------------------------------------*/
6272 AccAXRsh (char *x, int shCount)
6280 AccAXRrl1 (x); // 0->a:x
6285 AccAXRrl1 (x); // 0->a:x
6288 AccAXRrl1 (x); // 0->a:x
6293 case 5: // AAAAABBB:CCCCCDDD = a:x
6295 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6297 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6299 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6301 emitcode ("anl", "a,#0x%02x",
6302 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6304 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6306 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6308 emitcode ("anl", "a,#0x%02x",
6309 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6311 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6313 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6315 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6318 case 6: // AABBBBBB:CCDDDDDD
6320 emitcode ("mov", "c,acc.7");
6321 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6323 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6325 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6327 emitcode ("anl", "a,#0x%02x",
6328 SRMask[shCount]); // 000000AA:BBBBBBCC
6331 case 7: // ABBBBBBB:CDDDDDDD
6333 emitcode ("mov", "c,acc.7"); // c = A
6335 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6337 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6339 emitcode ("anl", "a,#0x%02x",
6340 SRMask[shCount]); // 0000000A:BBBBBBBC
6351 /*-----------------------------------------------------------------*/
6352 /* AccAXRshS - right shift signed a:x known count (0..7) */
6353 /*-----------------------------------------------------------------*/
6355 AccAXRshS (char *x, int shCount)
6363 emitcode ("mov", "c,acc.7");
6364 AccAXRrl1 (x); // s->a:x
6368 emitcode ("mov", "c,acc.7");
6369 AccAXRrl1 (x); // s->a:x
6371 emitcode ("mov", "c,acc.7");
6372 AccAXRrl1 (x); // s->a:x
6377 case 5: // AAAAABBB:CCCCCDDD = a:x
6379 tlbl = newiTempLabel (NULL);
6380 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6382 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6384 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6386 emitcode ("anl", "a,#0x%02x",
6387 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6389 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6391 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6393 emitcode ("anl", "a,#0x%02x",
6394 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6396 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6398 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6400 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6402 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6403 emitcode ("orl", "a,#0x%02x",
6404 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6406 emitcode ("", "%05d$:", tlbl->key + 100);
6407 break; // SSSSAAAA:BBBCCCCC
6409 case 6: // AABBBBBB:CCDDDDDD
6411 tlbl = newiTempLabel (NULL);
6412 emitcode ("mov", "c,acc.7");
6413 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6415 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6417 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6419 emitcode ("anl", "a,#0x%02x",
6420 SRMask[shCount]); // 000000AA:BBBBBBCC
6422 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6423 emitcode ("orl", "a,#0x%02x",
6424 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6426 emitcode ("", "%05d$:", tlbl->key + 100);
6428 case 7: // ABBBBBBB:CDDDDDDD
6430 tlbl = newiTempLabel (NULL);
6431 emitcode ("mov", "c,acc.7"); // c = A
6433 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6435 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6437 emitcode ("anl", "a,#0x%02x",
6438 SRMask[shCount]); // 0000000A:BBBBBBBC
6440 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6441 emitcode ("orl", "a,#0x%02x",
6442 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6444 emitcode ("", "%05d$:", tlbl->key + 100);
6454 /*-----------------------------------------------------------------*/
6455 /* shiftL2Left2Result - shift left two bytes from left to result */
6456 /*-----------------------------------------------------------------*/
6458 shiftL2Left2Result (operand * left, int offl,
6459 operand * result, int offr, int shCount)
6461 if (sameRegs (AOP (result), AOP (left)) &&
6462 ((offl + MSB16) == offr))
6464 /* don't crash result[offr] */
6465 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6466 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6470 movLeft2Result (left, offl, result, offr, 0);
6471 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6473 /* ax << shCount (x = lsb(result)) */
6474 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6475 aopPut (AOP (result), "a", offr + MSB16);
6481 /*-----------------------------------------------------------------*/
6482 /* shiftR2Left2Result - shift right two bytes from left to result */
6483 /*-----------------------------------------------------------------*/
6485 shiftR2Left2Result (operand * left, int offl,
6486 operand * result, int offr,
6487 int shCount, int sign)
6489 if (sameRegs (AOP (result), AOP (left)) &&
6490 ((offl + MSB16) == offr))
6492 /* don't crash result[offr] */
6493 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6494 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6498 movLeft2Result (left, offl, result, offr, 0);
6499 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6501 /* a:x >> shCount (x = lsb(result)) */
6503 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6505 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6506 if (getDataSize (result) > 1)
6507 aopPut (AOP (result), "a", offr + MSB16);
6513 /*-----------------------------------------------------------------*/
6514 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6515 /*-----------------------------------------------------------------*/
6517 shiftLLeftOrResult (operand * left, int offl,
6518 operand * result, int offr, int shCount)
6520 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6521 /* shift left accumulator */
6523 /* or with result */
6524 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6525 /* back to result */
6526 aopPut (AOP (result), "a", offr);
6532 /*-----------------------------------------------------------------*/
6533 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6534 /*-----------------------------------------------------------------*/
6536 shiftRLeftOrResult (operand * left, int offl,
6537 operand * result, int offr, int shCount)
6539 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6540 /* shift right accumulator */
6542 /* or with result */
6543 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6544 /* back to result */
6545 aopPut (AOP (result), "a", offr);
6551 /*-----------------------------------------------------------------*/
6552 /* genlshOne - left shift a one byte quantity by known count */
6553 /*-----------------------------------------------------------------*/
6555 genlshOne (operand * result, operand * left, int shCount)
6557 D (emitcode (";", "genlshOne ");
6559 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6565 /*-----------------------------------------------------------------*/
6566 /* genlshTwo - left shift two bytes by known amount != 0 */
6567 /*-----------------------------------------------------------------*/
6569 genlshTwo (operand * result, operand * left, int shCount)
6573 D (emitcode (";", "genlshTwo ");
6576 size = getDataSize (result);
6578 /* if shCount >= 8 */
6586 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6588 movLeft2Result (left, LSB, result, MSB16, 0);
6590 aopPut (AOP (result), zero, LSB);
6593 /* 1 <= shCount <= 7 */
6597 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6599 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6606 /*-----------------------------------------------------------------*/
6607 /* shiftLLong - shift left one long from left to result */
6608 /* offl = LSB or MSB16 */
6609 /*-----------------------------------------------------------------*/
6611 shiftLLong (operand * left, operand * result, int offr)
6614 int size = AOP_SIZE (result);
6616 if (size >= LSB + offr)
6618 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6620 emitcode ("add", "a,acc");
6621 if (sameRegs (AOP (left), AOP (result)) &&
6622 size >= MSB16 + offr && offr != LSB)
6623 emitcode ("xch", "a,%s",
6624 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6626 aopPut (AOP (result), "a", LSB + offr);
6629 if (size >= MSB16 + offr)
6631 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6633 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6636 emitcode ("rlc", "a");
6637 if (sameRegs (AOP (left), AOP (result)) &&
6638 size >= MSB24 + offr && offr != LSB)
6639 emitcode ("xch", "a,%s",
6640 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6642 aopPut (AOP (result), "a", MSB16 + offr);
6645 if (size >= MSB24 + offr)
6647 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6649 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6652 emitcode ("rlc", "a");
6653 if (sameRegs (AOP (left), AOP (result)) &&
6654 size >= MSB32 + offr && offr != LSB)
6655 emitcode ("xch", "a,%s",
6656 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6658 aopPut (AOP (result), "a", MSB24 + offr);
6661 if (size > MSB32 + offr)
6663 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6665 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6668 emitcode ("rlc", "a");
6669 aopPut (AOP (result), "a", MSB32 + offr);
6672 aopPut (AOP (result), zero, LSB);
6678 /*-----------------------------------------------------------------*/
6679 /* genlshFour - shift four byte by a known amount != 0 */
6680 /*-----------------------------------------------------------------*/
6682 genlshFour (operand * result, operand * left, int shCount)
6686 D (emitcode (";", "genlshFour ");
6689 size = AOP_SIZE (result);
6691 /* if shifting more that 3 bytes */
6696 /* lowest order of left goes to the highest
6697 order of the destination */
6698 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6700 movLeft2Result (left, LSB, result, MSB32, 0);
6701 aopPut (AOP (result), zero, LSB);
6702 aopPut (AOP (result), zero, MSB16);
6703 aopPut (AOP (result), zero, MSB24);
6707 /* more than two bytes */
6708 else if (shCount >= 16)
6710 /* lower order two bytes goes to higher order two bytes */
6712 /* if some more remaining */
6714 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6717 movLeft2Result (left, MSB16, result, MSB32, 0);
6718 movLeft2Result (left, LSB, result, MSB24, 0);
6720 aopPut (AOP (result), zero, MSB16);
6721 aopPut (AOP (result), zero, LSB);
6725 /* if more than 1 byte */
6726 else if (shCount >= 8)
6728 /* lower order three bytes goes to higher order three bytes */
6733 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6735 movLeft2Result (left, LSB, result, MSB16, 0);
6741 movLeft2Result (left, MSB24, result, MSB32, 0);
6742 movLeft2Result (left, MSB16, result, MSB24, 0);
6743 movLeft2Result (left, LSB, result, MSB16, 0);
6744 aopPut (AOP (result), zero, LSB);
6746 else if (shCount == 1)
6747 shiftLLong (left, result, MSB16);
6750 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6751 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6752 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6753 aopPut (AOP (result), zero, LSB);
6758 /* 1 <= shCount <= 7 */
6759 else if (shCount <= 2)
6761 shiftLLong (left, result, LSB);
6763 shiftLLong (result, result, LSB);
6765 /* 3 <= shCount <= 7, optimize */
6768 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6769 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6770 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6777 /*-----------------------------------------------------------------*/
6778 /* genLeftShiftLiteral - left shifting by known count */
6779 /*-----------------------------------------------------------------*/
6781 genLeftShiftLiteral (operand * left,
6786 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6789 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6792 freeAsmop (right, NULL, ic, TRUE);
6794 aopOp (left, ic, FALSE, FALSE);
6795 aopOp (result, ic, FALSE, TRUE);
6797 size = getSize (operandType (result));
6800 emitcode ("; shift left ", "result %d, left %d", size,
6804 /* I suppose that the left size >= result size */
6809 movLeft2Result (left, size, result, size, 0);
6813 else if (shCount >= (size * 8))
6815 aopPut (AOP (result), zero, size);
6821 genlshOne (result, left, shCount);
6825 case 3: /* bug: this is for generic pointers, I bet. */
6826 genlshTwo (result, left, shCount);
6830 genlshFour (result, left, shCount);
6834 freeAsmop (left, NULL, ic, TRUE);
6835 freeAsmop (result, NULL, ic, TRUE);
6839 /*-----------------------------------------------------------------*/
6840 /* genLeftShift - generates code for left shifting */
6841 /*-----------------------------------------------------------------*/
6843 genLeftShift (iCode * ic)
6845 operand *left, *right, *result;
6848 symbol *tlbl, *tlbl1;
6850 D (emitcode (";", "genLeftShift "););
6852 right = IC_RIGHT (ic);
6853 left = IC_LEFT (ic);
6854 result = IC_RESULT (ic);
6856 aopOp (right, ic, FALSE, FALSE);
6859 /* if the shift count is known then do it
6860 as efficiently as possible */
6861 if (AOP_TYPE (right) == AOP_LIT)
6863 genLeftShiftLiteral (left, right, result, ic);
6868 /* shift count is unknown then we have to form
6869 a loop get the loop count in B : Note: we take
6870 only the lower order byte since shifting
6871 more that 32 bits make no sense anyway, ( the
6872 largest size of an object can be only 32 bits ) */
6874 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6875 emitcode ("inc", "b");
6876 freeAsmop (right, NULL, ic, TRUE);
6877 aopOp (left, ic, FALSE, FALSE);
6878 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6880 /* now move the left to the result if they are not the
6882 if (!sameRegs (AOP (left), AOP (result)) &&
6883 AOP_SIZE (result) > 1)
6886 size = AOP_SIZE (result);
6888 _startLazyDPSEvaluation ();
6891 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6892 if (*l == '@' && (IS_AOP_PREG (result)))
6895 emitcode ("mov", "a,%s", l);
6896 aopPut (AOP (result), "a", offset);
6899 aopPut (AOP (result), l, offset);
6902 _endLazyDPSEvaluation ();
6905 tlbl = newiTempLabel (NULL);
6906 size = AOP_SIZE (result);
6908 tlbl1 = newiTempLabel (NULL);
6910 /* if it is only one byte then */
6913 symbol *tlbl1 = newiTempLabel (NULL);
6915 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6917 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6918 emitcode ("", "%05d$:", tlbl->key + 100);
6919 emitcode ("add", "a,acc");
6920 emitcode ("", "%05d$:", tlbl1->key + 100);
6921 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6922 aopPut (AOP (result), "a", 0);
6926 reAdjustPreg (AOP (result));
6928 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6929 emitcode ("", "%05d$:", tlbl->key + 100);
6930 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6932 emitcode ("add", "a,acc");
6933 aopPut (AOP (result), "a", offset++);
6934 _startLazyDPSEvaluation ();
6937 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6939 emitcode ("rlc", "a");
6940 aopPut (AOP (result), "a", offset++);
6942 _endLazyDPSEvaluation ();
6943 reAdjustPreg (AOP (result));
6945 emitcode ("", "%05d$:", tlbl1->key + 100);
6946 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6948 freeAsmop (left, NULL, ic, TRUE);
6949 freeAsmop (result, NULL, ic, TRUE);
6954 /*-----------------------------------------------------------------*/
6955 /* genrshOne - right shift a one byte quantity by known count */
6956 /*-----------------------------------------------------------------*/
6958 genrshOne (operand * result, operand * left,
6959 int shCount, int sign)
6961 D (emitcode (";", "genrshOne");
6963 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6969 /*-----------------------------------------------------------------*/
6970 /* genrshTwo - right shift two bytes by known amount != 0 */
6971 /*-----------------------------------------------------------------*/
6973 genrshTwo (operand * result, operand * left,
6974 int shCount, int sign)
6976 D (emitcode (";", "genrshTwo");
6979 /* if shCount >= 8 */
6984 shiftR1Left2Result (left, MSB16, result, LSB,
6987 movLeft2Result (left, MSB16, result, LSB, sign);
6988 addSign (result, MSB16, sign);
6991 /* 1 <= shCount <= 7 */
6993 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6999 /*-----------------------------------------------------------------*/
7000 /* shiftRLong - shift right one long from left to result */
7001 /* offl = LSB or MSB16 */
7002 /*-----------------------------------------------------------------*/
7004 shiftRLong (operand * left, int offl,
7005 operand * result, int sign)
7008 emitcode ("clr", "c");
7009 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7011 emitcode ("mov", "c,acc.7");
7012 emitcode ("rrc", "a");
7013 aopPut (AOP (result), "a", MSB32 - offl);
7015 /* add sign of "a" */
7016 addSign (result, MSB32, sign);
7018 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7019 emitcode ("rrc", "a");
7020 aopPut (AOP (result), "a", MSB24 - offl);
7022 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7023 emitcode ("rrc", "a");
7024 aopPut (AOP (result), "a", MSB16 - offl);
7028 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7029 emitcode ("rrc", "a");
7030 aopPut (AOP (result), "a", LSB);
7037 /*-----------------------------------------------------------------*/
7038 /* genrshFour - shift four byte by a known amount != 0 */
7039 /*-----------------------------------------------------------------*/
7041 genrshFour (operand * result, operand * left,
7042 int shCount, int sign)
7044 D (emitcode (";", "genrshFour");
7047 /* if shifting more that 3 bytes */
7052 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7054 movLeft2Result (left, MSB32, result, LSB, sign);
7055 addSign (result, MSB16, sign);
7057 else if (shCount >= 16)
7061 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7064 movLeft2Result (left, MSB24, result, LSB, 0);
7065 movLeft2Result (left, MSB32, result, MSB16, sign);
7067 addSign (result, MSB24, sign);
7069 else if (shCount >= 8)
7073 shiftRLong (left, MSB16, result, sign);
7074 else if (shCount == 0)
7076 movLeft2Result (left, MSB16, result, LSB, 0);
7077 movLeft2Result (left, MSB24, result, MSB16, 0);
7078 movLeft2Result (left, MSB32, result, MSB24, sign);
7079 addSign (result, MSB32, sign);
7083 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7084 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7085 /* the last shift is signed */
7086 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7087 addSign (result, MSB32, sign);
7091 { /* 1 <= shCount <= 7 */
7094 shiftRLong (left, LSB, result, sign);
7096 shiftRLong (result, LSB, result, sign);
7100 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7101 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7102 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7110 /*-----------------------------------------------------------------*/
7111 /* genRightShiftLiteral - right shifting by known count */
7112 /*-----------------------------------------------------------------*/
7114 genRightShiftLiteral (operand * left,
7120 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7123 D (emitcode (";", "genRightShiftLiteral");
7126 freeAsmop (right, NULL, ic, TRUE);
7128 aopOp (left, ic, FALSE, FALSE);
7129 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7132 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7136 size = getDataSize (left);
7137 /* test the LEFT size !!! */
7139 /* I suppose that the left size >= result size */
7142 size = getDataSize (result);
7144 movLeft2Result (left, size, result, size, 0);
7147 else if (shCount >= (size * 8))
7150 /* get sign in acc.7 */
7151 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7152 addSign (result, LSB, sign);
7159 genrshOne (result, left, shCount, sign);
7163 genrshTwo (result, left, shCount, sign);
7167 genrshFour (result, left, shCount, sign);
7173 freeAsmop (left, NULL, ic, TRUE);
7174 freeAsmop (result, NULL, ic, TRUE);
7179 /*-----------------------------------------------------------------*/
7180 /* genSignedRightShift - right shift of signed number */
7181 /*-----------------------------------------------------------------*/
7183 genSignedRightShift (iCode * ic)
7185 operand *right, *left, *result;
7188 symbol *tlbl, *tlbl1;
7190 D (emitcode (";", "genSignedRightShift ");
7193 /* we do it the hard way put the shift count in b
7194 and loop thru preserving the sign */
7196 right = IC_RIGHT (ic);
7197 left = IC_LEFT (ic);
7198 result = IC_RESULT (ic);
7200 aopOp (right, ic, FALSE, FALSE);
7203 if (AOP_TYPE (right) == AOP_LIT)
7205 genRightShiftLiteral (left, right, result, ic, 1);
7209 /* shift count is unknown then we have to form
7210 a loop get the loop count in B : Note: we take
7211 only the lower order byte since shifting
7212 more that 32 bits make no sense anyway, ( the
7213 largest size of an object can be only 32 bits ) */
7215 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7216 emitcode ("inc", "b");
7217 freeAsmop (right, NULL, ic, TRUE);
7218 aopOp (left, ic, FALSE, FALSE);
7219 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7221 /* now move the left to the result if they are not the
7223 if (!sameRegs (AOP (left), AOP (result)) &&
7224 AOP_SIZE (result) > 1)
7227 size = AOP_SIZE (result);
7229 _startLazyDPSEvaluation ();
7232 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7233 if (*l == '@' && IS_AOP_PREG (result))
7236 emitcode ("mov", "a,%s", l);
7237 aopPut (AOP (result), "a", offset);
7240 aopPut (AOP (result), l, offset);
7243 _endLazyDPSEvaluation ();
7246 /* mov the highest order bit to OVR */
7247 tlbl = newiTempLabel (NULL);
7248 tlbl1 = newiTempLabel (NULL);
7250 size = AOP_SIZE (result);
7252 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7253 emitcode ("rlc", "a");
7254 emitcode ("mov", "ov,c");
7255 /* if it is only one byte then */
7258 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7260 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7261 emitcode ("", "%05d$:", tlbl->key + 100);
7262 emitcode ("mov", "c,ov");
7263 emitcode ("rrc", "a");
7264 emitcode ("", "%05d$:", tlbl1->key + 100);
7265 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7266 aopPut (AOP (result), "a", 0);
7270 reAdjustPreg (AOP (result));
7271 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7272 emitcode ("", "%05d$:", tlbl->key + 100);
7273 emitcode ("mov", "c,ov");
7274 _startLazyDPSEvaluation ();
7277 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7279 emitcode ("rrc", "a");
7280 aopPut (AOP (result), "a", offset--);
7282 _endLazyDPSEvaluation ();
7283 reAdjustPreg (AOP (result));
7284 emitcode ("", "%05d$:", tlbl1->key + 100);
7285 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7288 freeAsmop (left, NULL, ic, TRUE);
7289 freeAsmop (result, NULL, ic, TRUE);
7292 /*-----------------------------------------------------------------*/
7293 /* genRightShift - generate code for right shifting */
7294 /*-----------------------------------------------------------------*/
7296 genRightShift (iCode * ic)
7298 operand *right, *left, *result;
7302 symbol *tlbl, *tlbl1;
7304 D (emitcode (";", "genRightShift ");
7307 /* if signed then we do it the hard way preserve the
7308 sign bit moving it inwards */
7309 retype = getSpec (operandType (IC_RESULT (ic)));
7311 if (!SPEC_USIGN (retype))
7313 genSignedRightShift (ic);
7317 /* signed & unsigned types are treated the same : i.e. the
7318 signed is NOT propagated inwards : quoting from the
7319 ANSI - standard : "for E1 >> E2, is equivalent to division
7320 by 2**E2 if unsigned or if it has a non-negative value,
7321 otherwise the result is implementation defined ", MY definition
7322 is that the sign does not get propagated */
7324 right = IC_RIGHT (ic);
7325 left = IC_LEFT (ic);
7326 result = IC_RESULT (ic);
7328 aopOp (right, ic, FALSE, FALSE);
7331 /* if the shift count is known then do it
7332 as efficiently as possible */
7333 if (AOP_TYPE (right) == AOP_LIT)
7335 genRightShiftLiteral (left, right, result, ic, 0);
7340 /* shift count is unknown then we have to form
7341 a loop get the loop count in B : Note: we take
7342 only the lower order byte since shifting
7343 more that 32 bits make no sense anyway, ( the
7344 largest size of an object can be only 32 bits ) */
7346 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7347 emitcode ("inc", "b");
7348 freeAsmop (right, NULL, ic, TRUE);
7349 aopOp (left, ic, FALSE, FALSE);
7350 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7352 /* now move the left to the result if they are not the
7354 if (!sameRegs (AOP (left), AOP (result)) &&
7355 AOP_SIZE (result) > 1)
7358 size = AOP_SIZE (result);
7360 _startLazyDPSEvaluation ();
7363 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7364 if (*l == '@' && IS_AOP_PREG (result))
7367 emitcode ("mov", "a,%s", l);
7368 aopPut (AOP (result), "a", offset);
7371 aopPut (AOP (result), l, offset);
7374 _endLazyDPSEvaluation ();
7377 tlbl = newiTempLabel (NULL);
7378 tlbl1 = newiTempLabel (NULL);
7379 size = AOP_SIZE (result);
7382 /* if it is only one byte then */
7385 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7387 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7388 emitcode ("", "%05d$:", tlbl->key + 100);
7390 emitcode ("rrc", "a");
7391 emitcode ("", "%05d$:", tlbl1->key + 100);
7392 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7393 aopPut (AOP (result), "a", 0);
7397 reAdjustPreg (AOP (result));
7398 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7399 emitcode ("", "%05d$:", tlbl->key + 100);
7401 _startLazyDPSEvaluation ();
7404 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7406 emitcode ("rrc", "a");
7407 aopPut (AOP (result), "a", offset--);
7409 _endLazyDPSEvaluation ();
7410 reAdjustPreg (AOP (result));
7412 emitcode ("", "%05d$:", tlbl1->key + 100);
7413 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7416 freeAsmop (left, NULL, ic, TRUE);
7417 freeAsmop (result, NULL, ic, TRUE);
7420 /*-----------------------------------------------------------------*/
7421 /* genUnpackBits - generates code for unpacking bits */
7422 /*-----------------------------------------------------------------*/
7424 genUnpackBits (operand * result, char *rname, int ptype)
7431 D (emitcode (";", "genUnpackBits ");
7434 etype = getSpec (operandType (result));
7436 /* read the first byte */
7442 emitcode ("mov", "a,@%s", rname);
7446 emitcode ("movx", "a,@%s", rname);
7450 emitcode ("movx", "a,@dptr");
7454 emitcode ("clr", "a");
7455 emitcode ("movc", "a", "@a+dptr");
7459 emitcode ("lcall", "__gptrget");
7463 /* if we have bitdisplacement then it fits */
7464 /* into this byte completely or if length is */
7465 /* less than a byte */
7466 if ((shCnt = SPEC_BSTR (etype)) ||
7467 (SPEC_BLEN (etype) <= 8))
7470 /* shift right acc */
7473 emitcode ("anl", "a,#0x%02x",
7474 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7475 aopPut (AOP (result), "a", offset);
7479 /* bit field did not fit in a byte */
7480 rlen = SPEC_BLEN (etype) - 8;
7481 aopPut (AOP (result), "a", offset++);
7490 emitcode ("inc", "%s", rname);
7491 emitcode ("mov", "a,@%s", rname);
7495 emitcode ("inc", "%s", rname);
7496 emitcode ("movx", "a,@%s", rname);
7500 emitcode ("inc", "dptr");
7501 emitcode ("movx", "a,@dptr");
7505 emitcode ("clr", "a");
7506 emitcode ("inc", "dptr");
7507 emitcode ("movc", "a", "@a+dptr");
7511 emitcode ("inc", "dptr");
7512 emitcode ("lcall", "__gptrget");
7517 /* if we are done */
7521 aopPut (AOP (result), "a", offset++);
7527 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7528 aopPut (AOP (result), "a", offset);
7535 /*-----------------------------------------------------------------*/
7536 /* genDataPointerGet - generates code when ptr offset is known */
7537 /*-----------------------------------------------------------------*/
7539 genDataPointerGet (operand * left,
7545 int size, offset = 0;
7546 aopOp (result, ic, TRUE, FALSE);
7548 /* get the string representation of the name */
7549 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7550 size = AOP_SIZE (result);
7551 _startLazyDPSEvaluation ();
7555 sprintf (buffer, "(%s + %d)", l + 1, offset);
7557 sprintf (buffer, "%s", l + 1);
7558 aopPut (AOP (result), buffer, offset++);
7560 _endLazyDPSEvaluation ();
7562 freeAsmop (left, NULL, ic, TRUE);
7563 freeAsmop (result, NULL, ic, TRUE);
7566 /*-----------------------------------------------------------------*/
7567 /* genNearPointerGet - emitcode for near pointer fetch */
7568 /*-----------------------------------------------------------------*/
7570 genNearPointerGet (operand * left,
7577 sym_link *rtype, *retype, *letype;
7578 sym_link *ltype = operandType (left);
7581 rtype = operandType (result);
7582 retype = getSpec (rtype);
7583 letype = getSpec (ltype);
7585 aopOp (left, ic, FALSE, FALSE);
7587 /* if left is rematerialisable and
7588 result is not bit variable type and
7589 the left is pointer to data space i.e
7590 lower 128 bytes of space */
7591 if (AOP_TYPE (left) == AOP_IMMD &&
7592 !IS_BITVAR (retype) &&
7593 !IS_BITVAR (letype) &&
7594 DCL_TYPE (ltype) == POINTER)
7596 genDataPointerGet (left, result, ic);
7600 /* if the value is already in a pointer register
7601 then don't need anything more */
7602 if (!AOP_INPREG (AOP (left)))
7604 /* otherwise get a free pointer register */
7606 preg = getFreePtr (ic, &aop, FALSE);
7607 emitcode ("mov", "%s,%s",
7609 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7613 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7615 freeAsmop (left, NULL, ic, TRUE);
7616 aopOp (result, ic, FALSE, FALSE);
7618 /* if bitfield then unpack the bits */
7619 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7620 genUnpackBits (result, rname, POINTER);
7623 /* we have can just get the values */
7624 int size = AOP_SIZE (result);
7629 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7632 emitcode ("mov", "a,@%s", rname);
7633 aopPut (AOP (result), "a", offset);
7637 sprintf (buffer, "@%s", rname);
7638 aopPut (AOP (result), buffer, offset);
7642 emitcode ("inc", "%s", rname);
7646 /* now some housekeeping stuff */
7649 /* we had to allocate for this iCode */
7650 freeAsmop (NULL, aop, ic, TRUE);
7654 /* we did not allocate which means left
7655 already in a pointer register, then
7656 if size > 0 && this could be used again
7657 we have to point it back to where it
7659 if (AOP_SIZE (result) > 1 &&
7660 !OP_SYMBOL (left)->remat &&
7661 (OP_SYMBOL (left)->liveTo > ic->seq ||
7664 int size = AOP_SIZE (result) - 1;
7666 emitcode ("dec", "%s", rname);
7671 freeAsmop (result, NULL, ic, TRUE);
7675 /*-----------------------------------------------------------------*/
7676 /* genPagedPointerGet - emitcode for paged pointer fetch */
7677 /*-----------------------------------------------------------------*/
7679 genPagedPointerGet (operand * left,
7686 sym_link *rtype, *retype, *letype;
7688 rtype = operandType (result);
7689 retype = getSpec (rtype);
7690 letype = getSpec (operandType (left));
7691 aopOp (left, ic, FALSE, FALSE);
7693 /* if the value is already in a pointer register
7694 then don't need anything more */
7695 if (!AOP_INPREG (AOP (left)))
7697 /* otherwise get a free pointer register */
7699 preg = getFreePtr (ic, &aop, FALSE);
7700 emitcode ("mov", "%s,%s",
7702 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7706 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7708 freeAsmop (left, NULL, ic, TRUE);
7709 aopOp (result, ic, FALSE, FALSE);
7711 /* if bitfield then unpack the bits */
7712 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7713 genUnpackBits (result, rname, PPOINTER);
7716 /* we have can just get the values */
7717 int size = AOP_SIZE (result);
7723 emitcode ("movx", "a,@%s", rname);
7724 aopPut (AOP (result), "a", offset);
7729 emitcode ("inc", "%s", rname);
7733 /* now some housekeeping stuff */
7736 /* we had to allocate for this iCode */
7737 freeAsmop (NULL, aop, ic, TRUE);
7741 /* we did not allocate which means left
7742 already in a pointer register, then
7743 if size > 0 && this could be used again
7744 we have to point it back to where it
7746 if (AOP_SIZE (result) > 1 &&
7747 !OP_SYMBOL (left)->remat &&
7748 (OP_SYMBOL (left)->liveTo > ic->seq ||
7751 int size = AOP_SIZE (result) - 1;
7753 emitcode ("dec", "%s", rname);
7758 freeAsmop (result, NULL, ic, TRUE);
7763 /*-----------------------------------------------------------------*/
7764 /* genFarPointerGet - gget value from far space */
7765 /*-----------------------------------------------------------------*/
7767 genFarPointerGet (operand * left,
7768 operand * result, iCode * ic)
7771 sym_link *retype = getSpec (operandType (result));
7772 sym_link *letype = getSpec (operandType (left));
7773 D (emitcode (";", "genFarPointerGet");
7776 aopOp (left, ic, FALSE, FALSE);
7778 /* if the operand is already in dptr
7779 then we do nothing else we move the value to dptr */
7780 if (AOP_TYPE (left) != AOP_STR)
7782 /* if this is remateriazable */
7783 if (AOP_TYPE (left) == AOP_IMMD)
7785 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7789 /* we need to get it byte by byte */
7790 _startLazyDPSEvaluation ();
7791 if (AOP_TYPE (left) != AOP_DPTR)
7793 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7794 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7795 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7799 /* We need to generate a load to DPTR indirect through DPTR. */
7800 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7802 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7803 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7804 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7805 emitcode ("pop", "dph");
7806 emitcode ("pop", "dpl");
7808 _endLazyDPSEvaluation ();
7811 /* so dptr know contains the address */
7812 freeAsmop (left, NULL, ic, TRUE);
7813 aopOp (result, ic, FALSE, TRUE);
7815 /* if bit then unpack */
7816 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7817 genUnpackBits (result, "dptr", FPOINTER);
7820 size = AOP_SIZE (result);
7823 _startLazyDPSEvaluation ();
7830 emitcode ("movx", "a,@dptr");
7832 emitcode ("inc", "dptr");
7834 aopPut (AOP (result), "a", offset++);
7836 _endLazyDPSEvaluation ();
7839 freeAsmop (result, NULL, ic, TRUE);
7842 /*-----------------------------------------------------------------*/
7843 /* emitcodePointerGet - gget value from code space */
7844 /*-----------------------------------------------------------------*/
7846 emitcodePointerGet (operand * left,
7847 operand * result, iCode * ic)
7850 sym_link *retype = getSpec (operandType (result));
7852 aopOp (left, ic, FALSE, FALSE);
7854 /* if the operand is already in dptr
7855 then we do nothing else we move the value to dptr */
7856 if (AOP_TYPE (left) != AOP_STR)
7858 /* if this is remateriazable */
7859 if (AOP_TYPE (left) == AOP_IMMD)
7861 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7864 { /* we need to get it byte by byte */
7865 _startLazyDPSEvaluation ();
7866 if (AOP_TYPE (left) != AOP_DPTR)
7868 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7869 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7870 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7874 /* We need to generate a load to DPTR indirect through DPTR. */
7875 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7877 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7878 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7879 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7880 emitcode ("pop", "dph");
7881 emitcode ("pop", "dpl");
7883 _endLazyDPSEvaluation ();
7886 /* so dptr know contains the address */
7887 freeAsmop (left, NULL, ic, TRUE);
7888 aopOp (result, ic, FALSE, TRUE);
7890 /* if bit then unpack */
7891 if (IS_BITVAR (retype))
7892 genUnpackBits (result, "dptr", CPOINTER);
7895 size = AOP_SIZE (result);
7898 _startLazyDPSEvaluation ();
7904 emitcode ("clr", "a");
7905 emitcode ("movc", "a,@a+dptr");
7907 emitcode ("inc", "dptr");
7908 aopPut (AOP (result), "a", offset++);
7910 _endLazyDPSEvaluation ();
7913 freeAsmop (result, NULL, ic, TRUE);
7916 /*-----------------------------------------------------------------*/
7917 /* genGenPointerGet - gget value from generic pointer space */
7918 /*-----------------------------------------------------------------*/
7920 genGenPointerGet (operand * left,
7921 operand * result, iCode * ic)
7924 sym_link *retype = getSpec (operandType (result));
7925 sym_link *letype = getSpec (operandType (left));
7927 D (emitcode (";", "genGenPointerGet "); );
7929 aopOp (left, ic, FALSE, TRUE);
7931 /* if the operand is already in dptr
7932 then we do nothing else we move the value to dptr */
7933 if (AOP_TYPE (left) != AOP_STR)
7935 /* if this is remateriazable */
7936 if (AOP_TYPE (left) == AOP_IMMD)
7938 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7939 emitcode ("mov", "b,#%d", pointerCode (retype));
7942 { /* we need to get it byte by byte */
7943 _startLazyDPSEvaluation ();
7944 if (AOP(left)->type==AOP_DPTR2) {
7946 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7949 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7950 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7953 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7954 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7957 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7958 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7960 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7961 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7962 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7963 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7965 _endLazyDPSEvaluation ();
7968 /* so dptr know contains the address */
7969 freeAsmop (left, NULL, ic, TRUE);
7970 aopOp (result, ic, FALSE, TRUE);
7972 /* if bit then unpack */
7973 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7974 genUnpackBits (result, "dptr", GPOINTER);
7977 size = AOP_SIZE (result);
7982 emitcode ("lcall", "__gptrget");
7983 aopPut (AOP (result), "a", offset++);
7985 emitcode ("inc", "dptr");
7989 freeAsmop (result, NULL, ic, TRUE);
7992 /*-----------------------------------------------------------------*/
7993 /* genPointerGet - generate code for pointer get */
7994 /*-----------------------------------------------------------------*/
7996 genPointerGet (iCode * ic)
7998 operand *left, *result;
7999 sym_link *type, *etype;
8002 D (emitcode (";", "genPointerGet ");
8005 left = IC_LEFT (ic);
8006 result = IC_RESULT (ic);
8008 /* depending on the type of pointer we need to
8009 move it to the correct pointer register */
8010 type = operandType (left);
8011 etype = getSpec (type);
8012 /* if left is of type of pointer then it is simple */
8013 if (IS_PTR (type) && !IS_FUNC (type->next))
8014 p_type = DCL_TYPE (type);
8017 /* we have to go by the storage class */
8018 p_type = PTR_TYPE (SPEC_OCLS (etype));
8021 /* now that we have the pointer type we assign
8022 the pointer values */
8028 genNearPointerGet (left, result, ic);
8032 genPagedPointerGet (left, result, ic);
8036 genFarPointerGet (left, result, ic);
8040 emitcodePointerGet (left, result, ic);
8044 genGenPointerGet (left, result, ic);
8050 /*-----------------------------------------------------------------*/
8051 /* genPackBits - generates code for packed bit storage */
8052 /*-----------------------------------------------------------------*/
8054 genPackBits (sym_link * etype,
8056 char *rname, int p_type)
8064 blen = SPEC_BLEN (etype);
8065 bstr = SPEC_BSTR (etype);
8067 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8070 /* if the bit lenth is less than or */
8071 /* it exactly fits a byte then */
8072 if (SPEC_BLEN (etype) <= 8)
8074 shCount = SPEC_BSTR (etype);
8076 /* shift left acc */
8079 if (SPEC_BLEN (etype) < 8)
8080 { /* if smaller than a byte */
8086 emitcode ("mov", "b,a");
8087 emitcode ("mov", "a,@%s", rname);
8091 emitcode ("mov", "b,a");
8092 emitcode ("movx", "a,@dptr");
8096 emitcode ("push", "b");
8097 emitcode ("push", "acc");
8098 emitcode ("lcall", "__gptrget");
8099 emitcode ("pop", "b");
8103 emitcode ("anl", "a,#0x%02x", (unsigned char)
8104 ((unsigned char) (0xFF << (blen + bstr)) |
8105 (unsigned char) (0xFF >> (8 - bstr))));
8106 emitcode ("orl", "a,b");
8107 if (p_type == GPOINTER)
8108 emitcode ("pop", "b");
8115 emitcode ("mov", "@%s,a", rname);
8119 emitcode ("movx", "@dptr,a");
8123 emitcode ("lcall", "__gptrput");
8128 if (SPEC_BLEN (etype) <= 8)
8131 emitcode ("inc", "%s", rname);
8132 rLen = SPEC_BLEN (etype);
8134 /* now generate for lengths greater than one byte */
8138 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8150 emitcode ("mov", "@%s,a", rname);
8153 emitcode ("mov", "@%s,%s", rname, l);
8158 emitcode ("movx", "@dptr,a");
8163 emitcode ("lcall", "__gptrput");
8166 emitcode ("inc", "%s", rname);
8171 /* last last was not complete */
8174 /* save the byte & read byte */
8178 emitcode ("mov", "b,a");
8179 emitcode ("mov", "a,@%s", rname);
8183 emitcode ("mov", "b,a");
8184 emitcode ("movx", "a,@dptr");
8188 emitcode ("push", "b");
8189 emitcode ("push", "acc");
8190 emitcode ("lcall", "__gptrget");
8191 emitcode ("pop", "b");
8195 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8196 emitcode ("orl", "a,b");
8199 if (p_type == GPOINTER)
8200 emitcode ("pop", "b");
8206 emitcode ("mov", "@%s,a", rname);
8210 emitcode ("movx", "@dptr,a");
8214 emitcode ("lcall", "__gptrput");
8218 /*-----------------------------------------------------------------*/
8219 /* genDataPointerSet - remat pointer to data space */
8220 /*-----------------------------------------------------------------*/
8222 genDataPointerSet (operand * right,
8226 int size, offset = 0;
8227 char *l, buffer[256];
8229 aopOp (right, ic, FALSE, FALSE);
8231 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8232 size = AOP_SIZE (right);
8236 sprintf (buffer, "(%s + %d)", l + 1, offset);
8238 sprintf (buffer, "%s", l + 1);
8239 emitcode ("mov", "%s,%s", buffer,
8240 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8243 freeAsmop (right, NULL, ic, TRUE);
8244 freeAsmop (result, NULL, ic, TRUE);
8247 /*-----------------------------------------------------------------*/
8248 /* genNearPointerSet - emitcode for near pointer put */
8249 /*-----------------------------------------------------------------*/
8251 genNearPointerSet (operand * right,
8258 sym_link *retype, *letype;
8259 sym_link *ptype = operandType (result);
8261 retype = getSpec (operandType (right));
8262 letype = getSpec (ptype);
8264 aopOp (result, ic, FALSE, FALSE);
8266 /* if the result is rematerializable &
8267 in data space & not a bit variable */
8268 if (AOP_TYPE (result) == AOP_IMMD &&
8269 DCL_TYPE (ptype) == POINTER &&
8270 !IS_BITVAR (retype) &&
8271 !IS_BITVAR (letype))
8273 genDataPointerSet (right, result, ic);
8277 /* if the value is already in a pointer register
8278 then don't need anything more */
8279 if (!AOP_INPREG (AOP (result)))
8281 /* otherwise get a free pointer register */
8283 preg = getFreePtr (ic, &aop, FALSE);
8284 emitcode ("mov", "%s,%s",
8286 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8290 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8292 freeAsmop (result, NULL, ic, TRUE);
8293 aopOp (right, ic, FALSE, FALSE);
8295 /* if bitfield then unpack the bits */
8296 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8297 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8300 /* we have can just get the values */
8301 int size = AOP_SIZE (right);
8306 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8310 emitcode ("mov", "@%s,a", rname);
8313 emitcode ("mov", "@%s,%s", rname, l);
8315 emitcode ("inc", "%s", rname);
8320 /* now some housekeeping stuff */
8323 /* we had to allocate for this iCode */
8324 freeAsmop (NULL, aop, ic, TRUE);
8328 /* we did not allocate which means left
8329 already in a pointer register, then
8330 if size > 0 && this could be used again
8331 we have to point it back to where it
8333 if (AOP_SIZE (right) > 1 &&
8334 !OP_SYMBOL (result)->remat &&
8335 (OP_SYMBOL (result)->liveTo > ic->seq ||
8338 int size = AOP_SIZE (right) - 1;
8340 emitcode ("dec", "%s", rname);
8345 freeAsmop (right, NULL, ic, TRUE);
8350 /*-----------------------------------------------------------------*/
8351 /* genPagedPointerSet - emitcode for Paged pointer put */
8352 /*-----------------------------------------------------------------*/
8354 genPagedPointerSet (operand * right,
8361 sym_link *retype, *letype;
8363 retype = getSpec (operandType (right));
8364 letype = getSpec (operandType (result));
8366 aopOp (result, ic, FALSE, FALSE);
8368 /* if the value is already in a pointer register
8369 then don't need anything more */
8370 if (!AOP_INPREG (AOP (result)))
8372 /* otherwise get a free pointer register */
8374 preg = getFreePtr (ic, &aop, FALSE);
8375 emitcode ("mov", "%s,%s",
8377 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8381 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8383 freeAsmop (result, NULL, ic, TRUE);
8384 aopOp (right, ic, FALSE, FALSE);
8386 /* if bitfield then unpack the bits */
8387 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8388 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8391 /* we have can just get the values */
8392 int size = AOP_SIZE (right);
8397 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8400 emitcode ("movx", "@%s,a", rname);
8403 emitcode ("inc", "%s", rname);
8409 /* now some housekeeping stuff */
8412 /* we had to allocate for this iCode */
8413 freeAsmop (NULL, aop, ic, TRUE);
8417 /* we did not allocate which means left
8418 already in a pointer register, then
8419 if size > 0 && this could be used again
8420 we have to point it back to where it
8422 if (AOP_SIZE (right) > 1 &&
8423 !OP_SYMBOL (result)->remat &&
8424 (OP_SYMBOL (result)->liveTo > ic->seq ||
8427 int size = AOP_SIZE (right) - 1;
8429 emitcode ("dec", "%s", rname);
8434 freeAsmop (right, NULL, ic, TRUE);
8439 /*-----------------------------------------------------------------*/
8440 /* genFarPointerSet - set value from far space */
8441 /*-----------------------------------------------------------------*/
8443 genFarPointerSet (operand * right,
8444 operand * result, iCode * ic)
8447 sym_link *retype = getSpec (operandType (right));
8448 sym_link *letype = getSpec (operandType (result));
8450 aopOp (result, ic, FALSE, FALSE);
8452 /* if the operand is already in dptr
8453 then we do nothing else we move the value to dptr */
8454 if (AOP_TYPE (result) != AOP_STR)
8456 /* if this is remateriazable */
8457 if (AOP_TYPE (result) == AOP_IMMD)
8458 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8461 /* we need to get it byte by byte */
8462 _startLazyDPSEvaluation ();
8463 if (AOP_TYPE (result) != AOP_DPTR)
8465 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8466 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8467 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8471 /* We need to generate a load to DPTR indirect through DPTR. */
8472 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8474 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8475 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8476 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8477 emitcode ("pop", "dph");
8478 emitcode ("pop", "dpl");
8480 _endLazyDPSEvaluation ();
8483 /* so dptr know contains the address */
8484 freeAsmop (result, NULL, ic, TRUE);
8485 aopOp (right, ic, FALSE, TRUE);
8487 /* if bit then unpack */
8488 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8489 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8492 size = AOP_SIZE (right);
8495 _startLazyDPSEvaluation ();
8498 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8504 emitcode ("movx", "@dptr,a");
8506 emitcode ("inc", "dptr");
8508 _endLazyDPSEvaluation ();
8511 freeAsmop (right, NULL, ic, TRUE);
8514 /*-----------------------------------------------------------------*/
8515 /* genGenPointerSet - set value from generic pointer space */
8516 /*-----------------------------------------------------------------*/
8518 genGenPointerSet (operand * right,
8519 operand * result, iCode * ic)
8522 sym_link *retype = getSpec (operandType (right));
8523 sym_link *letype = getSpec (operandType (result));
8525 aopOp (result, ic, FALSE, TRUE);
8527 /* if the operand is already in dptr
8528 then we do nothing else we move the value to dptr */
8529 if (AOP_TYPE (result) != AOP_STR)
8531 _startLazyDPSEvaluation ();
8532 /* if this is remateriazable */
8533 if (AOP_TYPE (result) == AOP_IMMD)
8535 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8536 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8539 { /* we need to get it byte by byte */
8540 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8541 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8542 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8543 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8545 _endLazyDPSEvaluation ();
8547 /* so dptr know contains the address */
8548 freeAsmop (result, NULL, ic, TRUE);
8549 aopOp (right, ic, FALSE, TRUE);
8551 /* if bit then unpack */
8552 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8553 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8556 size = AOP_SIZE (right);
8559 _startLazyDPSEvaluation ();
8562 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8568 emitcode ("lcall", "__gptrput");
8570 emitcode ("inc", "dptr");
8572 _endLazyDPSEvaluation ();
8575 freeAsmop (right, NULL, ic, TRUE);
8578 /*-----------------------------------------------------------------*/
8579 /* genPointerSet - stores the value into a pointer location */
8580 /*-----------------------------------------------------------------*/
8582 genPointerSet (iCode * ic)
8584 operand *right, *result;
8585 sym_link *type, *etype;
8588 D (emitcode (";", "genPointerSet ");
8591 right = IC_RIGHT (ic);
8592 result = IC_RESULT (ic);
8594 /* depending on the type of pointer we need to
8595 move it to the correct pointer register */
8596 type = operandType (result);
8597 etype = getSpec (type);
8598 /* if left is of type of pointer then it is simple */
8599 if (IS_PTR (type) && !IS_FUNC (type->next))
8601 p_type = DCL_TYPE (type);
8605 /* we have to go by the storage class */
8606 p_type = PTR_TYPE (SPEC_OCLS (etype));
8609 /* now that we have the pointer type we assign
8610 the pointer values */
8616 genNearPointerSet (right, result, ic);
8620 genPagedPointerSet (right, result, ic);
8624 genFarPointerSet (right, result, ic);
8628 genGenPointerSet (right, result, ic);
8634 /*-----------------------------------------------------------------*/
8635 /* genIfx - generate code for Ifx statement */
8636 /*-----------------------------------------------------------------*/
8638 genIfx (iCode * ic, iCode * popIc)
8640 operand *cond = IC_COND (ic);
8643 D (emitcode (";", "genIfx ");
8646 aopOp (cond, ic, FALSE, FALSE);
8648 /* get the value into acc */
8649 if (AOP_TYPE (cond) != AOP_CRY)
8653 /* the result is now in the accumulator */
8654 freeAsmop (cond, NULL, ic, TRUE);
8656 /* if there was something to be popped then do it */
8660 /* if the condition is a bit variable */
8661 if (isbit && IS_ITEMP (cond) &&
8663 genIfxJump (ic, SPIL_LOC (cond)->rname);
8664 else if (isbit && !IS_ITEMP (cond))
8665 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8667 genIfxJump (ic, "a");
8672 /*-----------------------------------------------------------------*/
8673 /* genAddrOf - generates code for address of */
8674 /*-----------------------------------------------------------------*/
8676 genAddrOf (iCode * ic)
8678 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8681 D (emitcode (";", "genAddrOf ");
8684 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8686 /* if the operand is on the stack then we
8687 need to get the stack offset of this
8691 /* if it has an offset then we need to compute
8695 emitcode ("mov", "a,_bp");
8696 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8697 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8701 /* we can just move _bp */
8702 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8704 /* fill the result with zero */
8705 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8708 if (options.stack10bit && size < (FPTRSIZE - 1))
8711 "*** warning: pointer to stack var truncated.\n");
8718 if (options.stack10bit && offset == 2)
8720 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8724 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8731 /* object not on stack then we need the name */
8732 size = AOP_SIZE (IC_RESULT (ic));
8737 char s[SDCC_NAME_MAX];
8739 sprintf (s, "#(%s >> %d)",
8743 sprintf (s, "#%s", sym->rname);
8744 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8748 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8752 /*-----------------------------------------------------------------*/
8753 /* genFarFarAssign - assignment when both are in far space */
8754 /*-----------------------------------------------------------------*/
8756 genFarFarAssign (operand * result, operand * right, iCode * ic)
8758 int size = AOP_SIZE (right);
8764 /* This is a net loss for size == 1, but a big gain
8767 D (emitcode (";", "genFarFarAssign (improved)");
8770 aopOp (result, ic, TRUE, TRUE);
8772 _startLazyDPSEvaluation ();
8775 aopPut (AOP (result),
8776 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8779 _endLazyDPSEvaluation ();
8780 freeAsmop (result, NULL, ic, FALSE);
8781 freeAsmop (right, NULL, ic, FALSE);
8785 D (emitcode (";", "genFarFarAssign ");
8788 /* first push the right side on to the stack */
8789 _startLazyDPSEvaluation ();
8792 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8794 emitcode ("push", "acc");
8797 freeAsmop (right, NULL, ic, FALSE);
8798 /* now assign DPTR to result */
8799 aopOp (result, ic, FALSE, FALSE);
8800 size = AOP_SIZE (result);
8803 emitcode ("pop", "acc");
8804 aopPut (AOP (result), "a", --offset);
8806 freeAsmop (result, NULL, ic, FALSE);
8807 _endLazyDPSEvaluation ();
8811 /*-----------------------------------------------------------------*/
8812 /* genAssign - generate code for assignment */
8813 /*-----------------------------------------------------------------*/
8815 genAssign (iCode * ic)
8817 operand *result, *right;
8819 unsigned long lit = 0L;
8821 D (emitcode (";", "genAssign ");
8824 result = IC_RESULT (ic);
8825 right = IC_RIGHT (ic);
8827 /* if they are the same */
8828 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8831 aopOp (right, ic, FALSE, FALSE);
8833 emitcode (";", "genAssign: resultIsFar = %s",
8834 isOperandInFarSpace (result) ?
8837 /* special case both in far space */
8838 if ((AOP_TYPE (right) == AOP_DPTR ||
8839 AOP_TYPE (right) == AOP_DPTR2) &&
8840 /* IS_TRUE_SYMOP(result) && */
8841 isOperandInFarSpace (result))
8843 genFarFarAssign (result, right, ic);
8847 aopOp (result, ic, TRUE, FALSE);
8849 /* if they are the same registers */
8850 if (sameRegs (AOP (right), AOP (result)))
8853 /* if the result is a bit */
8854 if (AOP_TYPE (result) == AOP_CRY)
8857 /* if the right size is a literal then
8858 we know what the value is */
8859 if (AOP_TYPE (right) == AOP_LIT)
8861 if (((int) operandLitValue (right)))
8862 aopPut (AOP (result), one, 0);
8864 aopPut (AOP (result), zero, 0);
8868 /* the right is also a bit variable */
8869 if (AOP_TYPE (right) == AOP_CRY)
8871 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8872 aopPut (AOP (result), "c", 0);
8878 aopPut (AOP (result), "a", 0);
8882 /* bit variables done */
8884 size = AOP_SIZE (result);
8886 if (AOP_TYPE (right) == AOP_LIT)
8887 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8890 (AOP_TYPE (result) != AOP_REG) &&
8891 (AOP_TYPE (right) == AOP_LIT) &&
8892 !IS_FLOAT (operandType (right)))
8894 D (emitcode (";", "Kevin's better literal load code");
8896 _startLazyDPSEvaluation ();
8897 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8899 aopPut (AOP (result),
8900 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8905 /* And now fill the rest with zeros. */
8908 emitcode ("clr", "a");
8912 aopPut (AOP (result), "a", offset++);
8914 _endLazyDPSEvaluation ();
8918 _startLazyDPSEvaluation ();
8921 aopPut (AOP (result),
8922 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8926 _endLazyDPSEvaluation ();
8930 freeAsmop (right, NULL, ic, FALSE);
8931 freeAsmop (result, NULL, ic, TRUE);
8934 /*-----------------------------------------------------------------*/
8935 /* genJumpTab - generates code for jump table */
8936 /*-----------------------------------------------------------------*/
8938 genJumpTab (iCode * ic)
8943 D (emitcode (";", "genJumpTab ");
8946 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8947 /* get the condition into accumulator */
8948 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8950 /* multiply by four! */
8951 emitcode ("add", "a,acc");
8952 emitcode ("add", "a,acc");
8953 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8955 jtab = newiTempLabel (NULL);
8956 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8957 emitcode ("jmp", "@a+dptr");
8958 emitcode ("", "%05d$:", jtab->key + 100);
8959 /* now generate the jump labels */
8960 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8961 jtab = setNextItem (IC_JTLABELS (ic)))
8962 emitcode ("ljmp", "%05d$", jtab->key + 100);
8966 /*-----------------------------------------------------------------*/
8967 /* genCast - gen code for casting */
8968 /*-----------------------------------------------------------------*/
8970 genCast (iCode * ic)
8972 operand *result = IC_RESULT (ic);
8973 sym_link *ctype = operandType (IC_LEFT (ic));
8974 sym_link *rtype = operandType (IC_RIGHT (ic));
8975 operand *right = IC_RIGHT (ic);
8978 D (emitcode (";", "genCast ");
8981 /* if they are equivalent then do nothing */
8982 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8985 aopOp (right, ic, FALSE, FALSE);
8986 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8988 /* if the result is a bit */
8989 if (AOP_TYPE (result) == AOP_CRY)
8991 /* if the right size is a literal then
8992 we know what the value is */
8993 if (AOP_TYPE (right) == AOP_LIT)
8995 if (((int) operandLitValue (right)))
8996 aopPut (AOP (result), one, 0);
8998 aopPut (AOP (result), zero, 0);
9003 /* the right is also a bit variable */
9004 if (AOP_TYPE (right) == AOP_CRY)
9006 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9007 aopPut (AOP (result), "c", 0);
9013 aopPut (AOP (result), "a", 0);
9017 /* if they are the same size : or less */
9018 if (AOP_SIZE (result) <= AOP_SIZE (right))
9021 /* if they are in the same place */
9022 if (sameRegs (AOP (right), AOP (result)))
9025 /* if they in different places then copy */
9026 size = AOP_SIZE (result);
9028 _startLazyDPSEvaluation ();
9031 aopPut (AOP (result),
9032 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9036 _endLazyDPSEvaluation ();
9041 /* if the result is of type pointer */
9046 sym_link *type = operandType (right);
9048 /* pointer to generic pointer */
9049 if (IS_GENPTR (ctype))
9055 p_type = DCL_TYPE (type);
9059 #if OLD_CAST_BEHAVIOR
9060 /* KV: we are converting a non-pointer type to
9061 * a generic pointer. This (ifdef'd out) code
9062 * says that the resulting generic pointer
9063 * should have the same class as the storage
9064 * location of the non-pointer variable.
9066 * For example, converting an int (which happens
9067 * to be stored in DATA space) to a pointer results
9068 * in a DATA generic pointer; if the original int
9069 * in XDATA space, so will be the resulting pointer.
9071 * I don't like that behavior, and thus this change:
9072 * all such conversions will be forced to XDATA and
9073 * throw a warning. If you want some non-XDATA
9074 * type, or you want to suppress the warning, you
9075 * must go through an intermediate cast, like so:
9077 * char _generic *gp = (char _xdata *)(intVar);
9079 sym_link *etype = getSpec (type);
9081 /* we have to go by the storage class */
9082 if (SPEC_OCLS (etype) != generic)
9084 p_type = PTR_TYPE (SPEC_OCLS (etype));
9089 /* Converting unknown class (i.e. register variable)
9090 * to generic pointer. This is not good, but
9091 * we'll make a guess (and throw a warning).
9094 werror (W_INT_TO_GEN_PTR_CAST);
9098 /* the first two bytes are known */
9099 size = GPTRSIZE - 1;
9101 _startLazyDPSEvaluation ();
9104 aopPut (AOP (result),
9105 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9109 _endLazyDPSEvaluation ();
9111 /* the last byte depending on type */
9129 /* this should never happen */
9130 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9131 "got unknown pointer type");
9134 aopPut (AOP (result), l, GPTRSIZE - 1);
9138 /* just copy the pointers */
9139 size = AOP_SIZE (result);
9141 _startLazyDPSEvaluation ();
9144 aopPut (AOP (result),
9145 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9149 _endLazyDPSEvaluation ();
9153 /* so we now know that the size of destination is greater
9154 than the size of the source */
9155 /* we move to result for the size of source */
9156 size = AOP_SIZE (right);
9158 _startLazyDPSEvaluation ();
9161 aopPut (AOP (result),
9162 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9166 _endLazyDPSEvaluation ();
9168 /* now depending on the sign of the source && destination */
9169 size = AOP_SIZE (result) - AOP_SIZE (right);
9170 /* if unsigned or not an integral type */
9171 /* also, if the source is a bit, we don't need to sign extend, because
9172 * it can't possibly have set the sign bit.
9174 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9178 aopPut (AOP (result), zero, offset++);
9183 /* we need to extend the sign :{ */
9184 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9185 FALSE, FALSE, TRUE);
9187 emitcode ("rlc", "a");
9188 emitcode ("subb", "a,acc");
9190 aopPut (AOP (result), "a", offset++);
9193 /* we are done hurray !!!! */
9196 freeAsmop (right, NULL, ic, TRUE);
9197 freeAsmop (result, NULL, ic, TRUE);
9201 /*-----------------------------------------------------------------*/
9202 /* genDjnz - generate decrement & jump if not zero instrucion */
9203 /*-----------------------------------------------------------------*/
9205 genDjnz (iCode * ic, iCode * ifx)
9211 /* if the if condition has a false label
9212 then we cannot save */
9216 /* if the minus is not of the form
9218 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9219 !IS_OP_LITERAL (IC_RIGHT (ic)))
9222 if (operandLitValue (IC_RIGHT (ic)) != 1)
9225 /* if the size of this greater than one then no
9227 if (getSize (operandType (IC_RESULT (ic))) > 1)
9230 /* otherwise we can save BIG */
9231 D(emitcode(";", "genDjnz"););
9233 lbl = newiTempLabel (NULL);
9234 lbl1 = newiTempLabel (NULL);
9236 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9238 if (AOP_NEEDSACC(IC_RESULT(ic)))
9240 /* If the result is accessed indirectly via
9241 * the accumulator, we must explicitly write
9242 * it back after the decrement.
9244 emitcode ("dec", "%s",
9245 aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, FALSE));
9246 aopPut(AOP(IC_RESULT(ic)), "acc", 0);
9247 emitcode ("jnz", "%05d$", lbl->key + 100);
9249 else if (IS_AOP_PREG (IC_RESULT (ic)))
9251 emitcode ("dec", "%s",
9252 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9253 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9254 emitcode ("jnz", "%05d$", lbl->key + 100);
9258 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9261 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9262 emitcode ("", "%05d$:", lbl->key + 100);
9263 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9264 emitcode ("", "%05d$:", lbl1->key + 100);
9266 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9271 /*-----------------------------------------------------------------*/
9272 /* genReceive - generate code for a receive iCode */
9273 /*-----------------------------------------------------------------*/
9275 genReceive (iCode * ic)
9278 D (emitcode (";", "genReceive ");
9281 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9282 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9283 IS_TRUE_SYMOP (IC_RESULT (ic))))
9285 int size = getSize (operandType (IC_RESULT (ic)));
9286 int offset = fReturnSizeDS390 - size;
9289 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9290 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9293 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9294 size = AOP_SIZE (IC_RESULT (ic));
9298 emitcode ("pop", "acc");
9299 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9306 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9308 assignResultValue (IC_RESULT (ic));
9311 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9314 /*-----------------------------------------------------------------*/
9315 /* gen390Code - generate code for Dallas 390 based controllers */
9316 /*-----------------------------------------------------------------*/
9318 gen390Code (iCode * lic)
9323 lineHead = lineCurr = NULL;
9327 /* print the allocation information */
9329 printAllocInfo (currFunc, codeOutFile);
9331 /* if debug information required */
9332 if (options.debug && currFunc)
9334 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9336 if (IS_STATIC (currFunc->etype))
9337 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9339 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9342 /* stack pointer name */
9343 if (options.useXstack)
9349 for (ic = lic; ic; ic = ic->next)
9352 if (cln != ic->lineno)
9357 emitcode ("", "C$%s$%d$%d$%d ==.",
9358 FileBaseName (ic->filename), ic->lineno,
9359 ic->level, ic->block);
9362 emitcode (";", "%s %d", ic->filename, ic->lineno);
9365 /* if the result is marked as
9366 spilt and rematerializable or code for
9367 this has already been generated then
9369 if (resultRemat (ic) || ic->generated)
9372 /* depending on the operation */
9392 /* IPOP happens only when trying to restore a
9393 spilt live range, if there is an ifx statement
9394 following this pop then the if statement might
9395 be using some of the registers being popped which
9396 would destory the contents of the register so
9397 we need to check for this condition and handle it */
9399 ic->next->op == IFX &&
9400 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9401 genIfx (ic->next, ic);
9419 genEndFunction (ic);
9439 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9456 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9460 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9467 /* note these two are xlated by algebraic equivalence
9468 during parsing SDCC.y */
9469 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9470 "got '>=' or '<=' shouldn't have come here");
9474 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9486 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9490 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9494 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9521 case GET_VALUE_AT_ADDRESS:
9526 if (POINTER_SET (ic))
9553 addSet (&_G.sendSet, ic);
9562 /* now we are ready to call the
9563 peep hole optimizer */
9564 if (!options.nopeep)
9565 peepHole (&lineHead);
9567 /* now do the actual printing */
9568 printLine (lineHead, codeOutFile);