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 ");
4339 left = IC_LEFT (ic);
4340 right = IC_RIGHT (ic);
4342 letype = getSpec (operandType (left));
4343 retype = getSpec (operandType (right));
4344 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4346 /* assign the left & right amsops */
4349 genCmp (left, right, ic, ifx, sign);
4352 /*-----------------------------------------------------------------*/
4353 /* gencjneshort - compare and jump if not equal */
4354 /*-----------------------------------------------------------------*/
4356 gencjneshort (operand * left, operand * right, symbol * lbl)
4358 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4360 unsigned long lit = 0L;
4362 D (emitcode (";", "gencjneshort");
4365 /* if the left side is a literal or
4366 if the right is in a pointer register and left
4368 if ((AOP_TYPE (left) == AOP_LIT) ||
4369 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4376 if (AOP_TYPE (right) == AOP_LIT)
4377 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4379 if (opIsGptr (left) || opIsGptr (right))
4381 /* We are comparing a generic pointer to something.
4382 * Exclude the generic type byte from the comparison.
4385 D (emitcode (";", "cjneshort: generic ptr special case.");
4390 /* if the right side is a literal then anything goes */
4391 if (AOP_TYPE (right) == AOP_LIT &&
4392 AOP_TYPE (left) != AOP_DIR)
4396 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4398 emitcode ("cjne", "a,%s,%05d$",
4399 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4405 /* if the right side is in a register or in direct space or
4406 if the left is a pointer register & right is not */
4407 else if (AOP_TYPE (right) == AOP_REG ||
4408 AOP_TYPE (right) == AOP_DIR ||
4409 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4410 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4414 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4415 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4416 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4417 emitcode ("jnz", "%05d$", lbl->key + 100);
4419 emitcode ("cjne", "a,%s,%05d$",
4420 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4427 /* right is a pointer reg need both a & b */
4430 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4431 if (strcmp (l, "b"))
4432 emitcode ("mov", "b,%s", l);
4433 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4434 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4440 /*-----------------------------------------------------------------*/
4441 /* gencjne - compare and jump if not equal */
4442 /*-----------------------------------------------------------------*/
4444 gencjne (operand * left, operand * right, symbol * lbl)
4446 symbol *tlbl = newiTempLabel (NULL);
4448 D (emitcode (";", "gencjne");
4451 gencjneshort (left, right, lbl);
4453 emitcode ("mov", "a,%s", one);
4454 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4455 emitcode ("", "%05d$:", lbl->key + 100);
4456 emitcode ("clr", "a");
4457 emitcode ("", "%05d$:", tlbl->key + 100);
4460 /*-----------------------------------------------------------------*/
4461 /* genCmpEq - generates code for equal to */
4462 /*-----------------------------------------------------------------*/
4464 genCmpEq (iCode * ic, iCode * ifx)
4466 operand *left, *right, *result;
4468 D (emitcode (";", "genCmpEq ");
4472 AOP_SET_LOCALS (ic);
4474 /* if literal, literal on the right or
4475 if the right is in a pointer register and left
4477 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4478 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4480 operand *t = IC_RIGHT (ic);
4481 IC_RIGHT (ic) = IC_LEFT (ic);
4485 if (ifx && /* !AOP_SIZE(result) */
4486 OP_SYMBOL (result) &&
4487 OP_SYMBOL (result)->regType == REG_CND)
4490 /* if they are both bit variables */
4491 if (AOP_TYPE (left) == AOP_CRY &&
4492 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4494 if (AOP_TYPE (right) == AOP_LIT)
4496 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4499 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4500 emitcode ("cpl", "c");
4504 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4508 emitcode ("clr", "c");
4510 /* AOP_TYPE(right) == AOP_CRY */
4514 symbol *lbl = newiTempLabel (NULL);
4515 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4516 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4517 emitcode ("cpl", "c");
4518 emitcode ("", "%05d$:", (lbl->key + 100));
4520 /* if true label then we jump if condition
4522 tlbl = newiTempLabel (NULL);
4525 emitcode ("jnc", "%05d$", tlbl->key + 100);
4526 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4530 emitcode ("jc", "%05d$", tlbl->key + 100);
4531 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4533 emitcode ("", "%05d$:", tlbl->key + 100);
4537 tlbl = newiTempLabel (NULL);
4538 gencjneshort (left, right, tlbl);
4541 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4542 emitcode ("", "%05d$:", tlbl->key + 100);
4546 symbol *lbl = newiTempLabel (NULL);
4547 emitcode ("sjmp", "%05d$", lbl->key + 100);
4548 emitcode ("", "%05d$:", tlbl->key + 100);
4549 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4550 emitcode ("", "%05d$:", lbl->key + 100);
4553 /* mark the icode as generated */
4556 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4557 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4561 /* if they are both bit variables */
4562 if (AOP_TYPE (left) == AOP_CRY &&
4563 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4565 if (AOP_TYPE (right) == AOP_LIT)
4567 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4570 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4571 emitcode ("cpl", "c");
4575 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579 emitcode ("clr", "c");
4581 /* AOP_TYPE(right) == AOP_CRY */
4585 symbol *lbl = newiTempLabel (NULL);
4586 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4587 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4588 emitcode ("cpl", "c");
4589 emitcode ("", "%05d$:", (lbl->key + 100));
4592 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4593 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4595 aopOp (result, ic, TRUE, FALSE);
4598 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4605 genIfxJump (ifx, "c");
4608 /* if the result is used in an arithmetic operation
4609 then put the result in place */
4614 gencjne (left, right, newiTempLabel (NULL));
4616 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4619 aopOp (result, ic, TRUE, FALSE);
4621 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4623 aopPut (AOP (result), "a", 0);
4628 genIfxJump (ifx, "a");
4631 /* if the result is used in an arithmetic operation
4632 then put the result in place */
4633 if (AOP_TYPE (result) != AOP_CRY)
4635 /* leave the result in acc */
4639 freeAsmop (result, NULL, ic, TRUE);
4642 /*-----------------------------------------------------------------*/
4643 /* ifxForOp - returns the icode containing the ifx for operand */
4644 /*-----------------------------------------------------------------*/
4646 ifxForOp (operand * op, iCode * ic)
4648 /* if true symbol then needs to be assigned */
4649 if (IS_TRUE_SYMOP (op))
4652 /* if this has register type condition and
4653 the next instruction is ifx with the same operand
4654 and live to of the operand is upto the ifx only then */
4656 ic->next->op == IFX &&
4657 IC_COND (ic->next)->key == op->key &&
4658 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4663 /*-----------------------------------------------------------------*/
4664 /* genAndOp - for && operation */
4665 /*-----------------------------------------------------------------*/
4667 genAndOp (iCode * ic)
4669 operand *left, *right, *result;
4672 D (emitcode (";", "genAndOp "););
4674 /* note here that && operations that are in an
4675 if statement are taken away by backPatchLabels
4676 only those used in arthmetic operations remain */
4678 AOP_SET_LOCALS (ic);
4680 /* if both are bit variables */
4681 if (AOP_TYPE (left) == AOP_CRY &&
4682 AOP_TYPE (right) == AOP_CRY)
4684 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4685 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4686 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4689 aopOp (result,ic,FALSE, FALSE);
4694 tlbl = newiTempLabel (NULL);
4696 emitcode ("jz", "%05d$", tlbl->key + 100);
4698 emitcode ("", "%05d$:", tlbl->key + 100);
4699 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4700 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4702 aopOp (result,ic,FALSE, FALSE);
4705 freeAsmop (result, NULL, ic, TRUE);
4709 /*-----------------------------------------------------------------*/
4710 /* genOrOp - for || operation */
4711 /*-----------------------------------------------------------------*/
4713 genOrOp (iCode * ic)
4715 operand *left, *right, *result;
4718 D (emitcode (";", "genOrOp "););
4720 /* note here that || operations that are in an
4721 if statement are taken away by backPatchLabels
4722 only those used in arthmetic operations remain */
4724 AOP_SET_LOCALS (ic);
4726 /* if both are bit variables */
4727 if (AOP_TYPE (left) == AOP_CRY &&
4728 AOP_TYPE (right) == AOP_CRY)
4730 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4731 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4733 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4735 aopOp (result,ic,FALSE, FALSE);
4741 tlbl = newiTempLabel (NULL);
4743 emitcode ("jnz", "%05d$", tlbl->key + 100);
4745 emitcode ("", "%05d$:", tlbl->key + 100);
4746 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4747 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4749 aopOp (result,ic,FALSE, FALSE);
4754 freeAsmop (result, NULL, ic, TRUE);
4757 /*-----------------------------------------------------------------*/
4758 /* isLiteralBit - test if lit == 2^n */
4759 /*-----------------------------------------------------------------*/
4761 isLiteralBit (unsigned long lit)
4763 unsigned long pw[32] =
4764 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4765 0x100L, 0x200L, 0x400L, 0x800L,
4766 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4767 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4768 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4769 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4770 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4773 for (idx = 0; idx < 32; idx++)
4779 /*-----------------------------------------------------------------*/
4780 /* continueIfTrue - */
4781 /*-----------------------------------------------------------------*/
4783 continueIfTrue (iCode * ic)
4786 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4790 /*-----------------------------------------------------------------*/
4792 /*-----------------------------------------------------------------*/
4794 jumpIfTrue (iCode * ic)
4797 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4801 /*-----------------------------------------------------------------*/
4802 /* jmpTrueOrFalse - */
4803 /*-----------------------------------------------------------------*/
4805 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4807 // ugly but optimized by peephole
4810 symbol *nlbl = newiTempLabel (NULL);
4811 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4812 emitcode ("", "%05d$:", tlbl->key + 100);
4813 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4814 emitcode ("", "%05d$:", nlbl->key + 100);
4818 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4819 emitcode ("", "%05d$:", tlbl->key + 100);
4824 // Generate code to perform a bit-wise logic operation
4825 // on two operands in far space (assumed to already have been
4826 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4827 // in far space. This requires pushing the result on the stack
4828 // then popping it into the result.
4830 genFarFarLogicOp(iCode *ic, char *logicOp)
4832 int size, resultSize, compSize;
4835 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4836 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4837 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4839 _startLazyDPSEvaluation();
4840 for (size = compSize; (size--); offset++)
4842 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4843 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4844 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4846 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4847 emitcode ("push", "acc");
4849 _endLazyDPSEvaluation();
4851 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4852 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4853 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4855 resultSize = AOP_SIZE(IC_RESULT(ic));
4857 ADJUST_PUSHED_RESULT(compSize, resultSize);
4859 _startLazyDPSEvaluation();
4862 emitcode ("pop", "acc");
4863 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4865 _endLazyDPSEvaluation();
4866 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4870 /*-----------------------------------------------------------------*/
4871 /* genAnd - code for and */
4872 /*-----------------------------------------------------------------*/
4874 genAnd (iCode * ic, iCode * ifx)
4876 operand *left, *right, *result;
4877 int size, offset = 0;
4878 unsigned long lit = 0L;
4883 D (emitcode (";", "genAnd "););
4885 AOP_OP_3_NOFATAL (ic, pushResult);
4886 AOP_SET_LOCALS (ic);
4890 genFarFarLogicOp(ic, "anl");
4895 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4897 AOP_TYPE (left), AOP_TYPE (right));
4898 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4900 AOP_SIZE (left), AOP_SIZE (right));
4903 /* if left is a literal & right is not then exchange them */
4904 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4905 AOP_NEEDSACC (left))
4907 operand *tmp = right;
4912 /* if result = right then exchange them */
4913 if (sameRegs (AOP (result), AOP (right)))
4915 operand *tmp = right;
4920 /* if right is bit then exchange them */
4921 if (AOP_TYPE (right) == AOP_CRY &&
4922 AOP_TYPE (left) != AOP_CRY)
4924 operand *tmp = right;
4928 if (AOP_TYPE (right) == AOP_LIT)
4929 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4931 size = AOP_SIZE (result);
4934 // result = bit & yy;
4935 if (AOP_TYPE (left) == AOP_CRY)
4937 // c = bit & literal;
4938 if (AOP_TYPE (right) == AOP_LIT)
4942 if (size && sameRegs (AOP (result), AOP (left)))
4945 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4950 if (size && (AOP_TYPE (result) == AOP_CRY))
4952 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4955 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4960 emitcode ("clr", "c");
4965 if (AOP_TYPE (right) == AOP_CRY)
4968 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4969 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4974 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4976 emitcode ("rrc", "a");
4977 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4985 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4986 genIfxJump (ifx, "c");
4990 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4991 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4992 if ((AOP_TYPE (right) == AOP_LIT) &&
4993 (AOP_TYPE (result) == AOP_CRY) &&
4994 (AOP_TYPE (left) != AOP_CRY))
4996 int posbit = isLiteralBit (lit);
5001 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5004 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5010 sprintf (buffer, "acc.%d", posbit & 0x07);
5011 genIfxJump (ifx, buffer);
5018 symbol *tlbl = newiTempLabel (NULL);
5019 int sizel = AOP_SIZE (left);
5021 emitcode ("setb", "c");
5024 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5026 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5028 if ((posbit = isLiteralBit (bytelit)) != 0)
5029 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5032 if (bytelit != 0x0FFL)
5033 emitcode ("anl", "a,%s",
5034 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5035 emitcode ("jnz", "%05d$", tlbl->key + 100);
5040 // bit = left & literal
5043 emitcode ("clr", "c");
5044 emitcode ("", "%05d$:", tlbl->key + 100);
5046 // if(left & literal)
5050 jmpTrueOrFalse (ifx, tlbl);
5058 /* if left is same as result */
5059 if (sameRegs (AOP (result), AOP (left)))
5061 for (; size--; offset++)
5063 if (AOP_TYPE (right) == AOP_LIT)
5065 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5067 else if (bytelit == 0)
5068 aopPut (AOP (result), zero, offset);
5069 else if (IS_AOP_PREG (result))
5071 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5072 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5073 aopPut (AOP (result), "a", offset);
5076 emitcode ("anl", "%s,%s",
5077 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5078 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5082 if (AOP_TYPE (left) == AOP_ACC)
5083 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5086 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5087 if (IS_AOP_PREG (result))
5089 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5090 aopPut (AOP (result), "a", offset);
5094 emitcode ("anl", "%s,a",
5095 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5102 // left & result in different registers
5103 if (AOP_TYPE (result) == AOP_CRY)
5106 // if(size), result in bit
5107 // if(!size && ifx), conditional oper: if(left & right)
5108 symbol *tlbl = newiTempLabel (NULL);
5109 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5111 emitcode ("setb", "c");
5114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5115 emitcode ("anl", "a,%s",
5116 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5117 emitcode ("jnz", "%05d$", tlbl->key + 100);
5123 emitcode ("", "%05d$:", tlbl->key + 100);
5127 jmpTrueOrFalse (ifx, tlbl);
5131 for (; (size--); offset++)
5134 // result = left & right
5135 if (AOP_TYPE (right) == AOP_LIT)
5137 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5139 aopPut (AOP (result),
5140 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5144 else if (bytelit == 0)
5146 aopPut (AOP (result), zero, offset);
5149 D (emitcode (";", "better literal AND.");
5151 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5152 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5153 FALSE, FALSE, FALSE));
5158 // faster than result <- left, anl result,right
5159 // and better if result is SFR
5160 if (AOP_TYPE (left) == AOP_ACC)
5162 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5163 FALSE, FALSE, FALSE));
5167 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5168 emitcode ("anl", "a,%s",
5169 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5172 aopPut (AOP (result), "a", offset);
5178 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5179 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5180 freeAsmop (result, NULL, ic, TRUE);
5184 /*-----------------------------------------------------------------*/
5185 /* genOr - code for or */
5186 /*-----------------------------------------------------------------*/
5188 genOr (iCode * ic, iCode * ifx)
5190 operand *left, *right, *result;
5191 int size, offset = 0;
5192 unsigned long lit = 0L;
5195 D (emitcode (";", "genOr "););
5197 AOP_OP_3_NOFATAL (ic, pushResult);
5198 AOP_SET_LOCALS (ic);
5202 genFarFarLogicOp(ic, "orl");
5208 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5210 AOP_TYPE (left), AOP_TYPE (right));
5211 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5213 AOP_SIZE (left), AOP_SIZE (right));
5216 /* if left is a literal & right is not then exchange them */
5217 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5218 AOP_NEEDSACC (left))
5220 operand *tmp = right;
5225 /* if result = right then exchange them */
5226 if (sameRegs (AOP (result), AOP (right)))
5228 operand *tmp = right;
5233 /* if right is bit then exchange them */
5234 if (AOP_TYPE (right) == AOP_CRY &&
5235 AOP_TYPE (left) != AOP_CRY)
5237 operand *tmp = right;
5241 if (AOP_TYPE (right) == AOP_LIT)
5242 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5244 size = AOP_SIZE (result);
5248 if (AOP_TYPE (left) == AOP_CRY)
5250 if (AOP_TYPE (right) == AOP_LIT)
5252 // c = bit & literal;
5255 // lit != 0 => result = 1
5256 if (AOP_TYPE (result) == AOP_CRY)
5259 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5261 continueIfTrue (ifx);
5264 emitcode ("setb", "c");
5268 // lit == 0 => result = left
5269 if (size && sameRegs (AOP (result), AOP (left)))
5271 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5276 if (AOP_TYPE (right) == AOP_CRY)
5279 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5280 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5285 symbol *tlbl = newiTempLabel (NULL);
5286 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5287 emitcode ("setb", "c");
5288 emitcode ("jb", "%s,%05d$",
5289 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5291 emitcode ("jnz", "%05d$", tlbl->key + 100);
5292 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5294 jmpTrueOrFalse (ifx, tlbl);
5300 emitcode ("", "%05d$:", tlbl->key + 100);
5309 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5310 genIfxJump (ifx, "c");
5314 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5315 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5316 if ((AOP_TYPE (right) == AOP_LIT) &&
5317 (AOP_TYPE (result) == AOP_CRY) &&
5318 (AOP_TYPE (left) != AOP_CRY))
5324 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5326 continueIfTrue (ifx);
5331 // lit = 0, result = boolean(left)
5333 emitcode ("setb", "c");
5337 symbol *tlbl = newiTempLabel (NULL);
5338 emitcode ("jnz", "%05d$", tlbl->key + 100);
5340 emitcode ("", "%05d$:", tlbl->key + 100);
5344 genIfxJump (ifx, "a");
5352 /* if left is same as result */
5353 if (sameRegs (AOP (result), AOP (left)))
5355 for (; size--; offset++)
5357 if (AOP_TYPE (right) == AOP_LIT)
5359 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5365 if (IS_AOP_PREG (left))
5367 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5368 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5369 aopPut (AOP (result), "a", offset);
5373 emitcode ("orl", "%s,%s",
5374 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5375 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5381 if (AOP_TYPE (left) == AOP_ACC)
5383 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5387 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5388 if (IS_AOP_PREG (left))
5390 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5391 aopPut (AOP (result), "a", offset);
5395 emitcode ("orl", "%s,a",
5396 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5404 // left & result in different registers
5405 if (AOP_TYPE (result) == AOP_CRY)
5408 // if(size), result in bit
5409 // if(!size && ifx), conditional oper: if(left | right)
5410 symbol *tlbl = newiTempLabel (NULL);
5411 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5413 emitcode ("setb", "c");
5416 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5417 emitcode ("orl", "a,%s",
5418 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5419 emitcode ("jnz", "%05d$", tlbl->key + 100);
5425 emitcode ("", "%05d$:", tlbl->key + 100);
5429 jmpTrueOrFalse (ifx, tlbl);
5433 for (; (size--); offset++)
5436 // result = left & right
5437 if (AOP_TYPE (right) == AOP_LIT)
5439 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5441 aopPut (AOP (result),
5442 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5446 D (emitcode (";", "better literal OR.");
5448 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5449 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5450 FALSE, FALSE, FALSE));
5455 // faster than result <- left, anl result,right
5456 // and better if result is SFR
5457 if (AOP_TYPE (left) == AOP_ACC)
5459 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5460 FALSE, FALSE, FALSE));
5464 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5465 emitcode ("orl", "a,%s",
5466 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5469 aopPut (AOP (result), "a", offset);
5475 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477 freeAsmop (result, NULL, ic, TRUE);
5480 /*-----------------------------------------------------------------*/
5481 /* genXor - code for xclusive or */
5482 /*-----------------------------------------------------------------*/
5484 genXor (iCode * ic, iCode * ifx)
5486 operand *left, *right, *result;
5487 int size, offset = 0;
5488 unsigned long lit = 0L;
5491 D (emitcode (";", "genXor "););
5493 AOP_OP_3_NOFATAL (ic, pushResult);
5494 AOP_SET_LOCALS (ic);
5498 genFarFarLogicOp(ic, "xrl");
5503 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5505 AOP_TYPE (left), AOP_TYPE (right));
5506 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5508 AOP_SIZE (left), AOP_SIZE (right));
5511 /* if left is a literal & right is not ||
5512 if left needs acc & right does not */
5513 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5514 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5516 operand *tmp = right;
5521 /* if result = right then exchange them */
5522 if (sameRegs (AOP (result), AOP (right)))
5524 operand *tmp = right;
5529 /* if right is bit then exchange them */
5530 if (AOP_TYPE (right) == AOP_CRY &&
5531 AOP_TYPE (left) != AOP_CRY)
5533 operand *tmp = right;
5537 if (AOP_TYPE (right) == AOP_LIT)
5538 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5540 size = AOP_SIZE (result);
5544 if (AOP_TYPE (left) == AOP_CRY)
5546 if (AOP_TYPE (right) == AOP_LIT)
5548 // c = bit & literal;
5551 // lit>>1 != 0 => result = 1
5552 if (AOP_TYPE (result) == AOP_CRY)
5555 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5557 continueIfTrue (ifx);
5560 emitcode ("setb", "c");
5567 // lit == 0, result = left
5568 if (size && sameRegs (AOP (result), AOP (left)))
5570 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5574 // lit == 1, result = not(left)
5575 if (size && sameRegs (AOP (result), AOP (left)))
5577 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5582 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5583 emitcode ("cpl", "c");
5592 symbol *tlbl = newiTempLabel (NULL);
5593 if (AOP_TYPE (right) == AOP_CRY)
5596 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5600 int sizer = AOP_SIZE (right);
5602 // if val>>1 != 0, result = 1
5603 emitcode ("setb", "c");
5606 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5608 // test the msb of the lsb
5609 emitcode ("anl", "a,#0xfe");
5610 emitcode ("jnz", "%05d$", tlbl->key + 100);
5614 emitcode ("rrc", "a");
5616 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5617 emitcode ("cpl", "c");
5618 emitcode ("", "%05d$:", (tlbl->key + 100));
5625 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5626 genIfxJump (ifx, "c");
5630 if (sameRegs (AOP (result), AOP (left)))
5632 /* if left is same as result */
5633 for (; size--; offset++)
5635 if (AOP_TYPE (right) == AOP_LIT)
5637 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5639 else if (IS_AOP_PREG (left))
5641 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5642 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5643 aopPut (AOP (result), "a", offset);
5646 emitcode ("xrl", "%s,%s",
5647 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5648 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5652 if (AOP_TYPE (left) == AOP_ACC)
5653 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5656 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5657 if (IS_AOP_PREG (left))
5659 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5660 aopPut (AOP (result), "a", offset);
5663 emitcode ("xrl", "%s,a",
5664 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5671 // left & result in different registers
5672 if (AOP_TYPE (result) == AOP_CRY)
5675 // if(size), result in bit
5676 // if(!size && ifx), conditional oper: if(left ^ right)
5677 symbol *tlbl = newiTempLabel (NULL);
5678 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5680 emitcode ("setb", "c");
5683 if ((AOP_TYPE (right) == AOP_LIT) &&
5684 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5686 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5690 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5691 emitcode ("xrl", "a,%s",
5692 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5694 emitcode ("jnz", "%05d$", tlbl->key + 100);
5700 emitcode ("", "%05d$:", tlbl->key + 100);
5704 jmpTrueOrFalse (ifx, tlbl);
5707 for (; (size--); offset++)
5710 // result = left & right
5711 if (AOP_TYPE (right) == AOP_LIT)
5713 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5715 aopPut (AOP (result),
5716 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5720 D (emitcode (";", "better literal XOR.");
5722 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5723 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5724 FALSE, FALSE, FALSE));
5728 // faster than result <- left, anl result,right
5729 // and better if result is SFR
5730 if (AOP_TYPE (left) == AOP_ACC)
5732 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5733 FALSE, FALSE, FALSE));
5737 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5738 emitcode ("xrl", "a,%s",
5739 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5742 aopPut (AOP (result), "a", offset);
5747 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5748 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5749 freeAsmop (result, NULL, ic, TRUE);
5752 /*-----------------------------------------------------------------*/
5753 /* genInline - write the inline code out */
5754 /*-----------------------------------------------------------------*/
5756 genInline (iCode * ic)
5758 char buffer[MAX_INLINEASM];
5762 D (emitcode (";", "genInline ");
5765 _G.inLine += (!options.asmpeep);
5766 strcpy (buffer, IC_INLINE (ic));
5768 /* emit each line as a code */
5793 /* emitcode("",buffer); */
5794 _G.inLine -= (!options.asmpeep);
5797 /*-----------------------------------------------------------------*/
5798 /* genRRC - rotate right with carry */
5799 /*-----------------------------------------------------------------*/
5803 operand *left, *result;
5804 int size, offset = 0;
5807 D (emitcode (";", "genRRC ");
5810 /* rotate right with carry */
5811 left = IC_LEFT (ic);
5812 result = IC_RESULT (ic);
5813 aopOp (left, ic, FALSE, FALSE);
5814 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5816 /* move it to the result */
5817 size = AOP_SIZE (result);
5821 _startLazyDPSEvaluation ();
5824 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5826 emitcode ("rrc", "a");
5827 if (AOP_SIZE (result) > 1)
5828 aopPut (AOP (result), "a", offset--);
5830 _endLazyDPSEvaluation ();
5832 /* now we need to put the carry into the
5833 highest order byte of the result */
5834 if (AOP_SIZE (result) > 1)
5836 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5839 emitcode ("mov", "acc.7,c");
5840 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5841 freeAsmop (left, NULL, ic, TRUE);
5842 freeAsmop (result, NULL, ic, TRUE);
5845 /*-----------------------------------------------------------------*/
5846 /* genRLC - generate code for rotate left with carry */
5847 /*-----------------------------------------------------------------*/
5851 operand *left, *result;
5852 int size, offset = 0;
5855 D (emitcode (";", "genRLC ");
5858 /* rotate right with carry */
5859 left = IC_LEFT (ic);
5860 result = IC_RESULT (ic);
5861 aopOp (left, ic, FALSE, FALSE);
5862 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5864 /* move it to the result */
5865 size = AOP_SIZE (result);
5869 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5871 emitcode ("add", "a,acc");
5872 if (AOP_SIZE (result) > 1)
5874 aopPut (AOP (result), "a", offset++);
5877 _startLazyDPSEvaluation ();
5880 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5882 emitcode ("rlc", "a");
5883 if (AOP_SIZE (result) > 1)
5884 aopPut (AOP (result), "a", offset++);
5886 _endLazyDPSEvaluation ();
5888 /* now we need to put the carry into the
5889 highest order byte of the result */
5890 if (AOP_SIZE (result) > 1)
5892 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5895 emitcode ("mov", "acc.0,c");
5896 aopPut (AOP (result), "a", 0);
5897 freeAsmop (left, NULL, ic, TRUE);
5898 freeAsmop (result, NULL, ic, TRUE);
5901 /*-----------------------------------------------------------------*/
5902 /* genGetHbit - generates code get highest order bit */
5903 /*-----------------------------------------------------------------*/
5905 genGetHbit (iCode * ic)
5907 operand *left, *result;
5908 left = IC_LEFT (ic);
5909 result = IC_RESULT (ic);
5910 aopOp (left, ic, FALSE, FALSE);
5911 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5913 D (emitcode (";", "genGetHbit ");
5916 /* get the highest order byte into a */
5917 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5918 if (AOP_TYPE (result) == AOP_CRY)
5920 emitcode ("rlc", "a");
5925 emitcode ("rl", "a");
5926 emitcode ("anl", "a,#0x01");
5931 freeAsmop (left, NULL, ic, TRUE);
5932 freeAsmop (result, NULL, ic, TRUE);
5935 /*-----------------------------------------------------------------*/
5936 /* AccRol - rotate left accumulator by known count */
5937 /*-----------------------------------------------------------------*/
5939 AccRol (int shCount)
5941 shCount &= 0x0007; // shCount : 0..7
5948 emitcode ("rl", "a");
5951 emitcode ("rl", "a");
5952 emitcode ("rl", "a");
5955 emitcode ("swap", "a");
5956 emitcode ("rr", "a");
5959 emitcode ("swap", "a");
5962 emitcode ("swap", "a");
5963 emitcode ("rl", "a");
5966 emitcode ("rr", "a");
5967 emitcode ("rr", "a");
5970 emitcode ("rr", "a");
5975 /*-----------------------------------------------------------------*/
5976 /* AccLsh - left shift accumulator by known count */
5977 /*-----------------------------------------------------------------*/
5979 AccLsh (int shCount)
5984 emitcode ("add", "a,acc");
5985 else if (shCount == 2)
5987 emitcode ("add", "a,acc");
5988 emitcode ("add", "a,acc");
5992 /* rotate left accumulator */
5994 /* and kill the lower order bits */
5995 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6000 /*-----------------------------------------------------------------*/
6001 /* AccRsh - right shift accumulator by known count */
6002 /*-----------------------------------------------------------------*/
6004 AccRsh (int shCount)
6011 emitcode ("rrc", "a");
6015 /* rotate right accumulator */
6016 AccRol (8 - shCount);
6017 /* and kill the higher order bits */
6018 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6025 /*-----------------------------------------------------------------*/
6026 /* AccSRsh - signed right shift accumulator by known count */
6027 /*-----------------------------------------------------------------*/
6029 AccSRsh (int shCount)
6036 emitcode ("mov", "c,acc.7");
6037 emitcode ("rrc", "a");
6039 else if (shCount == 2)
6041 emitcode ("mov", "c,acc.7");
6042 emitcode ("rrc", "a");
6043 emitcode ("mov", "c,acc.7");
6044 emitcode ("rrc", "a");
6048 tlbl = newiTempLabel (NULL);
6049 /* rotate right accumulator */
6050 AccRol (8 - shCount);
6051 /* and kill the higher order bits */
6052 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6053 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6054 emitcode ("orl", "a,#0x%02x",
6055 (unsigned char) ~SRMask[shCount]);
6056 emitcode ("", "%05d$:", tlbl->key + 100);
6064 /*-----------------------------------------------------------------*/
6065 /* shiftR1Left2Result - shift right one byte from left to result */
6066 /*-----------------------------------------------------------------*/
6068 shiftR1Left2Result (operand * left, int offl,
6069 operand * result, int offr,
6070 int shCount, int sign)
6072 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6073 /* shift right accumulator */
6078 aopPut (AOP (result), "a", offr);
6084 /*-----------------------------------------------------------------*/
6085 /* shiftL1Left2Result - shift left one byte from left to result */
6086 /*-----------------------------------------------------------------*/
6088 shiftL1Left2Result (operand * left, int offl,
6089 operand * result, int offr, int shCount)
6092 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6094 /* shift left accumulator */
6096 aopPut (AOP (result), "a", offr);
6102 /*-----------------------------------------------------------------*/
6103 /* movLeft2Result - move byte from left to result */
6104 /*-----------------------------------------------------------------*/
6106 movLeft2Result (operand * left, int offl,
6107 operand * result, int offr, int sign)
6110 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6112 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6114 if (*l == '@' && (IS_AOP_PREG (result)))
6116 emitcode ("mov", "a,%s", l);
6117 aopPut (AOP (result), "a", offr);
6122 aopPut (AOP (result), l, offr);
6125 /* MSB sign in acc.7 ! */
6126 if (getDataSize (left) == offl + 1)
6128 emitcode ("mov", "a,%s", l);
6129 aopPut (AOP (result), "a", offr);
6139 /*-----------------------------------------------------------------*/
6140 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6141 /*-----------------------------------------------------------------*/
6145 emitcode ("rrc", "a");
6146 emitcode ("xch", "a,%s", x);
6147 emitcode ("rrc", "a");
6148 emitcode ("xch", "a,%s", x);
6154 /*-----------------------------------------------------------------*/
6155 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6156 /*-----------------------------------------------------------------*/
6160 emitcode ("xch", "a,%s", x);
6161 emitcode ("rlc", "a");
6162 emitcode ("xch", "a,%s", x);
6163 emitcode ("rlc", "a");
6169 /*-----------------------------------------------------------------*/
6170 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6171 /*-----------------------------------------------------------------*/
6175 emitcode ("xch", "a,%s", x);
6176 emitcode ("add", "a,acc");
6177 emitcode ("xch", "a,%s", x);
6178 emitcode ("rlc", "a");
6184 /*-----------------------------------------------------------------*/
6185 /* AccAXLsh - left shift a:x by known count (0..7) */
6186 /*-----------------------------------------------------------------*/
6188 AccAXLsh (char *x, int shCount)
6203 case 5: // AAAAABBB:CCCCCDDD
6205 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6207 emitcode ("anl", "a,#0x%02x",
6208 SLMask[shCount]); // BBB00000:CCCCCDDD
6210 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6212 AccRol (shCount); // DDDCCCCC:BBB00000
6214 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6216 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6218 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6220 emitcode ("anl", "a,#0x%02x",
6221 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6223 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6225 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6228 case 6: // AAAAAABB:CCCCCCDD
6229 emitcode ("anl", "a,#0x%02x",
6230 SRMask[shCount]); // 000000BB:CCCCCCDD
6231 emitcode ("mov", "c,acc.0"); // c = B
6232 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6234 AccAXRrl1 (x); // BCCCCCCD:D000000B
6235 AccAXRrl1 (x); // BBCCCCCC:DD000000
6237 emitcode("rrc","a");
6238 emitcode("xch","a,%s", x);
6239 emitcode("rrc","a");
6240 emitcode("mov","c,acc.0"); //<< get correct bit
6241 emitcode("xch","a,%s", x);
6243 emitcode("rrc","a");
6244 emitcode("xch","a,%s", x);
6245 emitcode("rrc","a");
6246 emitcode("xch","a,%s", x);
6249 case 7: // a:x <<= 7
6251 emitcode ("anl", "a,#0x%02x",
6252 SRMask[shCount]); // 0000000B:CCCCCCCD
6254 emitcode ("mov", "c,acc.0"); // c = B
6256 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6258 AccAXRrl1 (x); // BCCCCCCC:D0000000
6269 /*-----------------------------------------------------------------*/
6270 /* AccAXRsh - right shift a:x known count (0..7) */
6271 /*-----------------------------------------------------------------*/
6273 AccAXRsh (char *x, int shCount)
6281 AccAXRrl1 (x); // 0->a:x
6286 AccAXRrl1 (x); // 0->a:x
6289 AccAXRrl1 (x); // 0->a:x
6294 case 5: // AAAAABBB:CCCCCDDD = a:x
6296 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6298 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6300 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6302 emitcode ("anl", "a,#0x%02x",
6303 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6305 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6307 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6309 emitcode ("anl", "a,#0x%02x",
6310 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6312 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6314 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6316 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6319 case 6: // AABBBBBB:CCDDDDDD
6321 emitcode ("mov", "c,acc.7");
6322 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6324 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6326 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6328 emitcode ("anl", "a,#0x%02x",
6329 SRMask[shCount]); // 000000AA:BBBBBBCC
6332 case 7: // ABBBBBBB:CDDDDDDD
6334 emitcode ("mov", "c,acc.7"); // c = A
6336 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6338 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6340 emitcode ("anl", "a,#0x%02x",
6341 SRMask[shCount]); // 0000000A:BBBBBBBC
6352 /*-----------------------------------------------------------------*/
6353 /* AccAXRshS - right shift signed a:x known count (0..7) */
6354 /*-----------------------------------------------------------------*/
6356 AccAXRshS (char *x, int shCount)
6364 emitcode ("mov", "c,acc.7");
6365 AccAXRrl1 (x); // s->a:x
6369 emitcode ("mov", "c,acc.7");
6370 AccAXRrl1 (x); // s->a:x
6372 emitcode ("mov", "c,acc.7");
6373 AccAXRrl1 (x); // s->a:x
6378 case 5: // AAAAABBB:CCCCCDDD = a:x
6380 tlbl = newiTempLabel (NULL);
6381 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6383 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6385 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6387 emitcode ("anl", "a,#0x%02x",
6388 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6390 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6392 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6394 emitcode ("anl", "a,#0x%02x",
6395 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6397 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6399 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6401 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6403 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6404 emitcode ("orl", "a,#0x%02x",
6405 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6407 emitcode ("", "%05d$:", tlbl->key + 100);
6408 break; // SSSSAAAA:BBBCCCCC
6410 case 6: // AABBBBBB:CCDDDDDD
6412 tlbl = newiTempLabel (NULL);
6413 emitcode ("mov", "c,acc.7");
6414 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6416 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6418 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6420 emitcode ("anl", "a,#0x%02x",
6421 SRMask[shCount]); // 000000AA:BBBBBBCC
6423 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6424 emitcode ("orl", "a,#0x%02x",
6425 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6427 emitcode ("", "%05d$:", tlbl->key + 100);
6429 case 7: // ABBBBBBB:CDDDDDDD
6431 tlbl = newiTempLabel (NULL);
6432 emitcode ("mov", "c,acc.7"); // c = A
6434 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6436 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6438 emitcode ("anl", "a,#0x%02x",
6439 SRMask[shCount]); // 0000000A:BBBBBBBC
6441 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6442 emitcode ("orl", "a,#0x%02x",
6443 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6445 emitcode ("", "%05d$:", tlbl->key + 100);
6455 /*-----------------------------------------------------------------*/
6456 /* shiftL2Left2Result - shift left two bytes from left to result */
6457 /*-----------------------------------------------------------------*/
6459 shiftL2Left2Result (operand * left, int offl,
6460 operand * result, int offr, int shCount)
6462 if (sameRegs (AOP (result), AOP (left)) &&
6463 ((offl + MSB16) == offr))
6465 /* don't crash result[offr] */
6466 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6467 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6471 movLeft2Result (left, offl, result, offr, 0);
6472 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6474 /* ax << shCount (x = lsb(result)) */
6475 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6476 aopPut (AOP (result), "a", offr + MSB16);
6482 /*-----------------------------------------------------------------*/
6483 /* shiftR2Left2Result - shift right two bytes from left to result */
6484 /*-----------------------------------------------------------------*/
6486 shiftR2Left2Result (operand * left, int offl,
6487 operand * result, int offr,
6488 int shCount, int sign)
6490 if (sameRegs (AOP (result), AOP (left)) &&
6491 ((offl + MSB16) == offr))
6493 /* don't crash result[offr] */
6494 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6495 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6499 movLeft2Result (left, offl, result, offr, 0);
6500 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6502 /* a:x >> shCount (x = lsb(result)) */
6504 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6506 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6507 if (getDataSize (result) > 1)
6508 aopPut (AOP (result), "a", offr + MSB16);
6514 /*-----------------------------------------------------------------*/
6515 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6516 /*-----------------------------------------------------------------*/
6518 shiftLLeftOrResult (operand * left, int offl,
6519 operand * result, int offr, int shCount)
6521 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6522 /* shift left accumulator */
6524 /* or with result */
6525 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6526 /* back to result */
6527 aopPut (AOP (result), "a", offr);
6533 /*-----------------------------------------------------------------*/
6534 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6535 /*-----------------------------------------------------------------*/
6537 shiftRLeftOrResult (operand * left, int offl,
6538 operand * result, int offr, int shCount)
6540 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6541 /* shift right accumulator */
6543 /* or with result */
6544 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6545 /* back to result */
6546 aopPut (AOP (result), "a", offr);
6552 /*-----------------------------------------------------------------*/
6553 /* genlshOne - left shift a one byte quantity by known count */
6554 /*-----------------------------------------------------------------*/
6556 genlshOne (operand * result, operand * left, int shCount)
6558 D (emitcode (";", "genlshOne ");
6560 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6566 /*-----------------------------------------------------------------*/
6567 /* genlshTwo - left shift two bytes by known amount != 0 */
6568 /*-----------------------------------------------------------------*/
6570 genlshTwo (operand * result, operand * left, int shCount)
6574 D (emitcode (";", "genlshTwo ");
6577 size = getDataSize (result);
6579 /* if shCount >= 8 */
6587 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6589 movLeft2Result (left, LSB, result, MSB16, 0);
6591 aopPut (AOP (result), zero, LSB);
6594 /* 1 <= shCount <= 7 */
6598 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6600 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6607 /*-----------------------------------------------------------------*/
6608 /* shiftLLong - shift left one long from left to result */
6609 /* offl = LSB or MSB16 */
6610 /*-----------------------------------------------------------------*/
6612 shiftLLong (operand * left, operand * result, int offr)
6615 int size = AOP_SIZE (result);
6617 if (size >= LSB + offr)
6619 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6621 emitcode ("add", "a,acc");
6622 if (sameRegs (AOP (left), AOP (result)) &&
6623 size >= MSB16 + offr && offr != LSB)
6624 emitcode ("xch", "a,%s",
6625 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6627 aopPut (AOP (result), "a", LSB + offr);
6630 if (size >= MSB16 + offr)
6632 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6634 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6637 emitcode ("rlc", "a");
6638 if (sameRegs (AOP (left), AOP (result)) &&
6639 size >= MSB24 + offr && offr != LSB)
6640 emitcode ("xch", "a,%s",
6641 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6643 aopPut (AOP (result), "a", MSB16 + offr);
6646 if (size >= MSB24 + offr)
6648 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6650 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6653 emitcode ("rlc", "a");
6654 if (sameRegs (AOP (left), AOP (result)) &&
6655 size >= MSB32 + offr && offr != LSB)
6656 emitcode ("xch", "a,%s",
6657 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6659 aopPut (AOP (result), "a", MSB24 + offr);
6662 if (size > MSB32 + offr)
6664 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6666 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6669 emitcode ("rlc", "a");
6670 aopPut (AOP (result), "a", MSB32 + offr);
6673 aopPut (AOP (result), zero, LSB);
6679 /*-----------------------------------------------------------------*/
6680 /* genlshFour - shift four byte by a known amount != 0 */
6681 /*-----------------------------------------------------------------*/
6683 genlshFour (operand * result, operand * left, int shCount)
6687 D (emitcode (";", "genlshFour ");
6690 size = AOP_SIZE (result);
6692 /* if shifting more that 3 bytes */
6697 /* lowest order of left goes to the highest
6698 order of the destination */
6699 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6701 movLeft2Result (left, LSB, result, MSB32, 0);
6702 aopPut (AOP (result), zero, LSB);
6703 aopPut (AOP (result), zero, MSB16);
6704 aopPut (AOP (result), zero, MSB24);
6708 /* more than two bytes */
6709 else if (shCount >= 16)
6711 /* lower order two bytes goes to higher order two bytes */
6713 /* if some more remaining */
6715 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6718 movLeft2Result (left, MSB16, result, MSB32, 0);
6719 movLeft2Result (left, LSB, result, MSB24, 0);
6721 aopPut (AOP (result), zero, MSB16);
6722 aopPut (AOP (result), zero, LSB);
6726 /* if more than 1 byte */
6727 else if (shCount >= 8)
6729 /* lower order three bytes goes to higher order three bytes */
6734 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6736 movLeft2Result (left, LSB, result, MSB16, 0);
6742 movLeft2Result (left, MSB24, result, MSB32, 0);
6743 movLeft2Result (left, MSB16, result, MSB24, 0);
6744 movLeft2Result (left, LSB, result, MSB16, 0);
6745 aopPut (AOP (result), zero, LSB);
6747 else if (shCount == 1)
6748 shiftLLong (left, result, MSB16);
6751 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6752 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6753 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6754 aopPut (AOP (result), zero, LSB);
6759 /* 1 <= shCount <= 7 */
6760 else if (shCount <= 2)
6762 shiftLLong (left, result, LSB);
6764 shiftLLong (result, result, LSB);
6766 /* 3 <= shCount <= 7, optimize */
6769 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6770 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6771 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6778 /*-----------------------------------------------------------------*/
6779 /* genLeftShiftLiteral - left shifting by known count */
6780 /*-----------------------------------------------------------------*/
6782 genLeftShiftLiteral (operand * left,
6787 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6790 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6793 freeAsmop (right, NULL, ic, TRUE);
6795 aopOp (left, ic, FALSE, FALSE);
6796 aopOp (result, ic, FALSE, TRUE);
6798 size = getSize (operandType (result));
6801 emitcode ("; shift left ", "result %d, left %d", size,
6805 /* I suppose that the left size >= result size */
6810 movLeft2Result (left, size, result, size, 0);
6814 else if (shCount >= (size * 8))
6816 aopPut (AOP (result), zero, size);
6822 genlshOne (result, left, shCount);
6826 case 3: /* bug: this is for generic pointers, I bet. */
6827 genlshTwo (result, left, shCount);
6831 genlshFour (result, left, shCount);
6835 freeAsmop (left, NULL, ic, TRUE);
6836 freeAsmop (result, NULL, ic, TRUE);
6840 /*-----------------------------------------------------------------*/
6841 /* genLeftShift - generates code for left shifting */
6842 /*-----------------------------------------------------------------*/
6844 genLeftShift (iCode * ic)
6846 operand *left, *right, *result;
6849 symbol *tlbl, *tlbl1;
6851 D (emitcode (";", "genLeftShift ");
6854 right = IC_RIGHT (ic);
6855 left = IC_LEFT (ic);
6856 result = IC_RESULT (ic);
6858 aopOp (right, ic, FALSE, FALSE);
6861 /* if the shift count is known then do it
6862 as efficiently as possible */
6863 if (AOP_TYPE (right) == AOP_LIT)
6865 genLeftShiftLiteral (left, right, result, ic);
6870 /* shift count is unknown then we have to form
6871 a loop get the loop count in B : Note: we take
6872 only the lower order byte since shifting
6873 more that 32 bits make no sense anyway, ( the
6874 largest size of an object can be only 32 bits ) */
6876 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6877 emitcode ("inc", "b");
6878 freeAsmop (right, NULL, ic, TRUE);
6879 aopOp (left, ic, FALSE, FALSE);
6880 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6882 /* now move the left to the result if they are not the
6884 if (!sameRegs (AOP (left), AOP (result)) &&
6885 AOP_SIZE (result) > 1)
6888 size = AOP_SIZE (result);
6890 _startLazyDPSEvaluation ();
6893 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6894 if (*l == '@' && (IS_AOP_PREG (result)))
6897 emitcode ("mov", "a,%s", l);
6898 aopPut (AOP (result), "a", offset);
6901 aopPut (AOP (result), l, offset);
6904 _endLazyDPSEvaluation ();
6907 tlbl = newiTempLabel (NULL);
6908 size = AOP_SIZE (result);
6910 tlbl1 = newiTempLabel (NULL);
6912 /* if it is only one byte then */
6915 symbol *tlbl1 = newiTempLabel (NULL);
6917 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6919 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6920 emitcode ("", "%05d$:", tlbl->key + 100);
6921 emitcode ("add", "a,acc");
6922 emitcode ("", "%05d$:", tlbl1->key + 100);
6923 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6924 aopPut (AOP (result), "a", 0);
6928 reAdjustPreg (AOP (result));
6930 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6931 emitcode ("", "%05d$:", tlbl->key + 100);
6932 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6934 emitcode ("add", "a,acc");
6935 aopPut (AOP (result), "a", offset++);
6936 _startLazyDPSEvaluation ();
6939 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6941 emitcode ("rlc", "a");
6942 aopPut (AOP (result), "a", offset++);
6944 _endLazyDPSEvaluation ();
6945 reAdjustPreg (AOP (result));
6947 emitcode ("", "%05d$:", tlbl1->key + 100);
6948 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6950 freeAsmop (left, NULL, ic, TRUE);
6951 freeAsmop (result, NULL, ic, TRUE);
6956 /*-----------------------------------------------------------------*/
6957 /* genrshOne - right shift a one byte quantity by known count */
6958 /*-----------------------------------------------------------------*/
6960 genrshOne (operand * result, operand * left,
6961 int shCount, int sign)
6963 D (emitcode (";", "genrshOne");
6965 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6971 /*-----------------------------------------------------------------*/
6972 /* genrshTwo - right shift two bytes by known amount != 0 */
6973 /*-----------------------------------------------------------------*/
6975 genrshTwo (operand * result, operand * left,
6976 int shCount, int sign)
6978 D (emitcode (";", "genrshTwo");
6981 /* if shCount >= 8 */
6986 shiftR1Left2Result (left, MSB16, result, LSB,
6989 movLeft2Result (left, MSB16, result, LSB, sign);
6990 addSign (result, MSB16, sign);
6993 /* 1 <= shCount <= 7 */
6995 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7001 /*-----------------------------------------------------------------*/
7002 /* shiftRLong - shift right one long from left to result */
7003 /* offl = LSB or MSB16 */
7004 /*-----------------------------------------------------------------*/
7006 shiftRLong (operand * left, int offl,
7007 operand * result, int sign)
7010 emitcode ("clr", "c");
7011 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7013 emitcode ("mov", "c,acc.7");
7014 emitcode ("rrc", "a");
7015 aopPut (AOP (result), "a", MSB32 - offl);
7017 /* add sign of "a" */
7018 addSign (result, MSB32, sign);
7020 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7021 emitcode ("rrc", "a");
7022 aopPut (AOP (result), "a", MSB24 - offl);
7024 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7025 emitcode ("rrc", "a");
7026 aopPut (AOP (result), "a", MSB16 - offl);
7030 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7031 emitcode ("rrc", "a");
7032 aopPut (AOP (result), "a", LSB);
7039 /*-----------------------------------------------------------------*/
7040 /* genrshFour - shift four byte by a known amount != 0 */
7041 /*-----------------------------------------------------------------*/
7043 genrshFour (operand * result, operand * left,
7044 int shCount, int sign)
7046 D (emitcode (";", "genrshFour");
7049 /* if shifting more that 3 bytes */
7054 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7056 movLeft2Result (left, MSB32, result, LSB, sign);
7057 addSign (result, MSB16, sign);
7059 else if (shCount >= 16)
7063 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7066 movLeft2Result (left, MSB24, result, LSB, 0);
7067 movLeft2Result (left, MSB32, result, MSB16, sign);
7069 addSign (result, MSB24, sign);
7071 else if (shCount >= 8)
7075 shiftRLong (left, MSB16, result, sign);
7076 else if (shCount == 0)
7078 movLeft2Result (left, MSB16, result, LSB, 0);
7079 movLeft2Result (left, MSB24, result, MSB16, 0);
7080 movLeft2Result (left, MSB32, result, MSB24, sign);
7081 addSign (result, MSB32, sign);
7085 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7086 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7087 /* the last shift is signed */
7088 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7089 addSign (result, MSB32, sign);
7093 { /* 1 <= shCount <= 7 */
7096 shiftRLong (left, LSB, result, sign);
7098 shiftRLong (result, LSB, result, sign);
7102 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7103 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7104 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7112 /*-----------------------------------------------------------------*/
7113 /* genRightShiftLiteral - right shifting by known count */
7114 /*-----------------------------------------------------------------*/
7116 genRightShiftLiteral (operand * left,
7122 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7125 D (emitcode (";", "genRightShiftLiteral");
7128 freeAsmop (right, NULL, ic, TRUE);
7130 aopOp (left, ic, FALSE, FALSE);
7131 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7134 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7138 size = getDataSize (left);
7139 /* test the LEFT size !!! */
7141 /* I suppose that the left size >= result size */
7144 size = getDataSize (result);
7146 movLeft2Result (left, size, result, size, 0);
7149 else if (shCount >= (size * 8))
7152 /* get sign in acc.7 */
7153 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7154 addSign (result, LSB, sign);
7161 genrshOne (result, left, shCount, sign);
7165 genrshTwo (result, left, shCount, sign);
7169 genrshFour (result, left, shCount, sign);
7175 freeAsmop (left, NULL, ic, TRUE);
7176 freeAsmop (result, NULL, ic, TRUE);
7181 /*-----------------------------------------------------------------*/
7182 /* genSignedRightShift - right shift of signed number */
7183 /*-----------------------------------------------------------------*/
7185 genSignedRightShift (iCode * ic)
7187 operand *right, *left, *result;
7190 symbol *tlbl, *tlbl1;
7192 D (emitcode (";", "genSignedRightShift ");
7195 /* we do it the hard way put the shift count in b
7196 and loop thru preserving the sign */
7198 right = IC_RIGHT (ic);
7199 left = IC_LEFT (ic);
7200 result = IC_RESULT (ic);
7202 aopOp (right, ic, FALSE, FALSE);
7205 if (AOP_TYPE (right) == AOP_LIT)
7207 genRightShiftLiteral (left, right, result, ic, 1);
7211 /* shift count is unknown then we have to form
7212 a loop get the loop count in B : Note: we take
7213 only the lower order byte since shifting
7214 more that 32 bits make no sense anyway, ( the
7215 largest size of an object can be only 32 bits ) */
7217 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7218 emitcode ("inc", "b");
7219 freeAsmop (right, NULL, ic, TRUE);
7220 aopOp (left, ic, FALSE, FALSE);
7221 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7223 /* now move the left to the result if they are not the
7225 if (!sameRegs (AOP (left), AOP (result)) &&
7226 AOP_SIZE (result) > 1)
7229 size = AOP_SIZE (result);
7231 _startLazyDPSEvaluation ();
7234 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7235 if (*l == '@' && IS_AOP_PREG (result))
7238 emitcode ("mov", "a,%s", l);
7239 aopPut (AOP (result), "a", offset);
7242 aopPut (AOP (result), l, offset);
7245 _endLazyDPSEvaluation ();
7248 /* mov the highest order bit to OVR */
7249 tlbl = newiTempLabel (NULL);
7250 tlbl1 = newiTempLabel (NULL);
7252 size = AOP_SIZE (result);
7254 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7255 emitcode ("rlc", "a");
7256 emitcode ("mov", "ov,c");
7257 /* if it is only one byte then */
7260 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7262 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7263 emitcode ("", "%05d$:", tlbl->key + 100);
7264 emitcode ("mov", "c,ov");
7265 emitcode ("rrc", "a");
7266 emitcode ("", "%05d$:", tlbl1->key + 100);
7267 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7268 aopPut (AOP (result), "a", 0);
7272 reAdjustPreg (AOP (result));
7273 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7274 emitcode ("", "%05d$:", tlbl->key + 100);
7275 emitcode ("mov", "c,ov");
7276 _startLazyDPSEvaluation ();
7279 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7281 emitcode ("rrc", "a");
7282 aopPut (AOP (result), "a", offset--);
7284 _endLazyDPSEvaluation ();
7285 reAdjustPreg (AOP (result));
7286 emitcode ("", "%05d$:", tlbl1->key + 100);
7287 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7290 freeAsmop (left, NULL, ic, TRUE);
7291 freeAsmop (result, NULL, ic, TRUE);
7294 /*-----------------------------------------------------------------*/
7295 /* genRightShift - generate code for right shifting */
7296 /*-----------------------------------------------------------------*/
7298 genRightShift (iCode * ic)
7300 operand *right, *left, *result;
7304 symbol *tlbl, *tlbl1;
7306 D (emitcode (";", "genRightShift ");
7309 /* if signed then we do it the hard way preserve the
7310 sign bit moving it inwards */
7311 retype = getSpec (operandType (IC_RESULT (ic)));
7313 if (!SPEC_USIGN (retype))
7315 genSignedRightShift (ic);
7319 /* signed & unsigned types are treated the same : i.e. the
7320 signed is NOT propagated inwards : quoting from the
7321 ANSI - standard : "for E1 >> E2, is equivalent to division
7322 by 2**E2 if unsigned or if it has a non-negative value,
7323 otherwise the result is implementation defined ", MY definition
7324 is that the sign does not get propagated */
7326 right = IC_RIGHT (ic);
7327 left = IC_LEFT (ic);
7328 result = IC_RESULT (ic);
7330 aopOp (right, ic, FALSE, FALSE);
7333 /* if the shift count is known then do it
7334 as efficiently as possible */
7335 if (AOP_TYPE (right) == AOP_LIT)
7337 genRightShiftLiteral (left, right, result, ic, 0);
7342 /* shift count is unknown then we have to form
7343 a loop get the loop count in B : Note: we take
7344 only the lower order byte since shifting
7345 more that 32 bits make no sense anyway, ( the
7346 largest size of an object can be only 32 bits ) */
7348 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7349 emitcode ("inc", "b");
7350 freeAsmop (right, NULL, ic, TRUE);
7351 aopOp (left, ic, FALSE, FALSE);
7352 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7354 /* now move the left to the result if they are not the
7356 if (!sameRegs (AOP (left), AOP (result)) &&
7357 AOP_SIZE (result) > 1)
7360 size = AOP_SIZE (result);
7362 _startLazyDPSEvaluation ();
7365 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7366 if (*l == '@' && IS_AOP_PREG (result))
7369 emitcode ("mov", "a,%s", l);
7370 aopPut (AOP (result), "a", offset);
7373 aopPut (AOP (result), l, offset);
7376 _endLazyDPSEvaluation ();
7379 tlbl = newiTempLabel (NULL);
7380 tlbl1 = newiTempLabel (NULL);
7381 size = AOP_SIZE (result);
7384 /* if it is only one byte then */
7387 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7389 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7390 emitcode ("", "%05d$:", tlbl->key + 100);
7392 emitcode ("rrc", "a");
7393 emitcode ("", "%05d$:", tlbl1->key + 100);
7394 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7395 aopPut (AOP (result), "a", 0);
7399 reAdjustPreg (AOP (result));
7400 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7401 emitcode ("", "%05d$:", tlbl->key + 100);
7403 _startLazyDPSEvaluation ();
7406 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7408 emitcode ("rrc", "a");
7409 aopPut (AOP (result), "a", offset--);
7411 _endLazyDPSEvaluation ();
7412 reAdjustPreg (AOP (result));
7414 emitcode ("", "%05d$:", tlbl1->key + 100);
7415 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7418 freeAsmop (left, NULL, ic, TRUE);
7419 freeAsmop (result, NULL, ic, TRUE);
7422 /*-----------------------------------------------------------------*/
7423 /* genUnpackBits - generates code for unpacking bits */
7424 /*-----------------------------------------------------------------*/
7426 genUnpackBits (operand * result, char *rname, int ptype)
7433 D (emitcode (";", "genUnpackBits ");
7436 etype = getSpec (operandType (result));
7438 /* read the first byte */
7444 emitcode ("mov", "a,@%s", rname);
7448 emitcode ("movx", "a,@%s", rname);
7452 emitcode ("movx", "a,@dptr");
7456 emitcode ("clr", "a");
7457 emitcode ("movc", "a", "@a+dptr");
7461 emitcode ("lcall", "__gptrget");
7465 /* if we have bitdisplacement then it fits */
7466 /* into this byte completely or if length is */
7467 /* less than a byte */
7468 if ((shCnt = SPEC_BSTR (etype)) ||
7469 (SPEC_BLEN (etype) <= 8))
7472 /* shift right acc */
7475 emitcode ("anl", "a,#0x%02x",
7476 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7477 aopPut (AOP (result), "a", offset);
7481 /* bit field did not fit in a byte */
7482 rlen = SPEC_BLEN (etype) - 8;
7483 aopPut (AOP (result), "a", offset++);
7492 emitcode ("inc", "%s", rname);
7493 emitcode ("mov", "a,@%s", rname);
7497 emitcode ("inc", "%s", rname);
7498 emitcode ("movx", "a,@%s", rname);
7502 emitcode ("inc", "dptr");
7503 emitcode ("movx", "a,@dptr");
7507 emitcode ("clr", "a");
7508 emitcode ("inc", "dptr");
7509 emitcode ("movc", "a", "@a+dptr");
7513 emitcode ("inc", "dptr");
7514 emitcode ("lcall", "__gptrget");
7519 /* if we are done */
7523 aopPut (AOP (result), "a", offset++);
7529 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7530 aopPut (AOP (result), "a", offset);
7537 /*-----------------------------------------------------------------*/
7538 /* genDataPointerGet - generates code when ptr offset is known */
7539 /*-----------------------------------------------------------------*/
7541 genDataPointerGet (operand * left,
7547 int size, offset = 0;
7548 aopOp (result, ic, TRUE, FALSE);
7550 /* get the string representation of the name */
7551 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7552 size = AOP_SIZE (result);
7553 _startLazyDPSEvaluation ();
7557 sprintf (buffer, "(%s + %d)", l + 1, offset);
7559 sprintf (buffer, "%s", l + 1);
7560 aopPut (AOP (result), buffer, offset++);
7562 _endLazyDPSEvaluation ();
7564 freeAsmop (left, NULL, ic, TRUE);
7565 freeAsmop (result, NULL, ic, TRUE);
7568 /*-----------------------------------------------------------------*/
7569 /* genNearPointerGet - emitcode for near pointer fetch */
7570 /*-----------------------------------------------------------------*/
7572 genNearPointerGet (operand * left,
7579 sym_link *rtype, *retype, *letype;
7580 sym_link *ltype = operandType (left);
7583 rtype = operandType (result);
7584 retype = getSpec (rtype);
7585 letype = getSpec (ltype);
7587 aopOp (left, ic, FALSE, FALSE);
7589 /* if left is rematerialisable and
7590 result is not bit variable type and
7591 the left is pointer to data space i.e
7592 lower 128 bytes of space */
7593 if (AOP_TYPE (left) == AOP_IMMD &&
7594 !IS_BITVAR (retype) &&
7595 !IS_BITVAR (letype) &&
7596 DCL_TYPE (ltype) == POINTER)
7598 genDataPointerGet (left, result, ic);
7602 /* if the value is already in a pointer register
7603 then don't need anything more */
7604 if (!AOP_INPREG (AOP (left)))
7606 /* otherwise get a free pointer register */
7608 preg = getFreePtr (ic, &aop, FALSE);
7609 emitcode ("mov", "%s,%s",
7611 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7615 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7617 freeAsmop (left, NULL, ic, TRUE);
7618 aopOp (result, ic, FALSE, FALSE);
7620 /* if bitfield then unpack the bits */
7621 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7622 genUnpackBits (result, rname, POINTER);
7625 /* we have can just get the values */
7626 int size = AOP_SIZE (result);
7631 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7634 emitcode ("mov", "a,@%s", rname);
7635 aopPut (AOP (result), "a", offset);
7639 sprintf (buffer, "@%s", rname);
7640 aopPut (AOP (result), buffer, offset);
7644 emitcode ("inc", "%s", rname);
7648 /* now some housekeeping stuff */
7651 /* we had to allocate for this iCode */
7652 freeAsmop (NULL, aop, ic, TRUE);
7656 /* we did not allocate which means left
7657 already in a pointer register, then
7658 if size > 0 && this could be used again
7659 we have to point it back to where it
7661 if (AOP_SIZE (result) > 1 &&
7662 !OP_SYMBOL (left)->remat &&
7663 (OP_SYMBOL (left)->liveTo > ic->seq ||
7666 int size = AOP_SIZE (result) - 1;
7668 emitcode ("dec", "%s", rname);
7673 freeAsmop (result, NULL, ic, TRUE);
7677 /*-----------------------------------------------------------------*/
7678 /* genPagedPointerGet - emitcode for paged pointer fetch */
7679 /*-----------------------------------------------------------------*/
7681 genPagedPointerGet (operand * left,
7688 sym_link *rtype, *retype, *letype;
7690 rtype = operandType (result);
7691 retype = getSpec (rtype);
7692 letype = getSpec (operandType (left));
7693 aopOp (left, ic, FALSE, FALSE);
7695 /* if the value is already in a pointer register
7696 then don't need anything more */
7697 if (!AOP_INPREG (AOP (left)))
7699 /* otherwise get a free pointer register */
7701 preg = getFreePtr (ic, &aop, FALSE);
7702 emitcode ("mov", "%s,%s",
7704 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7708 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7710 freeAsmop (left, NULL, ic, TRUE);
7711 aopOp (result, ic, FALSE, FALSE);
7713 /* if bitfield then unpack the bits */
7714 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7715 genUnpackBits (result, rname, PPOINTER);
7718 /* we have can just get the values */
7719 int size = AOP_SIZE (result);
7725 emitcode ("movx", "a,@%s", rname);
7726 aopPut (AOP (result), "a", offset);
7731 emitcode ("inc", "%s", rname);
7735 /* now some housekeeping stuff */
7738 /* we had to allocate for this iCode */
7739 freeAsmop (NULL, aop, ic, TRUE);
7743 /* we did not allocate which means left
7744 already in a pointer register, then
7745 if size > 0 && this could be used again
7746 we have to point it back to where it
7748 if (AOP_SIZE (result) > 1 &&
7749 !OP_SYMBOL (left)->remat &&
7750 (OP_SYMBOL (left)->liveTo > ic->seq ||
7753 int size = AOP_SIZE (result) - 1;
7755 emitcode ("dec", "%s", rname);
7760 freeAsmop (result, NULL, ic, TRUE);
7765 /*-----------------------------------------------------------------*/
7766 /* genFarPointerGet - gget value from far space */
7767 /*-----------------------------------------------------------------*/
7769 genFarPointerGet (operand * left,
7770 operand * result, iCode * ic)
7773 sym_link *retype = getSpec (operandType (result));
7774 sym_link *letype = getSpec (operandType (left));
7775 D (emitcode (";", "genFarPointerGet");
7778 aopOp (left, ic, FALSE, FALSE);
7780 /* if the operand is already in dptr
7781 then we do nothing else we move the value to dptr */
7782 if (AOP_TYPE (left) != AOP_STR)
7784 /* if this is remateriazable */
7785 if (AOP_TYPE (left) == AOP_IMMD)
7787 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7791 /* we need to get it byte by byte */
7792 _startLazyDPSEvaluation ();
7793 if (AOP_TYPE (left) != AOP_DPTR)
7795 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7796 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7797 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7801 /* We need to generate a load to DPTR indirect through DPTR. */
7802 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7804 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7805 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7806 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7807 emitcode ("pop", "dph");
7808 emitcode ("pop", "dpl");
7810 _endLazyDPSEvaluation ();
7813 /* so dptr know contains the address */
7814 freeAsmop (left, NULL, ic, TRUE);
7815 aopOp (result, ic, FALSE, TRUE);
7817 /* if bit then unpack */
7818 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7819 genUnpackBits (result, "dptr", FPOINTER);
7822 size = AOP_SIZE (result);
7825 _startLazyDPSEvaluation ();
7832 emitcode ("movx", "a,@dptr");
7834 emitcode ("inc", "dptr");
7836 aopPut (AOP (result), "a", offset++);
7838 _endLazyDPSEvaluation ();
7841 freeAsmop (result, NULL, ic, TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* emitcodePointerGet - gget value from code space */
7846 /*-----------------------------------------------------------------*/
7848 emitcodePointerGet (operand * left,
7849 operand * result, iCode * ic)
7852 sym_link *retype = getSpec (operandType (result));
7854 aopOp (left, ic, FALSE, FALSE);
7856 /* if the operand is already in dptr
7857 then we do nothing else we move the value to dptr */
7858 if (AOP_TYPE (left) != AOP_STR)
7860 /* if this is remateriazable */
7861 if (AOP_TYPE (left) == AOP_IMMD)
7863 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7866 { /* we need to get it byte by byte */
7867 _startLazyDPSEvaluation ();
7868 if (AOP_TYPE (left) != AOP_DPTR)
7870 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7871 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7872 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7876 /* We need to generate a load to DPTR indirect through DPTR. */
7877 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7879 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7880 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7881 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7882 emitcode ("pop", "dph");
7883 emitcode ("pop", "dpl");
7885 _endLazyDPSEvaluation ();
7888 /* so dptr know contains the address */
7889 freeAsmop (left, NULL, ic, TRUE);
7890 aopOp (result, ic, FALSE, TRUE);
7892 /* if bit then unpack */
7893 if (IS_BITVAR (retype))
7894 genUnpackBits (result, "dptr", CPOINTER);
7897 size = AOP_SIZE (result);
7900 _startLazyDPSEvaluation ();
7906 emitcode ("clr", "a");
7907 emitcode ("movc", "a,@a+dptr");
7909 emitcode ("inc", "dptr");
7910 aopPut (AOP (result), "a", offset++);
7912 _endLazyDPSEvaluation ();
7915 freeAsmop (result, NULL, ic, TRUE);
7918 /*-----------------------------------------------------------------*/
7919 /* genGenPointerGet - gget value from generic pointer space */
7920 /*-----------------------------------------------------------------*/
7922 genGenPointerGet (operand * left,
7923 operand * result, iCode * ic)
7926 sym_link *retype = getSpec (operandType (result));
7927 sym_link *letype = getSpec (operandType (left));
7929 D (emitcode (";", "genGenPointerGet "); );
7931 aopOp (left, ic, FALSE, TRUE);
7933 /* if the operand is already in dptr
7934 then we do nothing else we move the value to dptr */
7935 if (AOP_TYPE (left) != AOP_STR)
7937 /* if this is remateriazable */
7938 if (AOP_TYPE (left) == AOP_IMMD)
7940 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7941 emitcode ("mov", "b,#%d", pointerCode (retype));
7944 { /* we need to get it byte by byte */
7945 _startLazyDPSEvaluation ();
7946 if (AOP(left)->type==AOP_DPTR2) {
7948 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7951 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7952 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7955 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7956 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7959 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7960 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7962 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7963 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7964 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7965 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7967 _endLazyDPSEvaluation ();
7970 /* so dptr know contains the address */
7971 freeAsmop (left, NULL, ic, TRUE);
7972 aopOp (result, ic, FALSE, TRUE);
7974 /* if bit then unpack */
7975 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7976 genUnpackBits (result, "dptr", GPOINTER);
7979 size = AOP_SIZE (result);
7984 emitcode ("lcall", "__gptrget");
7985 aopPut (AOP (result), "a", offset++);
7987 emitcode ("inc", "dptr");
7991 freeAsmop (result, NULL, ic, TRUE);
7994 /*-----------------------------------------------------------------*/
7995 /* genPointerGet - generate code for pointer get */
7996 /*-----------------------------------------------------------------*/
7998 genPointerGet (iCode * ic)
8000 operand *left, *result;
8001 sym_link *type, *etype;
8004 D (emitcode (";", "genPointerGet ");
8007 left = IC_LEFT (ic);
8008 result = IC_RESULT (ic);
8010 /* depending on the type of pointer we need to
8011 move it to the correct pointer register */
8012 type = operandType (left);
8013 etype = getSpec (type);
8014 /* if left is of type of pointer then it is simple */
8015 if (IS_PTR (type) && !IS_FUNC (type->next))
8016 p_type = DCL_TYPE (type);
8019 /* we have to go by the storage class */
8020 p_type = PTR_TYPE (SPEC_OCLS (etype));
8023 /* now that we have the pointer type we assign
8024 the pointer values */
8030 genNearPointerGet (left, result, ic);
8034 genPagedPointerGet (left, result, ic);
8038 genFarPointerGet (left, result, ic);
8042 emitcodePointerGet (left, result, ic);
8046 genGenPointerGet (left, result, ic);
8052 /*-----------------------------------------------------------------*/
8053 /* genPackBits - generates code for packed bit storage */
8054 /*-----------------------------------------------------------------*/
8056 genPackBits (sym_link * etype,
8058 char *rname, int p_type)
8066 blen = SPEC_BLEN (etype);
8067 bstr = SPEC_BSTR (etype);
8069 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8072 /* if the bit lenth is less than or */
8073 /* it exactly fits a byte then */
8074 if (SPEC_BLEN (etype) <= 8)
8076 shCount = SPEC_BSTR (etype);
8078 /* shift left acc */
8081 if (SPEC_BLEN (etype) < 8)
8082 { /* if smaller than a byte */
8088 emitcode ("mov", "b,a");
8089 emitcode ("mov", "a,@%s", rname);
8093 emitcode ("mov", "b,a");
8094 emitcode ("movx", "a,@dptr");
8098 emitcode ("push", "b");
8099 emitcode ("push", "acc");
8100 emitcode ("lcall", "__gptrget");
8101 emitcode ("pop", "b");
8105 emitcode ("anl", "a,#0x%02x", (unsigned char)
8106 ((unsigned char) (0xFF << (blen + bstr)) |
8107 (unsigned char) (0xFF >> (8 - bstr))));
8108 emitcode ("orl", "a,b");
8109 if (p_type == GPOINTER)
8110 emitcode ("pop", "b");
8117 emitcode ("mov", "@%s,a", rname);
8121 emitcode ("movx", "@dptr,a");
8125 emitcode ("lcall", "__gptrput");
8130 if (SPEC_BLEN (etype) <= 8)
8133 emitcode ("inc", "%s", rname);
8134 rLen = SPEC_BLEN (etype);
8136 /* now generate for lengths greater than one byte */
8140 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8152 emitcode ("mov", "@%s,a", rname);
8155 emitcode ("mov", "@%s,%s", rname, l);
8160 emitcode ("movx", "@dptr,a");
8165 emitcode ("lcall", "__gptrput");
8168 emitcode ("inc", "%s", rname);
8173 /* last last was not complete */
8176 /* save the byte & read byte */
8180 emitcode ("mov", "b,a");
8181 emitcode ("mov", "a,@%s", rname);
8185 emitcode ("mov", "b,a");
8186 emitcode ("movx", "a,@dptr");
8190 emitcode ("push", "b");
8191 emitcode ("push", "acc");
8192 emitcode ("lcall", "__gptrget");
8193 emitcode ("pop", "b");
8197 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8198 emitcode ("orl", "a,b");
8201 if (p_type == GPOINTER)
8202 emitcode ("pop", "b");
8208 emitcode ("mov", "@%s,a", rname);
8212 emitcode ("movx", "@dptr,a");
8216 emitcode ("lcall", "__gptrput");
8220 /*-----------------------------------------------------------------*/
8221 /* genDataPointerSet - remat pointer to data space */
8222 /*-----------------------------------------------------------------*/
8224 genDataPointerSet (operand * right,
8228 int size, offset = 0;
8229 char *l, buffer[256];
8231 aopOp (right, ic, FALSE, FALSE);
8233 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8234 size = AOP_SIZE (right);
8238 sprintf (buffer, "(%s + %d)", l + 1, offset);
8240 sprintf (buffer, "%s", l + 1);
8241 emitcode ("mov", "%s,%s", buffer,
8242 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8245 freeAsmop (right, NULL, ic, TRUE);
8246 freeAsmop (result, NULL, ic, TRUE);
8249 /*-----------------------------------------------------------------*/
8250 /* genNearPointerSet - emitcode for near pointer put */
8251 /*-----------------------------------------------------------------*/
8253 genNearPointerSet (operand * right,
8260 sym_link *retype, *letype;
8261 sym_link *ptype = operandType (result);
8263 retype = getSpec (operandType (right));
8264 letype = getSpec (ptype);
8266 aopOp (result, ic, FALSE, FALSE);
8268 /* if the result is rematerializable &
8269 in data space & not a bit variable */
8270 if (AOP_TYPE (result) == AOP_IMMD &&
8271 DCL_TYPE (ptype) == POINTER &&
8272 !IS_BITVAR (retype) &&
8273 !IS_BITVAR (letype))
8275 genDataPointerSet (right, result, ic);
8279 /* if the value is already in a pointer register
8280 then don't need anything more */
8281 if (!AOP_INPREG (AOP (result)))
8283 /* otherwise get a free pointer register */
8285 preg = getFreePtr (ic, &aop, FALSE);
8286 emitcode ("mov", "%s,%s",
8288 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8292 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8294 freeAsmop (result, NULL, ic, TRUE);
8295 aopOp (right, ic, FALSE, FALSE);
8297 /* if bitfield then unpack the bits */
8298 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8299 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8302 /* we have can just get the values */
8303 int size = AOP_SIZE (right);
8308 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8312 emitcode ("mov", "@%s,a", rname);
8315 emitcode ("mov", "@%s,%s", rname, l);
8317 emitcode ("inc", "%s", rname);
8322 /* now some housekeeping stuff */
8325 /* we had to allocate for this iCode */
8326 freeAsmop (NULL, aop, ic, TRUE);
8330 /* we did not allocate which means left
8331 already in a pointer register, then
8332 if size > 0 && this could be used again
8333 we have to point it back to where it
8335 if (AOP_SIZE (right) > 1 &&
8336 !OP_SYMBOL (result)->remat &&
8337 (OP_SYMBOL (result)->liveTo > ic->seq ||
8340 int size = AOP_SIZE (right) - 1;
8342 emitcode ("dec", "%s", rname);
8347 freeAsmop (right, NULL, ic, TRUE);
8352 /*-----------------------------------------------------------------*/
8353 /* genPagedPointerSet - emitcode for Paged pointer put */
8354 /*-----------------------------------------------------------------*/
8356 genPagedPointerSet (operand * right,
8363 sym_link *retype, *letype;
8365 retype = getSpec (operandType (right));
8366 letype = getSpec (operandType (result));
8368 aopOp (result, ic, FALSE, FALSE);
8370 /* if the value is already in a pointer register
8371 then don't need anything more */
8372 if (!AOP_INPREG (AOP (result)))
8374 /* otherwise get a free pointer register */
8376 preg = getFreePtr (ic, &aop, FALSE);
8377 emitcode ("mov", "%s,%s",
8379 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8383 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8385 freeAsmop (result, NULL, ic, TRUE);
8386 aopOp (right, ic, FALSE, FALSE);
8388 /* if bitfield then unpack the bits */
8389 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8390 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8393 /* we have can just get the values */
8394 int size = AOP_SIZE (right);
8399 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8402 emitcode ("movx", "@%s,a", rname);
8405 emitcode ("inc", "%s", rname);
8411 /* now some housekeeping stuff */
8414 /* we had to allocate for this iCode */
8415 freeAsmop (NULL, aop, ic, TRUE);
8419 /* we did not allocate which means left
8420 already in a pointer register, then
8421 if size > 0 && this could be used again
8422 we have to point it back to where it
8424 if (AOP_SIZE (right) > 1 &&
8425 !OP_SYMBOL (result)->remat &&
8426 (OP_SYMBOL (result)->liveTo > ic->seq ||
8429 int size = AOP_SIZE (right) - 1;
8431 emitcode ("dec", "%s", rname);
8436 freeAsmop (right, NULL, ic, TRUE);
8441 /*-----------------------------------------------------------------*/
8442 /* genFarPointerSet - set value from far space */
8443 /*-----------------------------------------------------------------*/
8445 genFarPointerSet (operand * right,
8446 operand * result, iCode * ic)
8449 sym_link *retype = getSpec (operandType (right));
8450 sym_link *letype = getSpec (operandType (result));
8452 aopOp (result, ic, FALSE, FALSE);
8454 /* if the operand is already in dptr
8455 then we do nothing else we move the value to dptr */
8456 if (AOP_TYPE (result) != AOP_STR)
8458 /* if this is remateriazable */
8459 if (AOP_TYPE (result) == AOP_IMMD)
8460 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8463 /* we need to get it byte by byte */
8464 _startLazyDPSEvaluation ();
8465 if (AOP_TYPE (result) != AOP_DPTR)
8467 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8468 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8469 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8473 /* We need to generate a load to DPTR indirect through DPTR. */
8474 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8476 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8477 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8478 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8479 emitcode ("pop", "dph");
8480 emitcode ("pop", "dpl");
8482 _endLazyDPSEvaluation ();
8485 /* so dptr know contains the address */
8486 freeAsmop (result, NULL, ic, TRUE);
8487 aopOp (right, ic, FALSE, TRUE);
8489 /* if bit then unpack */
8490 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8491 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8494 size = AOP_SIZE (right);
8497 _startLazyDPSEvaluation ();
8500 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8506 emitcode ("movx", "@dptr,a");
8508 emitcode ("inc", "dptr");
8510 _endLazyDPSEvaluation ();
8513 freeAsmop (right, NULL, ic, TRUE);
8516 /*-----------------------------------------------------------------*/
8517 /* genGenPointerSet - set value from generic pointer space */
8518 /*-----------------------------------------------------------------*/
8520 genGenPointerSet (operand * right,
8521 operand * result, iCode * ic)
8524 sym_link *retype = getSpec (operandType (right));
8525 sym_link *letype = getSpec (operandType (result));
8527 aopOp (result, ic, FALSE, TRUE);
8529 /* if the operand is already in dptr
8530 then we do nothing else we move the value to dptr */
8531 if (AOP_TYPE (result) != AOP_STR)
8533 _startLazyDPSEvaluation ();
8534 /* if this is remateriazable */
8535 if (AOP_TYPE (result) == AOP_IMMD)
8537 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8538 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8541 { /* we need to get it byte by byte */
8542 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8543 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8544 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8545 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8547 _endLazyDPSEvaluation ();
8549 /* so dptr know contains the address */
8550 freeAsmop (result, NULL, ic, TRUE);
8551 aopOp (right, ic, FALSE, TRUE);
8553 /* if bit then unpack */
8554 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8555 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8558 size = AOP_SIZE (right);
8561 _startLazyDPSEvaluation ();
8564 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8570 emitcode ("lcall", "__gptrput");
8572 emitcode ("inc", "dptr");
8574 _endLazyDPSEvaluation ();
8577 freeAsmop (right, NULL, ic, TRUE);
8580 /*-----------------------------------------------------------------*/
8581 /* genPointerSet - stores the value into a pointer location */
8582 /*-----------------------------------------------------------------*/
8584 genPointerSet (iCode * ic)
8586 operand *right, *result;
8587 sym_link *type, *etype;
8590 D (emitcode (";", "genPointerSet ");
8593 right = IC_RIGHT (ic);
8594 result = IC_RESULT (ic);
8596 /* depending on the type of pointer we need to
8597 move it to the correct pointer register */
8598 type = operandType (result);
8599 etype = getSpec (type);
8600 /* if left is of type of pointer then it is simple */
8601 if (IS_PTR (type) && !IS_FUNC (type->next))
8603 p_type = DCL_TYPE (type);
8607 /* we have to go by the storage class */
8608 p_type = PTR_TYPE (SPEC_OCLS (etype));
8611 /* now that we have the pointer type we assign
8612 the pointer values */
8618 genNearPointerSet (right, result, ic);
8622 genPagedPointerSet (right, result, ic);
8626 genFarPointerSet (right, result, ic);
8630 genGenPointerSet (right, result, ic);
8636 /*-----------------------------------------------------------------*/
8637 /* genIfx - generate code for Ifx statement */
8638 /*-----------------------------------------------------------------*/
8640 genIfx (iCode * ic, iCode * popIc)
8642 operand *cond = IC_COND (ic);
8645 D (emitcode (";", "genIfx ");
8648 aopOp (cond, ic, FALSE, FALSE);
8650 /* get the value into acc */
8651 if (AOP_TYPE (cond) != AOP_CRY)
8655 /* the result is now in the accumulator */
8656 freeAsmop (cond, NULL, ic, TRUE);
8658 /* if there was something to be popped then do it */
8662 /* if the condition is a bit variable */
8663 if (isbit && IS_ITEMP (cond) &&
8665 genIfxJump (ic, SPIL_LOC (cond)->rname);
8666 else if (isbit && !IS_ITEMP (cond))
8667 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8669 genIfxJump (ic, "a");
8674 /*-----------------------------------------------------------------*/
8675 /* genAddrOf - generates code for address of */
8676 /*-----------------------------------------------------------------*/
8678 genAddrOf (iCode * ic)
8680 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8683 D (emitcode (";", "genAddrOf ");
8686 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8688 /* if the operand is on the stack then we
8689 need to get the stack offset of this
8693 /* if it has an offset then we need to compute
8697 emitcode ("mov", "a,_bp");
8698 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8699 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8703 /* we can just move _bp */
8704 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8706 /* fill the result with zero */
8707 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8710 if (options.stack10bit && size < (FPTRSIZE - 1))
8713 "*** warning: pointer to stack var truncated.\n");
8720 if (options.stack10bit && offset == 2)
8722 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8726 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8733 /* object not on stack then we need the name */
8734 size = AOP_SIZE (IC_RESULT (ic));
8739 char s[SDCC_NAME_MAX];
8741 sprintf (s, "#(%s >> %d)",
8745 sprintf (s, "#%s", sym->rname);
8746 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8750 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8754 /*-----------------------------------------------------------------*/
8755 /* genFarFarAssign - assignment when both are in far space */
8756 /*-----------------------------------------------------------------*/
8758 genFarFarAssign (operand * result, operand * right, iCode * ic)
8760 int size = AOP_SIZE (right);
8766 /* This is a net loss for size == 1, but a big gain
8769 D (emitcode (";", "genFarFarAssign (improved)");
8772 aopOp (result, ic, TRUE, TRUE);
8774 _startLazyDPSEvaluation ();
8777 aopPut (AOP (result),
8778 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8781 _endLazyDPSEvaluation ();
8782 freeAsmop (result, NULL, ic, FALSE);
8783 freeAsmop (right, NULL, ic, FALSE);
8787 D (emitcode (";", "genFarFarAssign ");
8790 /* first push the right side on to the stack */
8791 _startLazyDPSEvaluation ();
8794 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8796 emitcode ("push", "acc");
8799 freeAsmop (right, NULL, ic, FALSE);
8800 /* now assign DPTR to result */
8801 aopOp (result, ic, FALSE, FALSE);
8802 size = AOP_SIZE (result);
8805 emitcode ("pop", "acc");
8806 aopPut (AOP (result), "a", --offset);
8808 freeAsmop (result, NULL, ic, FALSE);
8809 _endLazyDPSEvaluation ();
8813 /*-----------------------------------------------------------------*/
8814 /* genAssign - generate code for assignment */
8815 /*-----------------------------------------------------------------*/
8817 genAssign (iCode * ic)
8819 operand *result, *right;
8821 unsigned long lit = 0L;
8823 D (emitcode (";", "genAssign ");
8826 result = IC_RESULT (ic);
8827 right = IC_RIGHT (ic);
8829 /* if they are the same */
8830 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8833 aopOp (right, ic, FALSE, FALSE);
8835 emitcode (";", "genAssign: resultIsFar = %s",
8836 isOperandInFarSpace (result) ?
8839 /* special case both in far space */
8840 if ((AOP_TYPE (right) == AOP_DPTR ||
8841 AOP_TYPE (right) == AOP_DPTR2) &&
8842 /* IS_TRUE_SYMOP(result) && */
8843 isOperandInFarSpace (result))
8845 genFarFarAssign (result, right, ic);
8849 aopOp (result, ic, TRUE, FALSE);
8851 /* if they are the same registers */
8852 if (sameRegs (AOP (right), AOP (result)))
8855 /* if the result is a bit */
8856 if (AOP_TYPE (result) == AOP_CRY)
8859 /* if the right size is a literal then
8860 we know what the value is */
8861 if (AOP_TYPE (right) == AOP_LIT)
8863 if (((int) operandLitValue (right)))
8864 aopPut (AOP (result), one, 0);
8866 aopPut (AOP (result), zero, 0);
8870 /* the right is also a bit variable */
8871 if (AOP_TYPE (right) == AOP_CRY)
8873 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8874 aopPut (AOP (result), "c", 0);
8880 aopPut (AOP (result), "a", 0);
8884 /* bit variables done */
8886 size = AOP_SIZE (result);
8888 if (AOP_TYPE (right) == AOP_LIT)
8889 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8892 (AOP_TYPE (result) != AOP_REG) &&
8893 (AOP_TYPE (right) == AOP_LIT) &&
8894 !IS_FLOAT (operandType (right)))
8896 D (emitcode (";", "Kevin's better literal load code");
8898 _startLazyDPSEvaluation ();
8899 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8901 aopPut (AOP (result),
8902 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8907 /* And now fill the rest with zeros. */
8910 emitcode ("clr", "a");
8914 aopPut (AOP (result), "a", offset++);
8916 _endLazyDPSEvaluation ();
8920 _startLazyDPSEvaluation ();
8923 aopPut (AOP (result),
8924 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8928 _endLazyDPSEvaluation ();
8932 freeAsmop (right, NULL, ic, FALSE);
8933 freeAsmop (result, NULL, ic, TRUE);
8936 /*-----------------------------------------------------------------*/
8937 /* genJumpTab - generates code for jump table */
8938 /*-----------------------------------------------------------------*/
8940 genJumpTab (iCode * ic)
8945 D (emitcode (";", "genJumpTab ");
8948 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8949 /* get the condition into accumulator */
8950 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8952 /* multiply by four! */
8953 emitcode ("add", "a,acc");
8954 emitcode ("add", "a,acc");
8955 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8957 jtab = newiTempLabel (NULL);
8958 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8959 emitcode ("jmp", "@a+dptr");
8960 emitcode ("", "%05d$:", jtab->key + 100);
8961 /* now generate the jump labels */
8962 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8963 jtab = setNextItem (IC_JTLABELS (ic)))
8964 emitcode ("ljmp", "%05d$", jtab->key + 100);
8968 /*-----------------------------------------------------------------*/
8969 /* genCast - gen code for casting */
8970 /*-----------------------------------------------------------------*/
8972 genCast (iCode * ic)
8974 operand *result = IC_RESULT (ic);
8975 sym_link *ctype = operandType (IC_LEFT (ic));
8976 sym_link *rtype = operandType (IC_RIGHT (ic));
8977 operand *right = IC_RIGHT (ic);
8980 D (emitcode (";", "genCast ");
8983 /* if they are equivalent then do nothing */
8984 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8987 aopOp (right, ic, FALSE, FALSE);
8988 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8990 /* if the result is a bit */
8991 if (AOP_TYPE (result) == AOP_CRY)
8993 /* if the right size is a literal then
8994 we know what the value is */
8995 if (AOP_TYPE (right) == AOP_LIT)
8997 if (((int) operandLitValue (right)))
8998 aopPut (AOP (result), one, 0);
9000 aopPut (AOP (result), zero, 0);
9005 /* the right is also a bit variable */
9006 if (AOP_TYPE (right) == AOP_CRY)
9008 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9009 aopPut (AOP (result), "c", 0);
9015 aopPut (AOP (result), "a", 0);
9019 /* if they are the same size : or less */
9020 if (AOP_SIZE (result) <= AOP_SIZE (right))
9023 /* if they are in the same place */
9024 if (sameRegs (AOP (right), AOP (result)))
9027 /* if they in different places then copy */
9028 size = AOP_SIZE (result);
9030 _startLazyDPSEvaluation ();
9033 aopPut (AOP (result),
9034 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9038 _endLazyDPSEvaluation ();
9043 /* if the result is of type pointer */
9048 sym_link *type = operandType (right);
9050 /* pointer to generic pointer */
9051 if (IS_GENPTR (ctype))
9057 p_type = DCL_TYPE (type);
9061 #if OLD_CAST_BEHAVIOR
9062 /* KV: we are converting a non-pointer type to
9063 * a generic pointer. This (ifdef'd out) code
9064 * says that the resulting generic pointer
9065 * should have the same class as the storage
9066 * location of the non-pointer variable.
9068 * For example, converting an int (which happens
9069 * to be stored in DATA space) to a pointer results
9070 * in a DATA generic pointer; if the original int
9071 * in XDATA space, so will be the resulting pointer.
9073 * I don't like that behavior, and thus this change:
9074 * all such conversions will be forced to XDATA and
9075 * throw a warning. If you want some non-XDATA
9076 * type, or you want to suppress the warning, you
9077 * must go through an intermediate cast, like so:
9079 * char _generic *gp = (char _xdata *)(intVar);
9081 sym_link *etype = getSpec (type);
9083 /* we have to go by the storage class */
9084 if (SPEC_OCLS (etype) != generic)
9086 p_type = PTR_TYPE (SPEC_OCLS (etype));
9091 /* Converting unknown class (i.e. register variable)
9092 * to generic pointer. This is not good, but
9093 * we'll make a guess (and throw a warning).
9096 werror (W_INT_TO_GEN_PTR_CAST);
9100 /* the first two bytes are known */
9101 size = GPTRSIZE - 1;
9103 _startLazyDPSEvaluation ();
9106 aopPut (AOP (result),
9107 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9111 _endLazyDPSEvaluation ();
9113 /* the last byte depending on type */
9131 /* this should never happen */
9132 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9133 "got unknown pointer type");
9136 aopPut (AOP (result), l, GPTRSIZE - 1);
9140 /* just copy the pointers */
9141 size = AOP_SIZE (result);
9143 _startLazyDPSEvaluation ();
9146 aopPut (AOP (result),
9147 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9151 _endLazyDPSEvaluation ();
9155 /* so we now know that the size of destination is greater
9156 than the size of the source */
9157 /* we move to result for the size of source */
9158 size = AOP_SIZE (right);
9160 _startLazyDPSEvaluation ();
9163 aopPut (AOP (result),
9164 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9168 _endLazyDPSEvaluation ();
9170 /* now depending on the sign of the source && destination */
9171 size = AOP_SIZE (result) - AOP_SIZE (right);
9172 /* if unsigned or not an integral type */
9173 /* also, if the source is a bit, we don't need to sign extend, because
9174 * it can't possibly have set the sign bit.
9176 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9180 aopPut (AOP (result), zero, offset++);
9185 /* we need to extend the sign :{ */
9186 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9187 FALSE, FALSE, TRUE);
9189 emitcode ("rlc", "a");
9190 emitcode ("subb", "a,acc");
9192 aopPut (AOP (result), "a", offset++);
9195 /* we are done hurray !!!! */
9198 freeAsmop (right, NULL, ic, TRUE);
9199 freeAsmop (result, NULL, ic, TRUE);
9203 /*-----------------------------------------------------------------*/
9204 /* genDjnz - generate decrement & jump if not zero instrucion */
9205 /*-----------------------------------------------------------------*/
9207 genDjnz (iCode * ic, iCode * ifx)
9213 /* if the if condition has a false label
9214 then we cannot save */
9218 /* if the minus is not of the form
9220 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9221 !IS_OP_LITERAL (IC_RIGHT (ic)))
9224 if (operandLitValue (IC_RIGHT (ic)) != 1)
9227 /* if the size of this greater than one then no
9229 if (getSize (operandType (IC_RESULT (ic))) > 1)
9232 /* otherwise we can save BIG */
9233 lbl = newiTempLabel (NULL);
9234 lbl1 = newiTempLabel (NULL);
9236 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9238 if (IS_AOP_PREG (IC_RESULT (ic)))
9240 emitcode ("dec", "%s",
9241 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9242 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9243 emitcode ("jnz", "%05d$", lbl->key + 100);
9247 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9250 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9251 emitcode ("", "%05d$:", lbl->key + 100);
9252 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9253 emitcode ("", "%05d$:", lbl1->key + 100);
9255 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9260 /*-----------------------------------------------------------------*/
9261 /* genReceive - generate code for a receive iCode */
9262 /*-----------------------------------------------------------------*/
9264 genReceive (iCode * ic)
9267 D (emitcode (";", "genReceive ");
9270 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9271 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9272 IS_TRUE_SYMOP (IC_RESULT (ic))))
9274 int size = getSize (operandType (IC_RESULT (ic)));
9275 int offset = fReturnSizeDS390 - size;
9278 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9279 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9282 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9283 size = AOP_SIZE (IC_RESULT (ic));
9287 emitcode ("pop", "acc");
9288 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9295 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9297 assignResultValue (IC_RESULT (ic));
9300 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9303 /*-----------------------------------------------------------------*/
9304 /* gen390Code - generate code for Dallas 390 based controllers */
9305 /*-----------------------------------------------------------------*/
9307 gen390Code (iCode * lic)
9312 lineHead = lineCurr = NULL;
9316 /* print the allocation information */
9318 printAllocInfo (currFunc, codeOutFile);
9320 /* if debug information required */
9321 if (options.debug && currFunc)
9323 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9325 if (IS_STATIC (currFunc->etype))
9326 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9328 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9331 /* stack pointer name */
9332 if (options.useXstack)
9338 for (ic = lic; ic; ic = ic->next)
9341 if (cln != ic->lineno)
9346 emitcode ("", "C$%s$%d$%d$%d ==.",
9347 FileBaseName (ic->filename), ic->lineno,
9348 ic->level, ic->block);
9351 emitcode (";", "%s %d", ic->filename, ic->lineno);
9354 /* if the result is marked as
9355 spilt and rematerializable or code for
9356 this has already been generated then
9358 if (resultRemat (ic) || ic->generated)
9361 /* depending on the operation */
9381 /* IPOP happens only when trying to restore a
9382 spilt live range, if there is an ifx statement
9383 following this pop then the if statement might
9384 be using some of the registers being popped which
9385 would destory the contents of the register so
9386 we need to check for this condition and handle it */
9388 ic->next->op == IFX &&
9389 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9390 genIfx (ic->next, ic);
9408 genEndFunction (ic);
9428 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9445 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9449 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9456 /* note these two are xlated by algebraic equivalence
9457 during parsing SDCC.y */
9458 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9459 "got '>=' or '<=' shouldn't have come here");
9463 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9475 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9479 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9483 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9510 case GET_VALUE_AT_ADDRESS:
9515 if (POINTER_SET (ic))
9542 addSet (&_G.sendSet, ic);
9551 /* now we are ready to call the
9552 peep hole optimizer */
9553 if (!options.nopeep)
9554 peepHole (&lineHead);
9556 /* now do the actual printing */
9557 printLine (lineHead, codeOutFile);