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 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[MAX_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 ds390_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 ds390_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return ds390_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
236 /* other wise this is true end of the world */
237 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
238 "getFreePtr should never reach here");
242 /*-----------------------------------------------------------------*/
243 /* newAsmop - creates a new asmOp */
244 /*-----------------------------------------------------------------*/
246 newAsmop (short type)
250 aop = Safe_calloc (1, sizeof (asmop));
255 static int _currentDPS; /* Current processor DPS. */
256 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
257 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
259 /*-----------------------------------------------------------------*/
260 /* genSetDPTR: generate code to select which DPTR is in use (zero */
261 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
262 /* alternate DPTR (DPL1/DPH1/DPX1). */
263 /*-----------------------------------------------------------------*/
268 /* If we are doing lazy evaluation, simply note the desired
269 * change, but don't emit any code yet.
279 emitcode ("mov", "dps, #0x00");
283 emitcode ("mov", "dps, #0x01");
287 /*-----------------------------------------------------------------*/
288 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
290 /* Any code that operates on DPTR (NB: not on the individual */
291 /* components, like DPH) *must* call _flushLazyDPS() before using */
292 /* DPTR within a lazy DPS evaluation block. */
294 /* Note that aopPut and aopGet already contain the proper calls to */
295 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
296 /* DPS evaluation block. */
298 /* Also, _flushLazyDPS must be called before any flow control */
299 /* operations that could potentially branch out of the block. */
301 /* Lazy DPS evaluation is simply an optimization (though an */
302 /* important one), so if in doubt, leave it out. */
303 /*-----------------------------------------------------------------*/
305 _startLazyDPSEvaluation (void)
312 /*-----------------------------------------------------------------*/
313 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
314 /* desired one. Call before using DPTR within a lazy DPS evaluation */
316 /*-----------------------------------------------------------------*/
326 if (_desiredDPS != _currentDPS)
330 emitcode ("inc", "dps");
334 emitcode ("dec", "dps");
336 _currentDPS = _desiredDPS;
340 /*-----------------------------------------------------------------*/
341 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
343 /* Forces us back to the safe state (standard DPTR selected). */
344 /*-----------------------------------------------------------------*/
346 _endLazyDPSEvaluation (void)
360 /*-----------------------------------------------------------------*/
361 /* pointerCode - returns the code for a pointer type */
362 /*-----------------------------------------------------------------*/
364 pointerCode (sym_link * etype)
367 return PTR_TYPE (SPEC_OCLS (etype));
371 /*-----------------------------------------------------------------*/
372 /* aopForSym - for a true symbol */
373 /*-----------------------------------------------------------------*/
375 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
378 memmap *space = SPEC_OCLS (sym->etype);
380 /* if already has one */
384 /* assign depending on the storage class */
385 /* if it is on the stack or indirectly addressable */
386 /* space we need to assign either r0 or r1 to it */
387 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
389 sym->aop = aop = newAsmop (0);
390 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
391 aop->size = getSize (sym->type);
393 /* now assign the address of the variable to
394 the pointer register */
395 if (aop->type != AOP_STK)
401 emitcode ("push", "acc");
403 emitcode ("mov", "a,_bp");
404 emitcode ("add", "a,#0x%02x",
406 ((char) (sym->stack - _G.nRegsSaved)) :
407 ((char) sym->stack)) & 0xff);
408 emitcode ("mov", "%s,a",
409 aop->aopu.aop_ptr->name);
412 emitcode ("pop", "acc");
415 emitcode ("mov", "%s,#%s",
416 aop->aopu.aop_ptr->name,
418 aop->paged = space->paged;
421 aop->aopu.aop_stk = sym->stack;
425 if (sym->onStack && options.stack10bit)
427 /* It's on the 10 bit stack, which is located in
432 emitcode ("push", "acc");
434 emitcode ("mov", "a,_bp");
435 emitcode ("add", "a,#0x%02x",
437 ((char) (sym->stack - _G.nRegsSaved)) :
438 ((char) sym->stack)) & 0xff);
443 emitcode ("mov", "dpx1,#0x40");
444 emitcode ("mov", "dph1,#0x00");
445 emitcode ("mov", "dpl1, a");
450 emitcode ("mov", "dpx,#0x40");
451 emitcode ("mov", "dph,#0x00");
452 emitcode ("mov", "dpl, a");
456 emitcode ("pop", "acc");
458 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
459 aop->size = getSize (sym->type);
463 /* if in bit space */
464 if (IN_BITSPACE (space))
466 sym->aop = aop = newAsmop (AOP_CRY);
467 aop->aopu.aop_dir = sym->rname;
468 aop->size = getSize (sym->type);
471 /* if it is in direct space */
472 if (IN_DIRSPACE (space))
474 sym->aop = aop = newAsmop (AOP_DIR);
475 aop->aopu.aop_dir = sym->rname;
476 aop->size = getSize (sym->type);
480 /* special case for a function */
481 if (IS_FUNC (sym->type))
483 sym->aop = aop = newAsmop (AOP_IMMD);
484 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
485 strcpy (aop->aopu.aop_immd, sym->rname);
486 aop->size = FPTRSIZE;
490 /* only remaining is far space */
491 /* in which case DPTR gets the address */
492 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
497 emitcode ("mov", "dptr,#%s", sym->rname);
502 emitcode ("mov", "dptr,#%s", sym->rname);
504 aop->size = getSize (sym->type);
506 /* if it is in code space */
507 if (IN_CODESPACE (space))
513 /*-----------------------------------------------------------------*/
514 /* aopForRemat - rematerialzes an object */
515 /*-----------------------------------------------------------------*/
517 aopForRemat (symbol * sym)
519 iCode *ic = sym->rematiCode;
520 asmop *aop = newAsmop (AOP_IMMD);
527 val += (int) operandLitValue (IC_RIGHT (ic));
528 else if (ic->op == '-')
529 val -= (int) operandLitValue (IC_RIGHT (ic));
533 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
537 sprintf (buffer, "(%s %c 0x%04x)",
538 OP_SYMBOL (IC_LEFT (ic))->rname,
539 val >= 0 ? '+' : '-',
542 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
544 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
545 strcpy (aop->aopu.aop_immd, buffer);
549 /*-----------------------------------------------------------------*/
550 /* regsInCommon - two operands have some registers in common */
551 /*-----------------------------------------------------------------*/
553 regsInCommon (operand * op1, operand * op2)
558 /* if they have registers in common */
559 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
562 sym1 = OP_SYMBOL (op1);
563 sym2 = OP_SYMBOL (op2);
565 if (sym1->nRegs == 0 || sym2->nRegs == 0)
568 for (i = 0; i < sym1->nRegs; i++)
574 for (j = 0; j < sym2->nRegs; j++)
579 if (sym2->regs[j] == sym1->regs[i])
587 /*-----------------------------------------------------------------*/
588 /* operandsEqu - equivalent */
589 /*-----------------------------------------------------------------*/
591 operandsEqu (operand * op1, operand * op2)
595 /* if they not symbols */
596 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
599 sym1 = OP_SYMBOL (op1);
600 sym2 = OP_SYMBOL (op2);
602 /* if both are itemps & one is spilt
603 and the other is not then false */
604 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
605 sym1->isspilt != sym2->isspilt)
608 /* if they are the same */
612 if (strcmp (sym1->rname, sym2->rname) == 0)
616 /* if left is a tmp & right is not */
617 if (IS_ITEMP (op1) &&
620 (sym1->usl.spillLoc == sym2))
623 if (IS_ITEMP (op2) &&
627 (sym2->usl.spillLoc == sym1))
633 /*-----------------------------------------------------------------*/
634 /* sameRegs - two asmops have the same registers */
635 /*-----------------------------------------------------------------*/
637 sameRegs (asmop * aop1, asmop * aop2)
643 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
650 if (aop1->type != AOP_REG ||
651 aop2->type != AOP_REG)
654 if (aop1->size != aop2->size)
657 for (i = 0; i < aop1->size; i++)
658 if (aop1->aopu.aop_reg[i] !=
659 aop2->aopu.aop_reg[i])
665 /*-----------------------------------------------------------------*/
666 /* aopOp - allocates an asmop for an operand : */
667 /*-----------------------------------------------------------------*/
669 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
678 /* if this a literal */
679 if (IS_OP_LITERAL (op))
681 op->aop = aop = newAsmop (AOP_LIT);
682 aop->aopu.aop_lit = op->operand.valOperand;
683 aop->size = getSize (operandType (op));
687 /* if already has a asmop then continue */
691 /* if the underlying symbol has a aop */
692 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
694 op->aop = OP_SYMBOL (op)->aop;
698 /* if this is a true symbol */
699 if (IS_TRUE_SYMOP (op))
701 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
705 /* this is a temporary : this has
711 e) can be a return use only */
713 sym = OP_SYMBOL (op);
716 /* if the type is a conditional */
717 if (sym->regType == REG_CND)
719 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
724 /* if it is spilt then two situations
726 b) has a spill location */
727 if (sym->isspilt || sym->nRegs == 0)
730 /* rematerialize it NOW */
733 sym->aop = op->aop = aop =
735 aop->size = getSize (sym->type);
742 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
743 aop->size = getSize (sym->type);
744 for (i = 0; i < 2; i++)
745 aop->aopu.aop_str[i] = accUse[i];
755 /* a AOP_STR uses DPTR, but DPTR is already in use;
758 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
761 aop = op->aop = sym->aop = newAsmop (AOP_STR);
762 aop->size = getSize (sym->type);
763 for (i = 0; i < (int) fReturnSizeDS390; i++)
764 aop->aopu.aop_str[i] = fReturn[i];
768 /* else spill location */
769 sym->aop = op->aop = aop =
770 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
771 aop->size = getSize (sym->type);
775 /* must be in a register */
776 sym->aop = op->aop = aop = newAsmop (AOP_REG);
777 aop->size = sym->nRegs;
778 for (i = 0; i < sym->nRegs; i++)
779 aop->aopu.aop_reg[i] = sym->regs[i];
782 /*-----------------------------------------------------------------*/
783 /* freeAsmop - free up the asmop given to an operand */
784 /*----------------------------------------------------------------*/
786 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
803 /* depending on the asmop type only three cases need work AOP_RO
804 , AOP_R1 && AOP_STK */
812 emitcode ("pop", "ar0");
816 bitVectUnSetBit (ic->rUsed, R0_IDX);
824 emitcode ("pop", "ar1");
828 bitVectUnSetBit (ic->rUsed, R1_IDX);
834 int stk = aop->aopu.aop_stk + aop->size;
835 bitVectUnSetBit (ic->rUsed, R0_IDX);
836 bitVectUnSetBit (ic->rUsed, R1_IDX);
838 getFreePtr (ic, &aop, FALSE);
840 if (options.stack10bit)
842 /* I'm not sure what to do here yet... */
845 "*** Warning: probably generating bad code for "
846 "10 bit stack mode.\n");
851 emitcode ("mov", "a,_bp");
852 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
853 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
857 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
862 emitcode ("pop", "acc");
863 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
866 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
869 freeAsmop (op, NULL, ic, TRUE);
872 emitcode ("pop", "ar0");
878 emitcode ("pop", "ar1");
885 /* all other cases just dealloc */
891 OP_SYMBOL (op)->aop = NULL;
892 /* if the symbol has a spill */
894 SPIL_LOC (op)->aop = NULL;
899 /*------------------------------------------------------------------*/
900 /* aopGet - for fetching value of the aop */
902 /* Set canClobberACC if you are aure it is OK to clobber the value */
903 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
904 /* just less efficient. */
905 /*------------------------------------------------------------------*/
917 /* offset is greater than
919 if (offset > (aop->size - 1) &&
920 aop->type != AOP_LIT)
923 /* depending on type */
929 /* if we need to increment it */
930 while (offset > aop->coff)
932 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
936 while (offset < aop->coff)
938 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
945 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
946 return (dname ? "acc" : "a");
948 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
949 rs = Safe_calloc (1, strlen (s) + 1);
956 if (aop->type == AOP_DPTR2)
961 emitcode ("xch", "a, ap");
967 while (offset > aop->coff)
969 emitcode ("inc", "dptr");
973 while (offset < aop->coff)
975 emitcode ("lcall", "__decdptr");
982 emitcode ("clr", "a");
983 emitcode ("movc", "a,@a+dptr");
987 emitcode ("movx", "a,@dptr");
990 if (aop->type == AOP_DPTR2)
995 emitcode ("xch", "a, ap");
999 return (dname ? "acc" : "a");
1003 sprintf (s, "#%s", aop->aopu.aop_immd);
1005 sprintf (s, "#(%s >> %d)",
1010 aop->aopu.aop_immd);
1011 rs = Safe_calloc (1, strlen (s) + 1);
1017 sprintf (s, "(%s + %d)",
1021 sprintf (s, "%s", aop->aopu.aop_dir);
1022 rs = Safe_calloc (1, strlen (s) + 1);
1028 return aop->aopu.aop_reg[offset]->dname;
1030 return aop->aopu.aop_reg[offset]->name;
1033 emitcode ("clr", "a");
1034 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1035 emitcode ("rlc", "a");
1036 return (dname ? "acc" : "a");
1039 if (!offset && dname)
1041 return aop->aopu.aop_str[offset];
1044 return aopLiteral (aop->aopu.aop_lit, offset);
1048 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1052 return aop->aopu.aop_str[offset];
1056 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1057 "aopget got unsupported aop->type");
1060 /*-----------------------------------------------------------------*/
1061 /* aopPut - puts a string for a aop */
1062 /*-----------------------------------------------------------------*/
1064 aopPut (asmop * aop, char *s, int offset)
1068 if (aop->size && offset > (aop->size - 1))
1070 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1071 "aopPut got offset > aop->size");
1075 /* will assign value to value */
1076 /* depending on where it is ofcourse */
1081 sprintf (d, "(%s + %d)",
1082 aop->aopu.aop_dir, offset);
1084 sprintf (d, "%s", aop->aopu.aop_dir);
1087 emitcode ("mov", "%s,%s", d, s);
1092 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1093 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1096 strcmp (s, "r0") == 0 ||
1097 strcmp (s, "r1") == 0 ||
1098 strcmp (s, "r2") == 0 ||
1099 strcmp (s, "r3") == 0 ||
1100 strcmp (s, "r4") == 0 ||
1101 strcmp (s, "r5") == 0 ||
1102 strcmp (s, "r6") == 0 ||
1103 strcmp (s, "r7") == 0)
1104 emitcode ("mov", "%s,%s",
1105 aop->aopu.aop_reg[offset]->dname, s);
1107 emitcode ("mov", "%s,%s",
1108 aop->aopu.aop_reg[offset]->name, s);
1115 if (aop->type == AOP_DPTR2)
1123 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1124 "aopPut writting to code space");
1128 while (offset > aop->coff)
1131 emitcode ("inc", "dptr");
1134 while (offset < aop->coff)
1137 emitcode ("lcall", "__decdptr");
1142 /* if not in accumulater */
1145 emitcode ("movx", "@dptr,a");
1147 if (aop->type == AOP_DPTR2)
1155 while (offset > aop->coff)
1158 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1160 while (offset < aop->coff)
1163 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1170 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1176 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1178 else if (strcmp (s, "r0") == 0 ||
1179 strcmp (s, "r1") == 0 ||
1180 strcmp (s, "r2") == 0 ||
1181 strcmp (s, "r3") == 0 ||
1182 strcmp (s, "r4") == 0 ||
1183 strcmp (s, "r5") == 0 ||
1184 strcmp (s, "r6") == 0 ||
1185 strcmp (s, "r7") == 0)
1188 sprintf (buffer, "a%s", s);
1189 emitcode ("mov", "@%s,%s",
1190 aop->aopu.aop_ptr->name, buffer);
1193 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1198 if (strcmp (s, "a") == 0)
1199 emitcode ("push", "acc");
1201 emitcode ("push", "%s", s);
1206 /* if bit variable */
1207 if (!aop->aopu.aop_dir)
1209 emitcode ("clr", "a");
1210 emitcode ("rlc", "a");
1215 emitcode ("clr", "%s", aop->aopu.aop_dir);
1217 emitcode ("setb", "%s", aop->aopu.aop_dir);
1218 else if (!strcmp (s, "c"))
1219 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1222 if (strcmp (s, "a"))
1227 symbol *lbl = newiTempLabel (NULL);
1228 emitcode ("clr", "c");
1229 emitcode ("jz", "%05d$", lbl->key + 100);
1230 emitcode ("cpl", "c");
1231 emitcode ("", "%05d$:", lbl->key + 100);
1232 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1240 if (strcmp (aop->aopu.aop_str[offset], s))
1241 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1246 if (!offset && (strcmp (s, "acc") == 0))
1249 if (strcmp (aop->aopu.aop_str[offset], s))
1250 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1255 "aopPut got unsupported aop->type");
1262 /*--------------------------------------------------------------------*/
1263 /* reAdjustPreg - points a register back to where it should (coff==0) */
1264 /*--------------------------------------------------------------------*/
1266 reAdjustPreg (asmop * aop)
1268 if ((aop->coff==0) || (aop->size <= 1)) {
1277 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1281 if (aop->type == AOP_DPTR2)
1288 emitcode ("lcall", "__decdptr");
1291 if (aop->type == AOP_DPTR2)
1301 #define AOP(op) op->aop
1302 #define AOP_TYPE(op) AOP(op)->type
1303 #define AOP_SIZE(op) AOP(op)->size
1304 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1305 AOP_TYPE(x) == AOP_R0))
1307 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1308 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1311 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1312 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1313 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1315 /* Workaround for DS80C390 bug: div ab may return bogus results
1316 * if A is accessed in instruction immediately before the div.
1318 * Will be fixed in B4 rev of processor, Dallas claims.
1321 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1322 if (!AOP_NEEDSACC(RIGHT)) \
1324 /* We can load A first, then B, since \
1325 * B (the RIGHT operand) won't clobber A, \
1326 * thus avoiding touching A right before the div. \
1328 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1329 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1331 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1335 /* Just stuff in a nop after loading A. */ \
1336 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1337 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1339 emitcode("nop", "; workaround for DS80C390 div bug."); \
1342 /*-----------------------------------------------------------------*/
1343 /* genNotFloat - generates not for float operations */
1344 /*-----------------------------------------------------------------*/
1346 genNotFloat (operand * op, operand * res)
1352 D (emitcode (";", "genNotFloat ");
1355 /* we will put 127 in the first byte of
1357 aopPut (AOP (res), "#127", 0);
1358 size = AOP_SIZE (op) - 1;
1361 _startLazyDPSEvaluation ();
1362 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1367 emitcode ("orl", "a,%s",
1369 offset++, FALSE, FALSE, FALSE));
1371 _endLazyDPSEvaluation ();
1373 tlbl = newiTempLabel (NULL);
1374 aopPut (res->aop, one, 1);
1375 emitcode ("jz", "%05d$", (tlbl->key + 100));
1376 aopPut (res->aop, zero, 1);
1377 emitcode ("", "%05d$:", (tlbl->key + 100));
1379 size = res->aop->size - 2;
1381 /* put zeros in the rest */
1383 aopPut (res->aop, zero, offset++);
1386 /*-----------------------------------------------------------------*/
1387 /* opIsGptr: returns non-zero if the passed operand is */
1388 /* a generic pointer type. */
1389 /*-----------------------------------------------------------------*/
1391 opIsGptr (operand * op)
1393 sym_link *type = operandType (op);
1395 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1402 /*-----------------------------------------------------------------*/
1403 /* getDataSize - get the operand data size */
1404 /*-----------------------------------------------------------------*/
1406 getDataSize (operand * op)
1409 size = AOP_SIZE (op);
1410 if (size == GPTRSIZE)
1412 sym_link *type = operandType (op);
1413 if (IS_GENPTR (type))
1415 /* generic pointer; arithmetic operations
1416 * should ignore the high byte (pointer type).
1424 /*-----------------------------------------------------------------*/
1425 /* outAcc - output Acc */
1426 /*-----------------------------------------------------------------*/
1428 outAcc (operand * result)
1431 size = getDataSize (result);
1434 aopPut (AOP (result), "a", 0);
1437 /* unsigned or positive */
1440 aopPut (AOP (result), zero, offset++);
1445 /*-----------------------------------------------------------------*/
1446 /* outBitC - output a bit C */
1447 /*-----------------------------------------------------------------*/
1449 outBitC (operand * result)
1451 /* if the result is bit */
1452 if (AOP_TYPE (result) == AOP_CRY)
1454 aopPut (AOP (result), "c", 0);
1458 emitcode ("clr", "a");
1459 emitcode ("rlc", "a");
1464 /*-----------------------------------------------------------------*/
1465 /* toBoolean - emit code for orl a,operator(sizeop) */
1466 /*-----------------------------------------------------------------*/
1468 toBoolean (operand * oper)
1470 int size = AOP_SIZE (oper) - 1;
1473 /* The generic part of a generic pointer should
1474 * not participate in it's truth value.
1476 * i.e. 0x10000000 is zero.
1478 if (opIsGptr (oper))
1480 D (emitcode (";", "toBoolean: generic ptr special case.");
1485 _startLazyDPSEvaluation ();
1486 if (AOP_NEEDSACC (oper))
1488 emitcode ("push", "b");
1489 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1493 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1497 if (AOP_NEEDSACC (oper))
1499 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1503 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1506 _endLazyDPSEvaluation ();
1508 if (AOP_NEEDSACC (oper))
1510 emitcode ("mov", "a,b");
1511 emitcode ("pop", "b");
1516 /*-----------------------------------------------------------------*/
1517 /* genNot - generate code for ! operation */
1518 /*-----------------------------------------------------------------*/
1523 sym_link *optype = operandType (IC_LEFT (ic));
1525 D (emitcode (";", "genNot ");
1528 /* assign asmOps to operand & result */
1529 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1530 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1532 /* if in bit space then a special case */
1533 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1535 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1536 emitcode ("cpl", "c");
1537 outBitC (IC_RESULT (ic));
1541 /* if type float then do float */
1542 if (IS_FLOAT (optype))
1544 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1548 toBoolean (IC_LEFT (ic));
1550 tlbl = newiTempLabel (NULL);
1551 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1552 emitcode ("", "%05d$:", tlbl->key + 100);
1553 outBitC (IC_RESULT (ic));
1556 /* release the aops */
1557 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1558 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1562 /*-----------------------------------------------------------------*/
1563 /* genCpl - generate code for complement */
1564 /*-----------------------------------------------------------------*/
1571 D (emitcode (";", "genCpl ");
1575 /* assign asmOps to operand & result */
1576 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1577 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1579 /* if both are in bit space then
1581 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1582 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1585 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1586 emitcode ("cpl", "c");
1587 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1591 size = AOP_SIZE (IC_RESULT (ic));
1592 _startLazyDPSEvaluation ();
1595 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1597 emitcode ("cpl", "a");
1598 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1600 _endLazyDPSEvaluation ();
1604 /* release the aops */
1605 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1606 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1609 /*-----------------------------------------------------------------*/
1610 /* genUminusFloat - unary minus for floating points */
1611 /*-----------------------------------------------------------------*/
1613 genUminusFloat (operand * op, operand * result)
1615 int size, offset = 0;
1617 /* for this we just need to flip the
1618 first it then copy the rest in place */
1619 D (emitcode (";", "genUminusFloat");
1622 _startLazyDPSEvaluation ();
1623 size = AOP_SIZE (op) - 1;
1624 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1627 emitcode ("cpl", "acc.7");
1628 aopPut (AOP (result), "a", 3);
1632 aopPut (AOP (result),
1633 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1637 _endLazyDPSEvaluation ();
1640 /*-----------------------------------------------------------------*/
1641 /* genUminus - unary minus code generation */
1642 /*-----------------------------------------------------------------*/
1644 genUminus (iCode * ic)
1647 sym_link *optype, *rtype;
1649 D (emitcode (";", "genUminus ");
1654 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1655 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1657 /* if both in bit space then special
1659 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1660 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1663 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1664 emitcode ("cpl", "c");
1665 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1669 optype = operandType (IC_LEFT (ic));
1670 rtype = operandType (IC_RESULT (ic));
1672 /* if float then do float stuff */
1673 if (IS_FLOAT (optype))
1675 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1679 /* otherwise subtract from zero */
1680 size = AOP_SIZE (IC_LEFT (ic));
1682 _startLazyDPSEvaluation ();
1685 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1686 if (!strcmp (l, "a"))
1690 emitcode ("cpl", "a");
1691 emitcode ("addc", "a,#0");
1697 emitcode ("clr", "a");
1698 emitcode ("subb", "a,%s", l);
1700 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1702 _endLazyDPSEvaluation ();
1704 /* if any remaining bytes in the result */
1705 /* we just need to propagate the sign */
1706 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1708 emitcode ("rlc", "a");
1709 emitcode ("subb", "a,acc");
1711 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1715 /* release the aops */
1716 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1717 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1720 /*-----------------------------------------------------------------*/
1721 /* saveRegisters - will look for a call and save the registers */
1722 /*-----------------------------------------------------------------*/
1724 saveRegisters (iCode * lic)
1732 for (ic = lic; ic; ic = ic->next)
1733 if (ic->op == CALL || ic->op == PCALL)
1738 fprintf (stderr, "found parameter push with no function call\n");
1742 /* if the registers have been saved already then
1744 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1747 /* find the registers in use at this time
1748 and push them away to safety */
1749 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1753 if (options.useXstack)
1755 if (bitVectBitValue (rsave, R0_IDX))
1756 emitcode ("mov", "b,r0");
1757 emitcode ("mov", "r0,%s", spname);
1758 for (i = 0; i < ds390_nRegs; i++)
1760 if (bitVectBitValue (rsave, i))
1763 emitcode ("mov", "a,b");
1765 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1766 emitcode ("movx", "@r0,a");
1767 emitcode ("inc", "r0");
1770 emitcode ("mov", "%s,r0", spname);
1771 if (bitVectBitValue (rsave, R0_IDX))
1772 emitcode ("mov", "r0,b");
1775 for (i = 0; i < ds390_nRegs; i++)
1777 if (bitVectBitValue (rsave, i))
1778 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1781 detype = getSpec (operandType (IC_LEFT (ic)));
1783 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1784 IS_ISR (currFunc->etype) &&
1787 saverbank (SPEC_BANK (detype), ic, TRUE);
1790 /*-----------------------------------------------------------------*/
1791 /* unsaveRegisters - pop the pushed registers */
1792 /*-----------------------------------------------------------------*/
1794 unsaveRegisters (iCode * ic)
1798 /* find the registers in use at this time
1799 and push them away to safety */
1800 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1803 if (options.useXstack)
1805 emitcode ("mov", "r0,%s", spname);
1806 for (i = ds390_nRegs; i >= 0; i--)
1808 if (bitVectBitValue (rsave, i))
1810 emitcode ("dec", "r0");
1811 emitcode ("movx", "a,@r0");
1813 emitcode ("mov", "b,a");
1815 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1819 emitcode ("mov", "%s,r0", spname);
1820 if (bitVectBitValue (rsave, R0_IDX))
1821 emitcode ("mov", "r0,b");
1824 for (i = ds390_nRegs; i >= 0; i--)
1826 if (bitVectBitValue (rsave, i))
1827 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1833 /*-----------------------------------------------------------------*/
1835 /*-----------------------------------------------------------------*/
1837 pushSide (operand * oper, int size)
1840 _startLazyDPSEvaluation ();
1843 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1844 if (AOP_TYPE (oper) != AOP_REG &&
1845 AOP_TYPE (oper) != AOP_DIR &&
1848 emitcode ("mov", "a,%s", l);
1849 emitcode ("push", "acc");
1852 emitcode ("push", "%s", l);
1854 _endLazyDPSEvaluation ();
1857 /*-----------------------------------------------------------------*/
1858 /* assignResultValue - */
1859 /*-----------------------------------------------------------------*/
1861 assignResultValue (operand * oper)
1864 int size = AOP_SIZE (oper);
1866 _startLazyDPSEvaluation ();
1869 aopPut (AOP (oper), fReturn[offset], offset);
1872 _endLazyDPSEvaluation ();
1876 /*-----------------------------------------------------------------*/
1877 /* genXpush - pushes onto the external stack */
1878 /*-----------------------------------------------------------------*/
1880 genXpush (iCode * ic)
1882 asmop *aop = newAsmop (0);
1884 int size, offset = 0;
1886 D (emitcode (";", "genXpush ");
1889 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1890 r = getFreePtr (ic, &aop, FALSE);
1893 emitcode ("mov", "%s,_spx", r->name);
1895 size = AOP_SIZE (IC_LEFT (ic));
1896 _startLazyDPSEvaluation ();
1900 char *l = aopGet (AOP (IC_LEFT (ic)),
1901 offset++, FALSE, FALSE, TRUE);
1903 emitcode ("movx", "@%s,a", r->name);
1904 emitcode ("inc", "%s", r->name);
1907 _endLazyDPSEvaluation ();
1910 emitcode ("mov", "_spx,%s", r->name);
1912 freeAsmop (NULL, aop, ic, TRUE);
1913 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1916 /*-----------------------------------------------------------------*/
1917 /* genIpush - genrate code for pushing this gets a little complex */
1918 /*-----------------------------------------------------------------*/
1920 genIpush (iCode * ic)
1922 int size, offset = 0;
1925 D (emitcode (";", "genIpush ");
1928 /* if this is not a parm push : ie. it is spill push
1929 and spill push is always done on the local stack */
1933 /* and the item is spilt then do nothing */
1934 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1937 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1938 size = AOP_SIZE (IC_LEFT (ic));
1939 /* push it on the stack */
1940 _startLazyDPSEvaluation ();
1943 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1949 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1951 _endLazyDPSEvaluation ();
1955 /* this is a paramter push: in this case we call
1956 the routine to find the call and save those
1957 registers that need to be saved */
1960 /* if use external stack then call the external
1961 stack pushing routine */
1962 if (options.useXstack)
1968 /* then do the push */
1969 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1971 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1972 size = AOP_SIZE (IC_LEFT (ic));
1974 _startLazyDPSEvaluation ();
1977 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1978 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1979 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1982 emitcode ("mov", "a,%s", l);
1983 emitcode ("push", "acc");
1986 emitcode ("push", "%s ;jwk genIpush", l);
1988 _endLazyDPSEvaluation ();
1990 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1993 /*-----------------------------------------------------------------*/
1994 /* genIpop - recover the registers: can happen only for spilling */
1995 /*-----------------------------------------------------------------*/
1997 genIpop (iCode * ic)
2001 D (emitcode (";", "genIpop ");
2005 /* if the temp was not pushed then */
2006 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2009 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2010 size = AOP_SIZE (IC_LEFT (ic));
2011 offset = (size - 1);
2012 _startLazyDPSEvaluation ();
2015 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2016 FALSE, TRUE, TRUE));
2018 _endLazyDPSEvaluation ();
2020 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2023 /*-----------------------------------------------------------------*/
2024 /* unsaverbank - restores the resgister bank from stack */
2025 /*-----------------------------------------------------------------*/
2027 unsaverbank (int bank, iCode * ic, bool popPsw)
2035 if (options.useXstack)
2038 r = getFreePtr (ic, &aop, FALSE);
2041 emitcode ("mov", "%s,_spx", r->name);
2042 emitcode ("movx", "a,@%s", r->name);
2043 emitcode ("mov", "psw,a");
2044 emitcode ("dec", "%s", r->name);
2048 emitcode ("pop", "psw");
2051 for (i = (ds390_nRegs - 1); i >= 0; i--)
2053 if (options.useXstack)
2055 emitcode ("movx", "a,@%s", r->name);
2056 emitcode ("mov", "(%s+%d),a",
2057 regs390[i].base, 8 * bank + regs390[i].offset);
2058 emitcode ("dec", "%s", r->name);
2062 emitcode ("pop", "(%s+%d)",
2063 regs390[i].base, 8 * bank + regs390[i].offset);
2066 if (options.useXstack)
2069 emitcode ("mov", "_spx,%s", r->name);
2070 freeAsmop (NULL, aop, ic, TRUE);
2075 /*-----------------------------------------------------------------*/
2076 /* saverbank - saves an entire register bank on the stack */
2077 /*-----------------------------------------------------------------*/
2079 saverbank (int bank, iCode * ic, bool pushPsw)
2085 if (options.useXstack)
2089 r = getFreePtr (ic, &aop, FALSE);
2090 emitcode ("mov", "%s,_spx", r->name);
2094 for (i = 0; i < ds390_nRegs; i++)
2096 if (options.useXstack)
2098 emitcode ("inc", "%s", r->name);
2099 emitcode ("mov", "a,(%s+%d)",
2100 regs390[i].base, 8 * bank + regs390[i].offset);
2101 emitcode ("movx", "@%s,a", r->name);
2104 emitcode ("push", "(%s+%d)",
2105 regs390[i].base, 8 * bank + regs390[i].offset);
2110 if (options.useXstack)
2112 emitcode ("mov", "a,psw");
2113 emitcode ("movx", "@%s,a", r->name);
2114 emitcode ("inc", "%s", r->name);
2115 emitcode ("mov", "_spx,%s", r->name);
2116 freeAsmop (NULL, aop, ic, TRUE);
2120 emitcode ("push", "psw");
2122 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2128 /*-----------------------------------------------------------------*/
2129 /* genCall - generates a call statement */
2130 /*-----------------------------------------------------------------*/
2132 genCall (iCode * ic)
2136 D (emitcode (";", "genCall ");
2139 /* if caller saves & we have not saved then */
2143 /* if we are calling a function that is not using
2144 the same register bank then we need to save the
2145 destination registers on the stack */
2146 detype = getSpec (operandType (IC_LEFT (ic)));
2148 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2149 IS_ISR (currFunc->etype) &&
2152 saverbank (SPEC_BANK (detype), ic, TRUE);
2154 /* if send set is not empty the assign */
2159 for (sic = setFirstItem (_G.sendSet); sic;
2160 sic = setNextItem (_G.sendSet))
2162 int size, offset = 0;
2164 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2165 size = AOP_SIZE (IC_LEFT (sic));
2167 _startLazyDPSEvaluation ();
2170 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2171 FALSE, FALSE, TRUE);
2172 if (strcmp (l, fReturn[offset])) {
2175 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2181 _endLazyDPSEvaluation ();
2182 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2187 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2188 OP_SYMBOL (IC_LEFT (ic))->rname :
2189 OP_SYMBOL (IC_LEFT (ic))->name));
2191 /* if we need assign a result value */
2192 if ((IS_ITEMP (IC_RESULT (ic)) &&
2193 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2194 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2195 IS_TRUE_SYMOP (IC_RESULT (ic)))
2197 if (isOperandInFarSpace (IC_RESULT (ic))
2198 && getSize (operandType (IC_RESULT (ic))) <= 2)
2200 int size = getSize (operandType (IC_RESULT (ic)));
2202 /* Special case for 1 or 2 byte return in far space. */
2203 emitcode (";", "Kevin function call abuse #1");
2208 emitcode ("mov", "b,%s", fReturn[1]);
2211 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2212 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2216 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2218 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2223 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2226 assignResultValue (IC_RESULT (ic));
2228 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2232 /* adjust the stack for parameters if
2237 if (ic->parmBytes > 3)
2239 emitcode ("mov", "a,%s", spname);
2240 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2241 emitcode ("mov", "%s,a", spname);
2244 for (i = 0; i < ic->parmBytes; i++)
2245 emitcode ("dec", "%s", spname);
2249 /* if register bank was saved then pop them */
2251 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2253 /* if we hade saved some registers then unsave them */
2254 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2255 unsaveRegisters (ic);
2260 /*-----------------------------------------------------------------*/
2261 /* genPcall - generates a call by pointer statement */
2262 /*-----------------------------------------------------------------*/
2264 genPcall (iCode * ic)
2267 symbol *rlbl = newiTempLabel (NULL);
2269 D (emitcode (";", "genPcall ");
2273 /* if caller saves & we have not saved then */
2277 /* if we are calling a function that is not using
2278 the same register bank then we need to save the
2279 destination registers on the stack */
2280 detype = getSpec (operandType (IC_LEFT (ic)));
2282 IS_ISR (currFunc->etype) &&
2283 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2284 saverbank (SPEC_BANK (detype), ic, TRUE);
2287 /* push the return address on to the stack */
2288 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2289 emitcode ("push", "acc");
2290 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2291 emitcode ("push", "acc");
2293 if (options.model == MODEL_FLAT24)
2295 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2296 emitcode ("push", "acc");
2299 /* now push the calling address */
2300 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2302 pushSide (IC_LEFT (ic), FPTRSIZE);
2304 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2306 /* if send set is not empty the assign */
2311 for (sic = setFirstItem (_G.sendSet); sic;
2312 sic = setNextItem (_G.sendSet))
2314 int size, offset = 0;
2316 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2317 size = AOP_SIZE (IC_LEFT (sic));
2318 _startLazyDPSEvaluation ();
2321 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2322 FALSE, FALSE, TRUE);
2323 if (strcmp (l, fReturn[offset]))
2325 emitcode ("mov", "%s,%s",
2331 _endLazyDPSEvaluation ();
2332 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2337 emitcode ("ret", "");
2338 emitcode ("", "%05d$:", (rlbl->key + 100));
2341 /* if we need assign a result value */
2342 if ((IS_ITEMP (IC_RESULT (ic)) &&
2343 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2344 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2345 IS_TRUE_SYMOP (IC_RESULT (ic)))
2349 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2352 assignResultValue (IC_RESULT (ic));
2354 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2357 /* adjust the stack for parameters if
2362 if (ic->parmBytes > 3)
2364 emitcode ("mov", "a,%s", spname);
2365 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2366 emitcode ("mov", "%s,a", spname);
2369 for (i = 0; i < ic->parmBytes; i++)
2370 emitcode ("dec", "%s", spname);
2374 /* if register bank was saved then unsave them */
2376 (SPEC_BANK (currFunc->etype) !=
2377 SPEC_BANK (detype)))
2378 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2380 /* if we hade saved some registers then
2383 unsaveRegisters (ic);
2387 /*-----------------------------------------------------------------*/
2388 /* resultRemat - result is rematerializable */
2389 /*-----------------------------------------------------------------*/
2391 resultRemat (iCode * ic)
2393 if (SKIP_IC (ic) || ic->op == IFX)
2396 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2398 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2399 if (sym->remat && !POINTER_SET (ic))
2406 #if defined(__BORLANDC__) || defined(_MSC_VER)
2407 #define STRCASECMP stricmp
2409 #define STRCASECMP strcasecmp
2412 /*-----------------------------------------------------------------*/
2413 /* inExcludeList - return 1 if the string is in exclude Reg list */
2414 /*-----------------------------------------------------------------*/
2416 inExcludeList (char *s)
2420 if (options.excludeRegs[i] &&
2421 STRCASECMP (options.excludeRegs[i], "none") == 0)
2424 for (i = 0; options.excludeRegs[i]; i++)
2426 if (options.excludeRegs[i] &&
2427 STRCASECMP (s, options.excludeRegs[i]) == 0)
2433 /*-----------------------------------------------------------------*/
2434 /* genFunction - generated code for function entry */
2435 /*-----------------------------------------------------------------*/
2437 genFunction (iCode * ic)
2442 D (emitcode (";", "genFunction ");
2446 /* create the function header */
2447 emitcode (";", "-----------------------------------------");
2448 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2449 emitcode (";", "-----------------------------------------");
2451 emitcode ("", "%s:", sym->rname);
2452 fetype = getSpec (operandType (IC_LEFT (ic)));
2454 /* if critical function then turn interrupts off */
2455 if (SPEC_CRTCL (fetype))
2456 emitcode ("clr", "ea");
2458 /* here we need to generate the equates for the
2459 register bank if required */
2460 if (SPEC_BANK (fetype) != rbank)
2464 rbank = SPEC_BANK (fetype);
2465 for (i = 0; i < ds390_nRegs; i++)
2467 if (strcmp (regs390[i].base, "0") == 0)
2468 emitcode ("", "%s = 0x%02x",
2470 8 * rbank + regs390[i].offset);
2472 emitcode ("", "%s = %s + 0x%02x",
2475 8 * rbank + regs390[i].offset);
2479 /* if this is an interrupt service routine then
2480 save acc, b, dpl, dph */
2481 if (IS_ISR (sym->etype))
2484 if (!inExcludeList ("acc"))
2485 emitcode ("push", "acc");
2486 if (!inExcludeList ("b"))
2487 emitcode ("push", "b");
2488 if (!inExcludeList ("dpl"))
2489 emitcode ("push", "dpl");
2490 if (!inExcludeList ("dph"))
2491 emitcode ("push", "dph");
2492 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2494 emitcode ("push", "dpx");
2495 /* Make sure we're using standard DPTR */
2496 emitcode ("push", "dps");
2497 emitcode ("mov", "dps, #0x00");
2498 if (options.stack10bit)
2500 /* This ISR could conceivably use DPTR2. Better save it. */
2501 emitcode ("push", "dpl1");
2502 emitcode ("push", "dph1");
2503 emitcode ("push", "dpx1");
2504 emitcode ("push", "ap");
2507 /* if this isr has no bank i.e. is going to
2508 run with bank 0 , then we need to save more
2510 if (!SPEC_BANK (sym->etype))
2513 /* if this function does not call any other
2514 function then we can be economical and
2515 save only those registers that are used */
2520 /* if any registers used */
2523 /* save the registers used */
2524 for (i = 0; i < sym->regsUsed->size; i++)
2526 if (bitVectBitValue (sym->regsUsed, i) ||
2527 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2528 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2535 /* this function has a function call cannot
2536 determines register usage so we will have the
2538 saverbank (0, ic, FALSE);
2544 /* if callee-save to be used for this function
2545 then save the registers being used in this function */
2546 if (sym->calleeSave)
2550 /* if any registers used */
2553 /* save the registers used */
2554 for (i = 0; i < sym->regsUsed->size; i++)
2556 if (bitVectBitValue (sym->regsUsed, i) ||
2557 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2559 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2567 /* set the register bank to the desired value */
2568 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2570 emitcode ("push", "psw");
2571 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2574 if (IS_RENT (sym->etype) || options.stackAuto)
2577 if (options.useXstack)
2579 emitcode ("mov", "r0,%s", spname);
2580 emitcode ("mov", "a,_bp");
2581 emitcode ("movx", "@r0,a");
2582 emitcode ("inc", "%s", spname);
2586 /* set up the stack */
2587 emitcode ("push", "_bp"); /* save the callers stack */
2589 emitcode ("mov", "_bp,%s", spname);
2592 /* adjust the stack for the function */
2598 werror (W_STACK_OVERFLOW, sym->name);
2600 if (i > 3 && sym->recvSize < 4)
2603 emitcode ("mov", "a,sp");
2604 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2605 emitcode ("mov", "sp,a");
2610 emitcode ("inc", "sp");
2616 emitcode ("mov", "a,_spx");
2617 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2618 emitcode ("mov", "_spx,a");
2623 /*-----------------------------------------------------------------*/
2624 /* genEndFunction - generates epilogue for functions */
2625 /*-----------------------------------------------------------------*/
2627 genEndFunction (iCode * ic)
2629 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2631 D (emitcode (";", "genEndFunction ");
2634 if (IS_RENT (sym->etype) || options.stackAuto)
2636 emitcode ("mov", "%s,_bp", spname);
2639 /* if use external stack but some variables were
2640 added to the local stack then decrement the
2642 if (options.useXstack && sym->stack)
2644 emitcode ("mov", "a,sp");
2645 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2646 emitcode ("mov", "sp,a");
2650 if ((IS_RENT (sym->etype) || options.stackAuto))
2652 if (options.useXstack)
2654 emitcode ("mov", "r0,%s", spname);
2655 emitcode ("movx", "a,@r0");
2656 emitcode ("mov", "_bp,a");
2657 emitcode ("dec", "%s", spname);
2661 emitcode ("pop", "_bp");
2665 /* restore the register bank */
2666 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2667 emitcode ("pop", "psw");
2669 if (IS_ISR (sym->etype))
2672 /* now we need to restore the registers */
2673 /* if this isr has no bank i.e. is going to
2674 run with bank 0 , then we need to save more
2676 if (!SPEC_BANK (sym->etype))
2679 /* if this function does not call any other
2680 function then we can be economical and
2681 save only those registers that are used */
2686 /* if any registers used */
2689 /* save the registers used */
2690 for (i = sym->regsUsed->size; i >= 0; i--)
2692 if (bitVectBitValue (sym->regsUsed, i) ||
2693 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2694 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2701 /* this function has a function call cannot
2702 determines register usage so we will have the
2704 unsaverbank (0, ic, FALSE);
2708 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2710 if (options.stack10bit)
2712 emitcode ("pop", "ap");
2713 emitcode ("pop", "dpx1");
2714 emitcode ("pop", "dph1");
2715 emitcode ("pop", "dpl1");
2717 emitcode ("pop", "dps");
2718 emitcode ("pop", "dpx");
2720 if (!inExcludeList ("dph"))
2721 emitcode ("pop", "dph");
2722 if (!inExcludeList ("dpl"))
2723 emitcode ("pop", "dpl");
2724 if (!inExcludeList ("b"))
2725 emitcode ("pop", "b");
2726 if (!inExcludeList ("acc"))
2727 emitcode ("pop", "acc");
2729 if (SPEC_CRTCL (sym->etype))
2730 emitcode ("setb", "ea");
2732 /* if debug then send end of function */
2733 /* if (options.debug && currFunc) { */
2737 emitcode ("", "C$%s$%d$%d$%d ==.",
2738 FileBaseName (ic->filename), currFunc->lastLine,
2739 ic->level, ic->block);
2740 if (IS_STATIC (currFunc->etype))
2741 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2743 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2747 emitcode ("reti", "");
2751 if (SPEC_CRTCL (sym->etype))
2752 emitcode ("setb", "ea");
2754 if (sym->calleeSave)
2758 /* if any registers used */
2761 /* save the registers used */
2762 for (i = sym->regsUsed->size; i >= 0; i--)
2764 if (bitVectBitValue (sym->regsUsed, i) ||
2765 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2766 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2772 /* if debug then send end of function */
2776 emitcode ("", "C$%s$%d$%d$%d ==.",
2777 FileBaseName (ic->filename), currFunc->lastLine,
2778 ic->level, ic->block);
2779 if (IS_STATIC (currFunc->etype))
2780 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2782 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2786 emitcode ("ret", "");
2791 /*-----------------------------------------------------------------*/
2792 /* genRet - generate code for return statement */
2793 /*-----------------------------------------------------------------*/
2797 int size, offset = 0, pushed = 0;
2799 D (emitcode (";", "genRet ");
2802 /* if we have no return value then
2803 just generate the "ret" */
2807 /* we have something to return then
2808 move the return value into place */
2809 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2810 size = AOP_SIZE (IC_LEFT (ic));
2812 _startLazyDPSEvaluation ();
2816 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2818 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2819 FALSE, TRUE, FALSE);
2820 emitcode ("push", "%s", l);
2825 l = aopGet (AOP (IC_LEFT (ic)), offset,
2826 FALSE, FALSE, FALSE);
2827 if (strcmp (fReturn[offset], l))
2828 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2831 _endLazyDPSEvaluation ();
2838 if (strcmp (fReturn[pushed], "a"))
2839 emitcode ("pop", fReturn[pushed]);
2841 emitcode ("pop", "acc");
2844 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2847 /* generate a jump to the return label
2848 if the next is not the return statement */
2849 if (!(ic->next && ic->next->op == LABEL &&
2850 IC_LABEL (ic->next) == returnLabel))
2852 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2856 /*-----------------------------------------------------------------*/
2857 /* genLabel - generates a label */
2858 /*-----------------------------------------------------------------*/
2860 genLabel (iCode * ic)
2862 /* special case never generate */
2863 if (IC_LABEL (ic) == entryLabel)
2866 D (emitcode (";", "genLabel ");
2869 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2872 /*-----------------------------------------------------------------*/
2873 /* genGoto - generates a ljmp */
2874 /*-----------------------------------------------------------------*/
2876 genGoto (iCode * ic)
2878 D (emitcode (";", "genGoto ");
2880 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2883 /*-----------------------------------------------------------------*/
2884 /* findLabelBackwards: walks back through the iCode chain looking */
2885 /* for the given label. Returns number of iCode instructions */
2886 /* between that label and given ic. */
2887 /* Returns zero if label not found. */
2888 /*-----------------------------------------------------------------*/
2890 findLabelBackwards (iCode * ic, int key)
2899 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2901 /* printf("findLabelBackwards = %d\n", count); */
2909 /*-----------------------------------------------------------------*/
2910 /* genPlusIncr :- does addition with increment if possible */
2911 /*-----------------------------------------------------------------*/
2913 genPlusIncr (iCode * ic)
2915 unsigned int icount;
2916 unsigned int size = getDataSize (IC_RESULT (ic));
2918 /* will try to generate an increment */
2919 /* if the right side is not a literal
2921 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2924 /* if the literal value of the right hand side
2925 is greater than 4 then it is not worth it */
2926 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2929 /* if increment 16 bits in register */
2931 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2932 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2933 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2941 /* If the next instruction is a goto and the goto target
2942 * is <= 5 instructions previous to this, we can generate
2943 * jumps straight to that target.
2945 if (ic->next && ic->next->op == GOTO
2946 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2949 emitcode (";", "tail increment optimized (range %d)", labelRange);
2950 tlbl = IC_LABEL (ic->next);
2955 tlbl = newiTempLabel (NULL);
2958 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2959 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2960 IS_AOP_PREG (IC_RESULT (ic)))
2961 emitcode ("cjne", "%s,#0x00,%05d$"
2962 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2966 emitcode ("clr", "a");
2967 emitcode ("cjne", "a,%s,%05d$"
2968 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2972 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2975 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2976 IS_AOP_PREG (IC_RESULT (ic)))
2977 emitcode ("cjne", "%s,#0x00,%05d$"
2978 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2981 emitcode ("cjne", "a,%s,%05d$"
2982 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2985 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2989 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2990 IS_AOP_PREG (IC_RESULT (ic)))
2991 emitcode ("cjne", "%s,#0x00,%05d$"
2992 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
2996 emitcode ("cjne", "a,%s,%05d$"
2997 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3000 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3005 emitcode ("", "%05d$:", tlbl->key + 100);
3010 /* if the sizes are greater than 1 then we cannot */
3011 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3012 AOP_SIZE (IC_LEFT (ic)) > 1)
3015 /* we can if the aops of the left & result match or
3016 if they are in registers and the registers are the
3019 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3020 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3021 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3026 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3027 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3028 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3033 _startLazyDPSEvaluation ();
3036 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3038 _endLazyDPSEvaluation ();
3047 /*-----------------------------------------------------------------*/
3048 /* outBitAcc - output a bit in acc */
3049 /*-----------------------------------------------------------------*/
3051 outBitAcc (operand * result)
3053 symbol *tlbl = newiTempLabel (NULL);
3054 /* if the result is a bit */
3055 if (AOP_TYPE (result) == AOP_CRY)
3057 aopPut (AOP (result), "a", 0);
3061 emitcode ("jz", "%05d$", tlbl->key + 100);
3062 emitcode ("mov", "a,%s", one);
3063 emitcode ("", "%05d$:", tlbl->key + 100);
3068 /*-----------------------------------------------------------------*/
3069 /* genPlusBits - generates code for addition of two bits */
3070 /*-----------------------------------------------------------------*/
3072 genPlusBits (iCode * ic)
3074 D (emitcode (";", "genPlusBits ");
3076 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3078 symbol *lbl = newiTempLabel (NULL);
3079 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3080 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3081 emitcode ("cpl", "c");
3082 emitcode ("", "%05d$:", (lbl->key + 100));
3083 outBitC (IC_RESULT (ic));
3087 emitcode ("clr", "a");
3088 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3089 emitcode ("rlc", "a");
3090 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3091 emitcode ("addc", "a,#0x00");
3092 outAcc (IC_RESULT (ic));
3097 adjustArithmeticResult (iCode * ic)
3099 if (opIsGptr (IC_RESULT (ic)) &&
3100 opIsGptr (IC_LEFT (ic)) &&
3101 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3103 aopPut (AOP (IC_RESULT (ic)),
3104 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3108 if (opIsGptr (IC_RESULT (ic)) &&
3109 opIsGptr (IC_RIGHT (ic)) &&
3110 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3112 aopPut (AOP (IC_RESULT (ic)),
3113 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3117 if (opIsGptr (IC_RESULT (ic)) &&
3118 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3119 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3120 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3121 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3124 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3125 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3129 #define AOP_OP_3(ic) \
3130 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3131 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3132 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3133 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3134 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3135 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3137 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3139 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3142 #define AOP_OP_3_NOFATAL(ic, rc) \
3143 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3144 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3145 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3146 isOperandInFarSpace(IC_RESULT(ic))) \
3148 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3153 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3154 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3156 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3157 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3159 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3161 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3165 #define AOP_OP_2(ic) \
3166 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3167 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3169 #define AOP_SET_LOCALS(ic) \
3170 left = IC_LEFT(ic); \
3171 right = IC_RIGHT(ic); \
3172 result = IC_RESULT(ic);
3174 /*-----------------------------------------------------------------*/
3175 /* genPlus - generates code for addition */
3176 /*-----------------------------------------------------------------*/
3178 genPlus (iCode * ic)
3180 int size, offset = 0;
3181 bool pushResult = FALSE;
3184 D (emitcode (";", "genPlus ");
3187 /* special cases :- */
3189 AOP_OP_3_NOFATAL (ic, pushResult);
3192 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3198 /* if literal, literal on the right or
3199 if left requires ACC or right is already
3201 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3202 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3203 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3205 operand *t = IC_RIGHT (ic);
3206 IC_RIGHT (ic) = IC_LEFT (ic);
3208 emitcode (";", "Swapped plus args.");
3211 /* if both left & right are in bit
3213 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3214 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3220 /* if left in bit space & right literal */
3221 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3222 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3224 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3225 /* if result in bit space */
3226 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3228 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3229 emitcode ("cpl", "c");
3230 outBitC (IC_RESULT (ic));
3234 size = getDataSize (IC_RESULT (ic));
3235 _startLazyDPSEvaluation ();
3238 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3239 emitcode ("addc", "a,#00");
3240 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3242 _endLazyDPSEvaluation ();
3247 /* if I can do an increment instead
3248 of add then GOOD for ME */
3249 if (genPlusIncr (ic) == TRUE)
3251 emitcode (";", "did genPlusIncr");
3256 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3258 _startLazyDPSEvaluation ();
3261 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3263 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3265 emitcode ("add", "a,%s",
3266 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3268 emitcode ("addc", "a,%s",
3269 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3273 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3275 emitcode ("add", "a,%s",
3276 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3278 emitcode ("addc", "a,%s",
3279 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3283 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3287 emitcode ("push", "acc");
3291 _endLazyDPSEvaluation ();
3295 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3297 size = getDataSize (IC_LEFT (ic));
3298 rSize = getDataSize (IC_RESULT (ic));
3300 /* If the pushed data is bigger than the result,
3301 * simply discard unused bytes. Icky, but works.
3303 * Should we throw a warning here? We're losing data...
3305 while (size > rSize)
3307 D (emitcode (";", "discarding unused result byte.");
3309 emitcode ("pop", "acc");
3315 emitcode ("clr", "a");
3316 /* Conversly, we haven't pushed enough here.
3317 * just zero-pad, and all is well.
3319 while (size < rSize)
3321 emitcode ("push", "acc");
3327 _startLazyDPSEvaluation ();
3330 emitcode ("pop", "acc");
3331 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3333 _endLazyDPSEvaluation ();
3336 adjustArithmeticResult (ic);
3339 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3340 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3341 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3344 /*-----------------------------------------------------------------*/
3345 /* genMinusDec :- does subtraction with deccrement if possible */
3346 /*-----------------------------------------------------------------*/
3348 genMinusDec (iCode * ic)
3350 unsigned int icount;
3351 unsigned int size = getDataSize (IC_RESULT (ic));
3353 /* will try to generate an increment */
3354 /* if the right side is not a literal
3356 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3359 /* if the literal value of the right hand side
3360 is greater than 4 then it is not worth it */
3361 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3364 /* if decrement 16 bits in register */
3365 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3366 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3367 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3375 /* If the next instruction is a goto and the goto target
3376 * is <= 5 instructions previous to this, we can generate
3377 * jumps straight to that target.
3379 if (ic->next && ic->next->op == GOTO
3380 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3383 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3384 tlbl = IC_LABEL (ic->next);
3389 tlbl = newiTempLabel (NULL);
3393 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3394 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3395 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3396 IS_AOP_PREG (IC_RESULT (ic)))
3397 emitcode ("cjne", "%s,#0xff,%05d$"
3398 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3402 emitcode ("mov", "a,#0xff");
3403 emitcode ("cjne", "a,%s,%05d$"
3404 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3407 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, 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)), MSB16, FALSE, FALSE, FALSE)
3418 emitcode ("cjne", "a,%s,%05d$"
3419 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3422 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, 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)), MSB24, FALSE, FALSE, FALSE)
3434 emitcode ("cjne", "a,%s,%05d$"
3435 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3438 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3442 emitcode ("", "%05d$:", tlbl->key + 100);
3447 /* if the sizes are greater than 1 then we cannot */
3448 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3449 AOP_SIZE (IC_LEFT (ic)) > 1)
3452 /* we can if the aops of the left & result match or
3453 if they are in registers and the registers are the
3456 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3457 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3458 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3461 _startLazyDPSEvaluation ();
3464 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3466 _endLazyDPSEvaluation ();
3474 /*-----------------------------------------------------------------*/
3475 /* addSign - complete with sign */
3476 /*-----------------------------------------------------------------*/
3478 addSign (operand * result, int offset, int sign)
3480 int size = (getDataSize (result) - offset);
3485 emitcode ("rlc", "a");
3486 emitcode ("subb", "a,acc");
3488 aopPut (AOP (result), "a", offset++);
3492 aopPut (AOP (result), zero, offset++);
3496 /*-----------------------------------------------------------------*/
3497 /* genMinusBits - generates code for subtraction of two bits */
3498 /*-----------------------------------------------------------------*/
3500 genMinusBits (iCode * ic)
3502 symbol *lbl = newiTempLabel (NULL);
3504 D (emitcode (";", "genMinusBits ");
3507 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3509 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3510 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3511 emitcode ("cpl", "c");
3512 emitcode ("", "%05d$:", (lbl->key + 100));
3513 outBitC (IC_RESULT (ic));
3517 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3518 emitcode ("subb", "a,acc");
3519 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3520 emitcode ("inc", "a");
3521 emitcode ("", "%05d$:", (lbl->key + 100));
3522 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3523 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3527 /*-----------------------------------------------------------------*/
3528 /* genMinus - generates code for subtraction */
3529 /*-----------------------------------------------------------------*/
3531 genMinus (iCode * ic)
3533 int size, offset = 0;
3535 unsigned long lit = 0L;
3536 bool pushResult = FALSE;
3538 D (emitcode (";", "genMinus ");
3541 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3542 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3543 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3544 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3550 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3552 /* special cases :- */
3553 /* if both left & right are in bit space */
3554 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3555 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3561 /* if I can do an decrement instead
3562 of subtract then GOOD for ME */
3563 if (genMinusDec (ic) == TRUE)
3568 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3570 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3576 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3581 /* if literal, add a,#-lit, else normal subb */
3582 _startLazyDPSEvaluation ();
3585 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3586 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3587 emitcode ("subb", "a,%s",
3588 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3591 /* first add without previous c */
3593 emitcode ("add", "a,#0x%02x",
3594 (unsigned int) (lit & 0x0FFL));
3596 emitcode ("addc", "a,#0x%02x",
3597 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3602 emitcode ("push", "acc");
3606 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3610 _endLazyDPSEvaluation ();
3614 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3616 size = getDataSize (IC_LEFT (ic));
3617 rSize = getDataSize (IC_RESULT (ic));
3619 /* If the pushed data is bigger than the result,
3620 * simply discard unused bytes. Icky, but works.
3622 * Should we throw a warning here? We're losing data...
3624 while (size > getDataSize (IC_RESULT (ic)))
3626 emitcode (";", "discarding unused result byte.");
3627 emitcode ("pop", "acc");
3633 emitcode ("clr", "a");
3634 /* Conversly, we haven't pushed enough here.
3635 * just zero-pad, and all is well.
3637 while (size < rSize)
3639 emitcode ("push", "acc");
3647 emitcode ("pop", "acc");
3648 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3652 adjustArithmeticResult (ic);
3655 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3656 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3657 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3661 /*-----------------------------------------------------------------*/
3662 /* genMultbits :- multiplication of bits */
3663 /*-----------------------------------------------------------------*/
3665 genMultbits (operand * left,
3669 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3670 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3675 /*-----------------------------------------------------------------*/
3676 /* genMultOneByte : 8*8=8/16 bit multiplication */
3677 /*-----------------------------------------------------------------*/
3679 genMultOneByte (operand * left,
3683 sym_link *opetype = operandType (result);
3685 int size=AOP_SIZE(result);
3687 emitcode (";",__FUNCTION__);
3688 if (size<1 || size>2) {
3689 // this should never happen
3690 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3691 AOP_SIZE(result), __FUNCTION__, lineno);
3695 /* (if two literals: the value is computed before) */
3696 /* if one literal, literal on the right */
3697 if (AOP_TYPE (left) == AOP_LIT)
3702 emitcode (";", "swapped left and right");
3705 if (SPEC_USIGN(opetype)
3706 // ignore the sign of left and right, what else can we do?
3707 || (SPEC_USIGN(operandType(left)) &&
3708 SPEC_USIGN(operandType(right)))) {
3709 // just an unsigned 8*8=8/16 multiply
3710 //emitcode (";","unsigned");
3711 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3712 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3713 emitcode ("mul", "ab");
3714 aopPut (AOP (result), "a", 0);
3716 aopPut (AOP (result), "b", 1);
3721 // we have to do a signed multiply
3723 emitcode (";", "signed");
3724 emitcode ("clr", "F0"); // reset sign flag
3725 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3726 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3728 lbl=newiTempLabel(NULL);
3729 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3730 // left side is negative, 8-bit two's complement, this fails for -128
3731 emitcode ("setb", "F0"); // set sign flag
3732 emitcode ("cpl", "a");
3733 emitcode ("inc", "a");
3735 emitcode ("", "%05d$:", lbl->key+100);
3736 emitcode ("xch", "a,b");
3739 if (AOP_TYPE(right)==AOP_LIT) {
3740 /* AND literal negative */
3741 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3742 // two's complement for literal<0
3743 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3744 emitcode ("cpl", "a");
3745 emitcode ("inc", "a");
3748 lbl=newiTempLabel(NULL);
3749 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3750 // right side is negative, 8-bit two's complement
3751 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3752 emitcode ("cpl", "a");
3753 emitcode ("inc", "a");
3754 emitcode ("", "%05d$:", lbl->key+100);
3756 emitcode ("mul", "ab");
3758 lbl=newiTempLabel(NULL);
3759 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3760 // only ONE op was negative, we have to do a 8/16-bit two's complement
3761 emitcode ("cpl", "a"); // lsb
3763 emitcode ("inc", "a");
3765 emitcode ("add", "a,#1");
3766 emitcode ("xch", "a,b");
3767 emitcode ("cpl", "a"); // msb
3768 emitcode ("addc", "a,#0");
3769 emitcode ("xch", "a,b");
3772 emitcode ("", "%05d$:", lbl->key+100);
3773 aopPut (AOP (result), "a", 0);
3775 aopPut (AOP (result), "b", 1);
3779 /*-----------------------------------------------------------------*/
3780 /* genMult - generates code for multiplication */
3781 /*-----------------------------------------------------------------*/
3783 genMult (iCode * ic)
3785 operand *left = IC_LEFT (ic);
3786 operand *right = IC_RIGHT (ic);
3787 operand *result = IC_RESULT (ic);
3789 D (emitcode (";", "genMult ");
3792 /* assign the amsops */
3795 /* special cases first */
3797 if (AOP_TYPE (left) == AOP_CRY &&
3798 AOP_TYPE (right) == AOP_CRY)
3800 genMultbits (left, right, result);
3804 /* if both are of size == 1 */
3805 if (AOP_SIZE (left) == 1 &&
3806 AOP_SIZE (right) == 1)
3808 genMultOneByte (left, right, result);
3812 /* should have been converted to function call */
3816 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3817 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3818 freeAsmop (result, NULL, ic, TRUE);
3821 /*-----------------------------------------------------------------*/
3822 /* genDivbits :- division of bits */
3823 /*-----------------------------------------------------------------*/
3825 genDivbits (operand * left,
3832 /* the result must be bit */
3833 LOAD_AB_FOR_DIV (left, right, l);
3834 emitcode ("div", "ab");
3835 emitcode ("rrc", "a");
3836 aopPut (AOP (result), "c", 0);
3839 /*-----------------------------------------------------------------*/
3840 /* genDivOneByte : 8 bit division */
3841 /*-----------------------------------------------------------------*/
3843 genDivOneByte (operand * left,
3847 sym_link *opetype = operandType (result);
3852 size = AOP_SIZE (result) - 1;
3854 /* signed or unsigned */
3855 if (SPEC_USIGN (opetype))
3857 /* unsigned is easy */
3858 LOAD_AB_FOR_DIV (left, right, l);
3859 emitcode ("div", "ab");
3860 aopPut (AOP (result), "a", 0);
3862 aopPut (AOP (result), zero, offset++);
3866 /* signed is a little bit more difficult */
3868 /* save the signs of the operands */
3869 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3871 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3872 emitcode ("push", "acc"); /* save it on the stack */
3874 /* now sign adjust for both left & right */
3875 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3877 lbl = newiTempLabel (NULL);
3878 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3879 emitcode ("cpl", "a");
3880 emitcode ("inc", "a");
3881 emitcode ("", "%05d$:", (lbl->key + 100));
3882 emitcode ("mov", "b,a");
3884 /* sign adjust left side */
3885 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3888 lbl = newiTempLabel (NULL);
3889 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3890 emitcode ("cpl", "a");
3891 emitcode ("inc", "a");
3892 emitcode ("", "%05d$:", (lbl->key + 100));
3894 /* now the division */
3895 emitcode ("nop", "; workaround for DS80C390 div bug.");
3896 emitcode ("div", "ab");
3897 /* we are interested in the lower order
3899 emitcode ("mov", "b,a");
3900 lbl = newiTempLabel (NULL);
3901 emitcode ("pop", "acc");
3902 /* if there was an over flow we don't
3903 adjust the sign of the result */
3904 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3905 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3907 emitcode ("clr", "a");
3908 emitcode ("subb", "a,b");
3909 emitcode ("mov", "b,a");
3910 emitcode ("", "%05d$:", (lbl->key + 100));
3912 /* now we are done */
3913 aopPut (AOP (result), "b", 0);
3916 emitcode ("mov", "c,b.7");
3917 emitcode ("subb", "a,acc");
3920 aopPut (AOP (result), "a", offset++);
3924 /*-----------------------------------------------------------------*/
3925 /* genDiv - generates code for division */
3926 /*-----------------------------------------------------------------*/
3930 operand *left = IC_LEFT (ic);
3931 operand *right = IC_RIGHT (ic);
3932 operand *result = IC_RESULT (ic);
3934 D (emitcode (";", "genDiv ");
3937 /* assign the amsops */
3940 /* special cases first */
3942 if (AOP_TYPE (left) == AOP_CRY &&
3943 AOP_TYPE (right) == AOP_CRY)
3945 genDivbits (left, right, result);
3949 /* if both are of size == 1 */
3950 if (AOP_SIZE (left) == 1 &&
3951 AOP_SIZE (right) == 1)
3953 genDivOneByte (left, right, result);
3957 /* should have been converted to function call */
3960 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3961 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3962 freeAsmop (result, NULL, ic, TRUE);
3965 /*-----------------------------------------------------------------*/
3966 /* genModbits :- modulus of bits */
3967 /*-----------------------------------------------------------------*/
3969 genModbits (operand * left,
3976 /* the result must be bit */
3977 LOAD_AB_FOR_DIV (left, right, l);
3978 emitcode ("div", "ab");
3979 emitcode ("mov", "a,b");
3980 emitcode ("rrc", "a");
3981 aopPut (AOP (result), "c", 0);
3984 /*-----------------------------------------------------------------*/
3985 /* genModOneByte : 8 bit modulus */
3986 /*-----------------------------------------------------------------*/
3988 genModOneByte (operand * left,
3992 sym_link *opetype = operandType (result);
3996 /* signed or unsigned */
3997 if (SPEC_USIGN (opetype))
3999 /* unsigned is easy */
4000 LOAD_AB_FOR_DIV (left, right, l);
4001 emitcode ("div", "ab");
4002 aopPut (AOP (result), "b", 0);
4006 /* signed is a little bit more difficult */
4008 /* save the signs of the operands */
4009 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4012 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4013 emitcode ("push", "acc"); /* save it on the stack */
4015 /* now sign adjust for both left & right */
4016 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4019 lbl = newiTempLabel (NULL);
4020 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4021 emitcode ("cpl", "a");
4022 emitcode ("inc", "a");
4023 emitcode ("", "%05d$:", (lbl->key + 100));
4024 emitcode ("mov", "b,a");
4026 /* sign adjust left side */
4027 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4030 lbl = newiTempLabel (NULL);
4031 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4032 emitcode ("cpl", "a");
4033 emitcode ("inc", "a");
4034 emitcode ("", "%05d$:", (lbl->key + 100));
4036 /* now the multiplication */
4037 emitcode ("nop", "; workaround for DS80C390 div bug.");
4038 emitcode ("div", "ab");
4039 /* we are interested in the lower order
4041 lbl = newiTempLabel (NULL);
4042 emitcode ("pop", "acc");
4043 /* if there was an over flow we don't
4044 adjust the sign of the result */
4045 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4046 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4048 emitcode ("clr", "a");
4049 emitcode ("subb", "a,b");
4050 emitcode ("mov", "b,a");
4051 emitcode ("", "%05d$:", (lbl->key + 100));
4053 /* now we are done */
4054 aopPut (AOP (result), "b", 0);
4058 /*-----------------------------------------------------------------*/
4059 /* genMod - generates code for division */
4060 /*-----------------------------------------------------------------*/
4064 operand *left = IC_LEFT (ic);
4065 operand *right = IC_RIGHT (ic);
4066 operand *result = IC_RESULT (ic);
4068 D (emitcode (";", "genMod ");
4071 /* assign the amsops */
4074 /* special cases first */
4076 if (AOP_TYPE (left) == AOP_CRY &&
4077 AOP_TYPE (right) == AOP_CRY)
4079 genModbits (left, right, result);
4083 /* if both are of size == 1 */
4084 if (AOP_SIZE (left) == 1 &&
4085 AOP_SIZE (right) == 1)
4087 genModOneByte (left, right, result);
4091 /* should have been converted to function call */
4095 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4096 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097 freeAsmop (result, NULL, ic, TRUE);
4100 /*-----------------------------------------------------------------*/
4101 /* genIfxJump :- will create a jump depending on the ifx */
4102 /*-----------------------------------------------------------------*/
4104 genIfxJump (iCode * ic, char *jval)
4107 symbol *tlbl = newiTempLabel (NULL);
4110 D (emitcode (";", "genIfxJump ");
4113 /* if true label then we jump if condition
4117 jlbl = IC_TRUE (ic);
4118 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4119 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4123 /* false label is present */
4124 jlbl = IC_FALSE (ic);
4125 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4126 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4128 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4129 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4131 emitcode (inst, "%05d$", tlbl->key + 100);
4132 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4133 emitcode ("", "%05d$:", tlbl->key + 100);
4135 /* mark the icode as generated */
4139 /*-----------------------------------------------------------------*/
4140 /* genCmp :- greater or less than comparison */
4141 /*-----------------------------------------------------------------*/
4143 genCmp (operand * left, operand * right,
4144 iCode * ic, iCode * ifx, int sign)
4146 int size, offset = 0;
4147 unsigned long lit = 0L;
4150 D (emitcode (";", "genCmp");
4153 result = IC_RESULT (ic);
4155 /* if left & right are bit variables */
4156 if (AOP_TYPE (left) == AOP_CRY &&
4157 AOP_TYPE (right) == AOP_CRY)
4159 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4160 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4164 /* subtract right from left if at the
4165 end the carry flag is set then we know that
4166 left is greater than right */
4167 size = max (AOP_SIZE (left), AOP_SIZE (right));
4169 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4170 if ((size == 1) && !sign &&
4171 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4173 symbol *lbl = newiTempLabel (NULL);
4174 emitcode ("cjne", "%s,%s,%05d$",
4175 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4176 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4178 emitcode ("", "%05d$:", lbl->key + 100);
4182 if (AOP_TYPE (right) == AOP_LIT)
4184 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4185 /* optimize if(x < 0) or if(x >= 0) */
4194 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4196 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4197 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4199 aopOp (result, ic, FALSE, FALSE);
4201 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4203 freeAsmop (result, NULL, ic, TRUE);
4204 genIfxJump (ifx, "acc.7");
4209 emitcode ("rlc", "a");
4211 goto release_freedLR;
4219 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4220 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4221 emitcode (";", "genCmp #2");
4222 if (sign && (size == 0))
4224 emitcode (";", "genCmp #3");
4225 emitcode ("xrl", "a,#0x80");
4226 if (AOP_TYPE (right) == AOP_LIT)
4228 unsigned long lit = (unsigned long)
4229 floatFromVal (AOP (right)->aopu.aop_lit);
4230 emitcode (";", "genCmp #3.1");
4231 emitcode ("subb", "a,#0x%02x",
4232 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4236 emitcode (";", "genCmp #3.2");
4237 if (AOP_NEEDSACC (right))
4239 emitcode ("push", "acc");
4241 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4242 FALSE, FALSE, FALSE));
4243 emitcode ("xrl", "b,#0x80");
4244 if (AOP_NEEDSACC (right))
4246 emitcode ("pop", "acc");
4248 emitcode ("subb", "a,b");
4255 emitcode (";", "genCmp #4");
4256 if (AOP_NEEDSACC (right))
4259 emitcode (";", "genCmp #4.1");
4260 emitcode ("xch", "a, b");
4261 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4262 emitcode ("xch", "a, b");
4267 emitcode (";", "genCmp #4.2");
4268 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4271 emitcode ("subb", "a,%s", s);
4278 /* Don't need the left & right operands any more; do need the result. */
4279 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4280 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4282 aopOp (result, ic, FALSE, FALSE);
4286 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4292 /* if the result is used in the next
4293 ifx conditional branch then generate
4294 code a little differently */
4297 genIfxJump (ifx, "c");
4303 /* leave the result in acc */
4305 freeAsmop (result, NULL, ic, TRUE);
4308 /*-----------------------------------------------------------------*/
4309 /* genCmpGt :- greater than comparison */
4310 /*-----------------------------------------------------------------*/
4312 genCmpGt (iCode * ic, iCode * ifx)
4314 operand *left, *right;
4315 sym_link *letype, *retype;
4318 D (emitcode (";", "genCmpGt ");
4321 left = IC_LEFT (ic);
4322 right = IC_RIGHT (ic);
4324 letype = getSpec (operandType (left));
4325 retype = getSpec (operandType (right));
4326 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4328 /* assign the left & right amsops */
4331 genCmp (right, left, ic, ifx, sign);
4334 /*-----------------------------------------------------------------*/
4335 /* genCmpLt - less than comparisons */
4336 /*-----------------------------------------------------------------*/
4338 genCmpLt (iCode * ic, iCode * ifx)
4340 operand *left, *right;
4341 sym_link *letype, *retype;
4344 D (emitcode (";", "genCmpLt ");
4347 left = IC_LEFT (ic);
4348 right = IC_RIGHT (ic);
4350 letype = getSpec (operandType (left));
4351 retype = getSpec (operandType (right));
4352 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4354 /* assign the left & right amsops */
4357 genCmp (left, right, ic, ifx, sign);
4360 /*-----------------------------------------------------------------*/
4361 /* gencjneshort - compare and jump if not equal */
4362 /*-----------------------------------------------------------------*/
4364 gencjneshort (operand * left, operand * right, symbol * lbl)
4366 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4368 unsigned long lit = 0L;
4370 D (emitcode (";", "gencjneshort");
4373 /* if the left side is a literal or
4374 if the right is in a pointer register and left
4376 if ((AOP_TYPE (left) == AOP_LIT) ||
4377 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4384 if (AOP_TYPE (right) == AOP_LIT)
4385 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4387 if (opIsGptr (left) || opIsGptr (right))
4389 /* We are comparing a generic pointer to something.
4390 * Exclude the generic type byte from the comparison.
4393 D (emitcode (";", "cjneshort: generic ptr special case.");
4398 /* if the right side is a literal then anything goes */
4399 if (AOP_TYPE (right) == AOP_LIT &&
4400 AOP_TYPE (left) != AOP_DIR)
4404 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4406 emitcode ("cjne", "a,%s,%05d$",
4407 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4413 /* if the right side is in a register or in direct space or
4414 if the left is a pointer register & right is not */
4415 else if (AOP_TYPE (right) == AOP_REG ||
4416 AOP_TYPE (right) == AOP_DIR ||
4417 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4418 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4422 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4423 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4424 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4425 emitcode ("jnz", "%05d$", lbl->key + 100);
4427 emitcode ("cjne", "a,%s,%05d$",
4428 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4435 /* right is a pointer reg need both a & b */
4438 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4439 if (strcmp (l, "b"))
4440 emitcode ("mov", "b,%s", l);
4441 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4442 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4448 /*-----------------------------------------------------------------*/
4449 /* gencjne - compare and jump if not equal */
4450 /*-----------------------------------------------------------------*/
4452 gencjne (operand * left, operand * right, symbol * lbl)
4454 symbol *tlbl = newiTempLabel (NULL);
4456 D (emitcode (";", "gencjne");
4459 gencjneshort (left, right, lbl);
4461 emitcode ("mov", "a,%s", one);
4462 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4463 emitcode ("", "%05d$:", lbl->key + 100);
4464 emitcode ("clr", "a");
4465 emitcode ("", "%05d$:", tlbl->key + 100);
4468 /*-----------------------------------------------------------------*/
4469 /* genCmpEq - generates code for equal to */
4470 /*-----------------------------------------------------------------*/
4472 genCmpEq (iCode * ic, iCode * ifx)
4474 operand *left, *right, *result;
4476 D (emitcode (";", "genCmpEq ");
4480 AOP_SET_LOCALS (ic);
4482 /* if literal, literal on the right or
4483 if the right is in a pointer register and left
4485 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4486 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4488 operand *t = IC_RIGHT (ic);
4489 IC_RIGHT (ic) = IC_LEFT (ic);
4493 if (ifx && /* !AOP_SIZE(result) */
4494 OP_SYMBOL (result) &&
4495 OP_SYMBOL (result)->regType == REG_CND)
4498 /* if they are both bit variables */
4499 if (AOP_TYPE (left) == AOP_CRY &&
4500 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4502 if (AOP_TYPE (right) == AOP_LIT)
4504 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4508 emitcode ("cpl", "c");
4512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4516 emitcode ("clr", "c");
4518 /* AOP_TYPE(right) == AOP_CRY */
4522 symbol *lbl = newiTempLabel (NULL);
4523 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4524 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4525 emitcode ("cpl", "c");
4526 emitcode ("", "%05d$:", (lbl->key + 100));
4528 /* if true label then we jump if condition
4530 tlbl = newiTempLabel (NULL);
4533 emitcode ("jnc", "%05d$", tlbl->key + 100);
4534 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4538 emitcode ("jc", "%05d$", tlbl->key + 100);
4539 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4541 emitcode ("", "%05d$:", tlbl->key + 100);
4545 tlbl = newiTempLabel (NULL);
4546 gencjneshort (left, right, tlbl);
4549 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4550 emitcode ("", "%05d$:", tlbl->key + 100);
4554 symbol *lbl = newiTempLabel (NULL);
4555 emitcode ("sjmp", "%05d$", lbl->key + 100);
4556 emitcode ("", "%05d$:", tlbl->key + 100);
4557 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4558 emitcode ("", "%05d$:", lbl->key + 100);
4561 /* mark the icode as generated */
4564 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4569 /* if they are both bit variables */
4570 if (AOP_TYPE (left) == AOP_CRY &&
4571 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4573 if (AOP_TYPE (right) == AOP_LIT)
4575 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4578 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579 emitcode ("cpl", "c");
4583 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4587 emitcode ("clr", "c");
4589 /* AOP_TYPE(right) == AOP_CRY */
4593 symbol *lbl = newiTempLabel (NULL);
4594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4595 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4596 emitcode ("cpl", "c");
4597 emitcode ("", "%05d$:", (lbl->key + 100));
4600 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4601 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603 aopOp (result, ic, TRUE, FALSE);
4606 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4613 genIfxJump (ifx, "c");
4616 /* if the result is used in an arithmetic operation
4617 then put the result in place */
4622 gencjne (left, right, newiTempLabel (NULL));
4624 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4625 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4627 aopOp (result, ic, TRUE, FALSE);
4629 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4631 aopPut (AOP (result), "a", 0);
4636 genIfxJump (ifx, "a");
4639 /* if the result is used in an arithmetic operation
4640 then put the result in place */
4641 if (AOP_TYPE (result) != AOP_CRY)
4643 /* leave the result in acc */
4647 freeAsmop (result, NULL, ic, TRUE);
4650 /*-----------------------------------------------------------------*/
4651 /* ifxForOp - returns the icode containing the ifx for operand */
4652 /*-----------------------------------------------------------------*/
4654 ifxForOp (operand * op, iCode * ic)
4656 /* if true symbol then needs to be assigned */
4657 if (IS_TRUE_SYMOP (op))
4660 /* if this has register type condition and
4661 the next instruction is ifx with the same operand
4662 and live to of the operand is upto the ifx only then */
4664 ic->next->op == IFX &&
4665 IC_COND (ic->next)->key == op->key &&
4666 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4671 /*-----------------------------------------------------------------*/
4672 /* genAndOp - for && operation */
4673 /*-----------------------------------------------------------------*/
4675 genAndOp (iCode * ic)
4677 operand *left, *right, *result;
4680 D (emitcode (";", "genAndOp ");
4683 /* note here that && operations that are in an
4684 if statement are taken away by backPatchLabels
4685 only those used in arthmetic operations remain */
4687 AOP_SET_LOCALS (ic);
4689 /* if both are bit variables */
4690 if (AOP_TYPE (left) == AOP_CRY &&
4691 AOP_TYPE (right) == AOP_CRY)
4693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4694 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4699 tlbl = newiTempLabel (NULL);
4701 emitcode ("jz", "%05d$", tlbl->key + 100);
4703 emitcode ("", "%05d$:", tlbl->key + 100);
4707 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4708 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4709 freeAsmop (result, NULL, ic, TRUE);
4713 /*-----------------------------------------------------------------*/
4714 /* genOrOp - for || operation */
4715 /*-----------------------------------------------------------------*/
4717 genOrOp (iCode * ic)
4719 operand *left, *right, *result;
4722 D (emitcode (";", "genOrOp ");
4725 /* note here that || operations that are in an
4726 if statement are taken away by backPatchLabels
4727 only those used in arthmetic operations remain */
4729 AOP_SET_LOCALS (ic);
4731 /* if both are bit variables */
4732 if (AOP_TYPE (left) == AOP_CRY &&
4733 AOP_TYPE (right) == AOP_CRY)
4735 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4736 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4741 tlbl = newiTempLabel (NULL);
4743 emitcode ("jnz", "%05d$", tlbl->key + 100);
4745 emitcode ("", "%05d$:", tlbl->key + 100);
4749 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4751 freeAsmop (result, NULL, ic, TRUE);
4754 /*-----------------------------------------------------------------*/
4755 /* isLiteralBit - test if lit == 2^n */
4756 /*-----------------------------------------------------------------*/
4758 isLiteralBit (unsigned long lit)
4760 unsigned long pw[32] =
4761 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4762 0x100L, 0x200L, 0x400L, 0x800L,
4763 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4764 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4765 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4766 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4767 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4770 for (idx = 0; idx < 32; idx++)
4776 /*-----------------------------------------------------------------*/
4777 /* continueIfTrue - */
4778 /*-----------------------------------------------------------------*/
4780 continueIfTrue (iCode * ic)
4783 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4787 /*-----------------------------------------------------------------*/
4789 /*-----------------------------------------------------------------*/
4791 jumpIfTrue (iCode * ic)
4794 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4798 /*-----------------------------------------------------------------*/
4799 /* jmpTrueOrFalse - */
4800 /*-----------------------------------------------------------------*/
4802 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4804 // ugly but optimized by peephole
4807 symbol *nlbl = newiTempLabel (NULL);
4808 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4809 emitcode ("", "%05d$:", tlbl->key + 100);
4810 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4811 emitcode ("", "%05d$:", nlbl->key + 100);
4815 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4816 emitcode ("", "%05d$:", tlbl->key + 100);
4821 /*-----------------------------------------------------------------*/
4822 /* genAnd - code for and */
4823 /*-----------------------------------------------------------------*/
4825 genAnd (iCode * ic, iCode * ifx)
4827 operand *left, *right, *result;
4828 int size, offset = 0;
4829 unsigned long lit = 0L;
4833 D (emitcode (";", "genAnd ");
4837 AOP_SET_LOCALS (ic);
4840 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4842 AOP_TYPE (left), AOP_TYPE (right));
4843 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4845 AOP_SIZE (left), AOP_SIZE (right));
4848 /* if left is a literal & right is not then exchange them */
4849 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4850 AOP_NEEDSACC (left))
4852 operand *tmp = right;
4857 /* if result = right then exchange them */
4858 if (sameRegs (AOP (result), AOP (right)))
4860 operand *tmp = right;
4865 /* if right is bit then exchange them */
4866 if (AOP_TYPE (right) == AOP_CRY &&
4867 AOP_TYPE (left) != AOP_CRY)
4869 operand *tmp = right;
4873 if (AOP_TYPE (right) == AOP_LIT)
4874 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4876 size = AOP_SIZE (result);
4879 // result = bit & yy;
4880 if (AOP_TYPE (left) == AOP_CRY)
4882 // c = bit & literal;
4883 if (AOP_TYPE (right) == AOP_LIT)
4887 if (size && sameRegs (AOP (result), AOP (left)))
4890 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4895 if (size && (AOP_TYPE (result) == AOP_CRY))
4897 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4900 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4905 emitcode ("clr", "c");
4910 if (AOP_TYPE (right) == AOP_CRY)
4913 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4914 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4919 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4921 emitcode ("rrc", "a");
4922 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4930 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4931 genIfxJump (ifx, "c");
4935 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4936 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4937 if ((AOP_TYPE (right) == AOP_LIT) &&
4938 (AOP_TYPE (result) == AOP_CRY) &&
4939 (AOP_TYPE (left) != AOP_CRY))
4941 int posbit = isLiteralBit (lit);
4946 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4949 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4955 sprintf (buffer, "acc.%d", posbit & 0x07);
4956 genIfxJump (ifx, buffer);
4963 symbol *tlbl = newiTempLabel (NULL);
4964 int sizel = AOP_SIZE (left);
4966 emitcode ("setb", "c");
4969 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4971 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4973 if ((posbit = isLiteralBit (bytelit)) != 0)
4974 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4977 if (bytelit != 0x0FFL)
4978 emitcode ("anl", "a,%s",
4979 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4980 emitcode ("jnz", "%05d$", tlbl->key + 100);
4985 // bit = left & literal
4988 emitcode ("clr", "c");
4989 emitcode ("", "%05d$:", tlbl->key + 100);
4991 // if(left & literal)
4995 jmpTrueOrFalse (ifx, tlbl);
5003 /* if left is same as result */
5004 if (sameRegs (AOP (result), AOP (left)))
5006 for (; size--; offset++)
5008 if (AOP_TYPE (right) == AOP_LIT)
5010 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5012 else if (bytelit == 0)
5013 aopPut (AOP (result), zero, offset);
5014 else if (IS_AOP_PREG (result))
5016 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5017 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5018 aopPut (AOP (result), "a", offset);
5021 emitcode ("anl", "%s,%s",
5022 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5023 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5027 if (AOP_TYPE (left) == AOP_ACC)
5028 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5031 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5032 if (IS_AOP_PREG (result))
5034 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5035 aopPut (AOP (result), "a", offset);
5039 emitcode ("anl", "%s,a",
5040 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5047 // left & result in different registers
5048 if (AOP_TYPE (result) == AOP_CRY)
5051 // if(size), result in bit
5052 // if(!size && ifx), conditional oper: if(left & right)
5053 symbol *tlbl = newiTempLabel (NULL);
5054 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5056 emitcode ("setb", "c");
5059 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5060 emitcode ("anl", "a,%s",
5061 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5062 emitcode ("jnz", "%05d$", tlbl->key + 100);
5068 emitcode ("", "%05d$:", tlbl->key + 100);
5072 jmpTrueOrFalse (ifx, tlbl);
5076 for (; (size--); offset++)
5079 // result = left & right
5080 if (AOP_TYPE (right) == AOP_LIT)
5082 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5084 aopPut (AOP (result),
5085 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5089 else if (bytelit == 0)
5091 aopPut (AOP (result), zero, offset);
5094 D (emitcode (";", "better literal AND.");
5096 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5097 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5098 FALSE, FALSE, FALSE));
5103 // faster than result <- left, anl result,right
5104 // and better if result is SFR
5105 if (AOP_TYPE (left) == AOP_ACC)
5107 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5108 FALSE, FALSE, FALSE));
5112 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5113 emitcode ("anl", "a,%s",
5114 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5117 aopPut (AOP (result), "a", offset);
5123 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5124 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5125 freeAsmop (result, NULL, ic, TRUE);
5128 /*-----------------------------------------------------------------*/
5129 /* genOr - code for or */
5130 /*-----------------------------------------------------------------*/
5132 genOr (iCode * ic, iCode * ifx)
5134 operand *left, *right, *result;
5135 int size, offset = 0;
5136 unsigned long lit = 0L;
5138 D (emitcode (";", "genOr ");
5142 AOP_SET_LOCALS (ic);
5145 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5147 AOP_TYPE (left), AOP_TYPE (right));
5148 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5150 AOP_SIZE (left), AOP_SIZE (right));
5153 /* if left is a literal & right is not then exchange them */
5154 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5155 AOP_NEEDSACC (left))
5157 operand *tmp = right;
5162 /* if result = right then exchange them */
5163 if (sameRegs (AOP (result), AOP (right)))
5165 operand *tmp = right;
5170 /* if right is bit then exchange them */
5171 if (AOP_TYPE (right) == AOP_CRY &&
5172 AOP_TYPE (left) != AOP_CRY)
5174 operand *tmp = right;
5178 if (AOP_TYPE (right) == AOP_LIT)
5179 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5181 size = AOP_SIZE (result);
5185 if (AOP_TYPE (left) == AOP_CRY)
5187 if (AOP_TYPE (right) == AOP_LIT)
5189 // c = bit & literal;
5192 // lit != 0 => result = 1
5193 if (AOP_TYPE (result) == AOP_CRY)
5196 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5198 continueIfTrue (ifx);
5201 emitcode ("setb", "c");
5205 // lit == 0 => result = left
5206 if (size && sameRegs (AOP (result), AOP (left)))
5208 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5213 if (AOP_TYPE (right) == AOP_CRY)
5216 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5217 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5222 symbol *tlbl = newiTempLabel (NULL);
5223 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5224 emitcode ("setb", "c");
5225 emitcode ("jb", "%s,%05d$",
5226 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5228 emitcode ("jnz", "%05d$", tlbl->key + 100);
5229 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5231 jmpTrueOrFalse (ifx, tlbl);
5237 emitcode ("", "%05d$:", tlbl->key + 100);
5246 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5247 genIfxJump (ifx, "c");
5251 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5252 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5253 if ((AOP_TYPE (right) == AOP_LIT) &&
5254 (AOP_TYPE (result) == AOP_CRY) &&
5255 (AOP_TYPE (left) != AOP_CRY))
5261 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5263 continueIfTrue (ifx);
5268 // lit = 0, result = boolean(left)
5270 emitcode ("setb", "c");
5274 symbol *tlbl = newiTempLabel (NULL);
5275 emitcode ("jnz", "%05d$", tlbl->key + 100);
5277 emitcode ("", "%05d$:", tlbl->key + 100);
5281 genIfxJump (ifx, "a");
5289 /* if left is same as result */
5290 if (sameRegs (AOP (result), AOP (left)))
5292 for (; size--; offset++)
5294 if (AOP_TYPE (right) == AOP_LIT)
5296 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5302 if (IS_AOP_PREG (left))
5304 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5305 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5306 aopPut (AOP (result), "a", offset);
5310 emitcode ("orl", "%s,%s",
5311 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5312 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5318 if (AOP_TYPE (left) == AOP_ACC)
5320 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5324 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5325 if (IS_AOP_PREG (left))
5327 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5328 aopPut (AOP (result), "a", offset);
5332 emitcode ("orl", "%s,a",
5333 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5341 // left & result in different registers
5342 if (AOP_TYPE (result) == AOP_CRY)
5345 // if(size), result in bit
5346 // if(!size && ifx), conditional oper: if(left | right)
5347 symbol *tlbl = newiTempLabel (NULL);
5348 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5350 emitcode ("setb", "c");
5353 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5354 emitcode ("orl", "a,%s",
5355 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5356 emitcode ("jnz", "%05d$", tlbl->key + 100);
5362 emitcode ("", "%05d$:", tlbl->key + 100);
5366 jmpTrueOrFalse (ifx, tlbl);
5370 for (; (size--); offset++)
5373 // result = left & right
5374 if (AOP_TYPE (right) == AOP_LIT)
5376 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5378 aopPut (AOP (result),
5379 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5383 D (emitcode (";", "better literal OR.");
5385 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5386 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5387 FALSE, FALSE, FALSE));
5392 // faster than result <- left, anl result,right
5393 // and better if result is SFR
5394 if (AOP_TYPE (left) == AOP_ACC)
5396 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5397 FALSE, FALSE, FALSE));
5401 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5402 emitcode ("orl", "a,%s",
5403 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5406 aopPut (AOP (result), "a", offset);
5412 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5414 freeAsmop (result, NULL, ic, TRUE);
5417 /*-----------------------------------------------------------------*/
5418 /* genXor - code for xclusive or */
5419 /*-----------------------------------------------------------------*/
5421 genXor (iCode * ic, iCode * ifx)
5423 operand *left, *right, *result;
5424 int size, offset = 0;
5425 unsigned long lit = 0L;
5427 D (emitcode (";", "genXor ");
5431 AOP_SET_LOCALS (ic);
5434 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5436 AOP_TYPE (left), AOP_TYPE (right));
5437 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5439 AOP_SIZE (left), AOP_SIZE (right));
5442 /* if left is a literal & right is not ||
5443 if left needs acc & right does not */
5444 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5445 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5447 operand *tmp = right;
5452 /* if result = right then exchange them */
5453 if (sameRegs (AOP (result), AOP (right)))
5455 operand *tmp = right;
5460 /* if right is bit then exchange them */
5461 if (AOP_TYPE (right) == AOP_CRY &&
5462 AOP_TYPE (left) != AOP_CRY)
5464 operand *tmp = right;
5468 if (AOP_TYPE (right) == AOP_LIT)
5469 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5471 size = AOP_SIZE (result);
5475 if (AOP_TYPE (left) == AOP_CRY)
5477 if (AOP_TYPE (right) == AOP_LIT)
5479 // c = bit & literal;
5482 // lit>>1 != 0 => result = 1
5483 if (AOP_TYPE (result) == AOP_CRY)
5486 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5488 continueIfTrue (ifx);
5491 emitcode ("setb", "c");
5498 // lit == 0, result = left
5499 if (size && sameRegs (AOP (result), AOP (left)))
5501 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5505 // lit == 1, result = not(left)
5506 if (size && sameRegs (AOP (result), AOP (left)))
5508 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5513 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5514 emitcode ("cpl", "c");
5523 symbol *tlbl = newiTempLabel (NULL);
5524 if (AOP_TYPE (right) == AOP_CRY)
5527 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5531 int sizer = AOP_SIZE (right);
5533 // if val>>1 != 0, result = 1
5534 emitcode ("setb", "c");
5537 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5539 // test the msb of the lsb
5540 emitcode ("anl", "a,#0xfe");
5541 emitcode ("jnz", "%05d$", tlbl->key + 100);
5545 emitcode ("rrc", "a");
5547 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5548 emitcode ("cpl", "c");
5549 emitcode ("", "%05d$:", (tlbl->key + 100));
5556 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5557 genIfxJump (ifx, "c");
5561 if (sameRegs (AOP (result), AOP (left)))
5563 /* if left is same as result */
5564 for (; size--; offset++)
5566 if (AOP_TYPE (right) == AOP_LIT)
5568 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5570 else if (IS_AOP_PREG (left))
5572 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5573 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5574 aopPut (AOP (result), "a", offset);
5577 emitcode ("xrl", "%s,%s",
5578 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5579 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5583 if (AOP_TYPE (left) == AOP_ACC)
5584 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5587 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5588 if (IS_AOP_PREG (left))
5590 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5591 aopPut (AOP (result), "a", offset);
5594 emitcode ("xrl", "%s,a",
5595 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5602 // left & result in different registers
5603 if (AOP_TYPE (result) == AOP_CRY)
5606 // if(size), result in bit
5607 // if(!size && ifx), conditional oper: if(left ^ right)
5608 symbol *tlbl = newiTempLabel (NULL);
5609 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5611 emitcode ("setb", "c");
5614 if ((AOP_TYPE (right) == AOP_LIT) &&
5615 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5617 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5621 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5622 emitcode ("xrl", "a,%s",
5623 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5625 emitcode ("jnz", "%05d$", tlbl->key + 100);
5631 emitcode ("", "%05d$:", tlbl->key + 100);
5635 jmpTrueOrFalse (ifx, tlbl);
5638 for (; (size--); offset++)
5641 // result = left & right
5642 if (AOP_TYPE (right) == AOP_LIT)
5644 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5646 aopPut (AOP (result),
5647 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5651 D (emitcode (";", "better literal XOR.");
5653 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5654 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5655 FALSE, FALSE, FALSE));
5659 // faster than result <- left, anl result,right
5660 // and better if result is SFR
5661 if (AOP_TYPE (left) == AOP_ACC)
5663 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5664 FALSE, FALSE, FALSE));
5668 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5669 emitcode ("xrl", "a,%s",
5670 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5673 aopPut (AOP (result), "a", offset);
5678 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5679 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5680 freeAsmop (result, NULL, ic, TRUE);
5683 /*-----------------------------------------------------------------*/
5684 /* genInline - write the inline code out */
5685 /*-----------------------------------------------------------------*/
5687 genInline (iCode * ic)
5689 char buffer[MAX_INLINEASM];
5693 D (emitcode (";", "genInline ");
5696 _G.inLine += (!options.asmpeep);
5697 strcpy (buffer, IC_INLINE (ic));
5699 /* emit each line as a code */
5724 /* emitcode("",buffer); */
5725 _G.inLine -= (!options.asmpeep);
5728 /*-----------------------------------------------------------------*/
5729 /* genRRC - rotate right with carry */
5730 /*-----------------------------------------------------------------*/
5734 operand *left, *result;
5735 int size, offset = 0;
5738 D (emitcode (";", "genRRC ");
5741 /* rotate right with carry */
5742 left = IC_LEFT (ic);
5743 result = IC_RESULT (ic);
5744 aopOp (left, ic, FALSE, FALSE);
5745 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5747 /* move it to the result */
5748 size = AOP_SIZE (result);
5752 _startLazyDPSEvaluation ();
5755 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5757 emitcode ("rrc", "a");
5758 if (AOP_SIZE (result) > 1)
5759 aopPut (AOP (result), "a", offset--);
5761 _endLazyDPSEvaluation ();
5763 /* now we need to put the carry into the
5764 highest order byte of the result */
5765 if (AOP_SIZE (result) > 1)
5767 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5770 emitcode ("mov", "acc.7,c");
5771 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5772 freeAsmop (left, NULL, ic, TRUE);
5773 freeAsmop (result, NULL, ic, TRUE);
5776 /*-----------------------------------------------------------------*/
5777 /* genRLC - generate code for rotate left with carry */
5778 /*-----------------------------------------------------------------*/
5782 operand *left, *result;
5783 int size, offset = 0;
5786 D (emitcode (";", "genRLC ");
5789 /* rotate right with carry */
5790 left = IC_LEFT (ic);
5791 result = IC_RESULT (ic);
5792 aopOp (left, ic, FALSE, FALSE);
5793 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5795 /* move it to the result */
5796 size = AOP_SIZE (result);
5800 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5802 emitcode ("add", "a,acc");
5803 if (AOP_SIZE (result) > 1)
5805 aopPut (AOP (result), "a", offset++);
5808 _startLazyDPSEvaluation ();
5811 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5813 emitcode ("rlc", "a");
5814 if (AOP_SIZE (result) > 1)
5815 aopPut (AOP (result), "a", offset++);
5817 _endLazyDPSEvaluation ();
5819 /* now we need to put the carry into the
5820 highest order byte of the result */
5821 if (AOP_SIZE (result) > 1)
5823 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5826 emitcode ("mov", "acc.0,c");
5827 aopPut (AOP (result), "a", 0);
5828 freeAsmop (left, NULL, ic, TRUE);
5829 freeAsmop (result, NULL, ic, TRUE);
5832 /*-----------------------------------------------------------------*/
5833 /* genGetHbit - generates code get highest order bit */
5834 /*-----------------------------------------------------------------*/
5836 genGetHbit (iCode * ic)
5838 operand *left, *result;
5839 left = IC_LEFT (ic);
5840 result = IC_RESULT (ic);
5841 aopOp (left, ic, FALSE, FALSE);
5842 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5844 D (emitcode (";", "genGetHbit ");
5847 /* get the highest order byte into a */
5848 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5849 if (AOP_TYPE (result) == AOP_CRY)
5851 emitcode ("rlc", "a");
5856 emitcode ("rl", "a");
5857 emitcode ("anl", "a,#0x01");
5862 freeAsmop (left, NULL, ic, TRUE);
5863 freeAsmop (result, NULL, ic, TRUE);
5866 /*-----------------------------------------------------------------*/
5867 /* AccRol - rotate left accumulator by known count */
5868 /*-----------------------------------------------------------------*/
5870 AccRol (int shCount)
5872 shCount &= 0x0007; // shCount : 0..7
5879 emitcode ("rl", "a");
5882 emitcode ("rl", "a");
5883 emitcode ("rl", "a");
5886 emitcode ("swap", "a");
5887 emitcode ("rr", "a");
5890 emitcode ("swap", "a");
5893 emitcode ("swap", "a");
5894 emitcode ("rl", "a");
5897 emitcode ("rr", "a");
5898 emitcode ("rr", "a");
5901 emitcode ("rr", "a");
5906 /*-----------------------------------------------------------------*/
5907 /* AccLsh - left shift accumulator by known count */
5908 /*-----------------------------------------------------------------*/
5910 AccLsh (int shCount)
5915 emitcode ("add", "a,acc");
5916 else if (shCount == 2)
5918 emitcode ("add", "a,acc");
5919 emitcode ("add", "a,acc");
5923 /* rotate left accumulator */
5925 /* and kill the lower order bits */
5926 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5931 /*-----------------------------------------------------------------*/
5932 /* AccRsh - right shift accumulator by known count */
5933 /*-----------------------------------------------------------------*/
5935 AccRsh (int shCount)
5942 emitcode ("rrc", "a");
5946 /* rotate right accumulator */
5947 AccRol (8 - shCount);
5948 /* and kill the higher order bits */
5949 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5956 /*-----------------------------------------------------------------*/
5957 /* AccSRsh - signed right shift accumulator by known count */
5958 /*-----------------------------------------------------------------*/
5960 AccSRsh (int shCount)
5967 emitcode ("mov", "c,acc.7");
5968 emitcode ("rrc", "a");
5970 else if (shCount == 2)
5972 emitcode ("mov", "c,acc.7");
5973 emitcode ("rrc", "a");
5974 emitcode ("mov", "c,acc.7");
5975 emitcode ("rrc", "a");
5979 tlbl = newiTempLabel (NULL);
5980 /* rotate right accumulator */
5981 AccRol (8 - shCount);
5982 /* and kill the higher order bits */
5983 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5984 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5985 emitcode ("orl", "a,#0x%02x",
5986 (unsigned char) ~SRMask[shCount]);
5987 emitcode ("", "%05d$:", tlbl->key + 100);
5995 /*-----------------------------------------------------------------*/
5996 /* shiftR1Left2Result - shift right one byte from left to result */
5997 /*-----------------------------------------------------------------*/
5999 shiftR1Left2Result (operand * left, int offl,
6000 operand * result, int offr,
6001 int shCount, int sign)
6003 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6004 /* shift right accumulator */
6009 aopPut (AOP (result), "a", offr);
6015 /*-----------------------------------------------------------------*/
6016 /* shiftL1Left2Result - shift left one byte from left to result */
6017 /*-----------------------------------------------------------------*/
6019 shiftL1Left2Result (operand * left, int offl,
6020 operand * result, int offr, int shCount)
6023 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6025 /* shift left accumulator */
6027 aopPut (AOP (result), "a", offr);
6033 /*-----------------------------------------------------------------*/
6034 /* movLeft2Result - move byte from left to result */
6035 /*-----------------------------------------------------------------*/
6037 movLeft2Result (operand * left, int offl,
6038 operand * result, int offr, int sign)
6041 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6043 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6045 if (*l == '@' && (IS_AOP_PREG (result)))
6047 emitcode ("mov", "a,%s", l);
6048 aopPut (AOP (result), "a", offr);
6053 aopPut (AOP (result), l, offr);
6056 /* MSB sign in acc.7 ! */
6057 if (getDataSize (left) == offl + 1)
6059 emitcode ("mov", "a,%s", l);
6060 aopPut (AOP (result), "a", offr);
6070 /*-----------------------------------------------------------------*/
6071 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6072 /*-----------------------------------------------------------------*/
6076 emitcode ("rrc", "a");
6077 emitcode ("xch", "a,%s", x);
6078 emitcode ("rrc", "a");
6079 emitcode ("xch", "a,%s", x);
6085 /*-----------------------------------------------------------------*/
6086 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6087 /*-----------------------------------------------------------------*/
6091 emitcode ("xch", "a,%s", x);
6092 emitcode ("rlc", "a");
6093 emitcode ("xch", "a,%s", x);
6094 emitcode ("rlc", "a");
6100 /*-----------------------------------------------------------------*/
6101 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6102 /*-----------------------------------------------------------------*/
6106 emitcode ("xch", "a,%s", x);
6107 emitcode ("add", "a,acc");
6108 emitcode ("xch", "a,%s", x);
6109 emitcode ("rlc", "a");
6115 /*-----------------------------------------------------------------*/
6116 /* AccAXLsh - left shift a:x by known count (0..7) */
6117 /*-----------------------------------------------------------------*/
6119 AccAXLsh (char *x, int shCount)
6134 case 5: // AAAAABBB:CCCCCDDD
6136 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6138 emitcode ("anl", "a,#0x%02x",
6139 SLMask[shCount]); // BBB00000:CCCCCDDD
6141 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6143 AccRol (shCount); // DDDCCCCC:BBB00000
6145 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6147 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6149 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6151 emitcode ("anl", "a,#0x%02x",
6152 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6154 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6156 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6159 case 6: // AAAAAABB:CCCCCCDD
6160 emitcode ("anl", "a,#0x%02x",
6161 SRMask[shCount]); // 000000BB:CCCCCCDD
6162 emitcode ("mov", "c,acc.0"); // c = B
6163 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6165 AccAXRrl1 (x); // BCCCCCCD:D000000B
6166 AccAXRrl1 (x); // BBCCCCCC:DD000000
6168 emitcode("rrc","a");
6169 emitcode("xch","a,%s", x);
6170 emitcode("rrc","a");
6171 emitcode("mov","c,acc.0"); //<< get correct bit
6172 emitcode("xch","a,%s", x);
6174 emitcode("rrc","a");
6175 emitcode("xch","a,%s", x);
6176 emitcode("rrc","a");
6177 emitcode("xch","a,%s", x);
6180 case 7: // a:x <<= 7
6182 emitcode ("anl", "a,#0x%02x",
6183 SRMask[shCount]); // 0000000B:CCCCCCCD
6185 emitcode ("mov", "c,acc.0"); // c = B
6187 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6189 AccAXRrl1 (x); // BCCCCCCC:D0000000
6200 /*-----------------------------------------------------------------*/
6201 /* AccAXRsh - right shift a:x known count (0..7) */
6202 /*-----------------------------------------------------------------*/
6204 AccAXRsh (char *x, int shCount)
6212 AccAXRrl1 (x); // 0->a:x
6217 AccAXRrl1 (x); // 0->a:x
6220 AccAXRrl1 (x); // 0->a:x
6225 case 5: // AAAAABBB:CCCCCDDD = a:x
6227 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6229 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6231 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6233 emitcode ("anl", "a,#0x%02x",
6234 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6236 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6238 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6240 emitcode ("anl", "a,#0x%02x",
6241 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6243 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6245 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6247 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6250 case 6: // AABBBBBB:CCDDDDDD
6252 emitcode ("mov", "c,acc.7");
6253 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6255 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6257 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6259 emitcode ("anl", "a,#0x%02x",
6260 SRMask[shCount]); // 000000AA:BBBBBBCC
6263 case 7: // ABBBBBBB:CDDDDDDD
6265 emitcode ("mov", "c,acc.7"); // c = A
6267 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6269 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6271 emitcode ("anl", "a,#0x%02x",
6272 SRMask[shCount]); // 0000000A:BBBBBBBC
6283 /*-----------------------------------------------------------------*/
6284 /* AccAXRshS - right shift signed a:x known count (0..7) */
6285 /*-----------------------------------------------------------------*/
6287 AccAXRshS (char *x, int shCount)
6295 emitcode ("mov", "c,acc.7");
6296 AccAXRrl1 (x); // s->a:x
6300 emitcode ("mov", "c,acc.7");
6301 AccAXRrl1 (x); // s->a:x
6303 emitcode ("mov", "c,acc.7");
6304 AccAXRrl1 (x); // s->a:x
6309 case 5: // AAAAABBB:CCCCCDDD = a:x
6311 tlbl = newiTempLabel (NULL);
6312 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6314 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6316 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6318 emitcode ("anl", "a,#0x%02x",
6319 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6321 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6323 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6325 emitcode ("anl", "a,#0x%02x",
6326 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6328 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6330 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6332 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6334 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6335 emitcode ("orl", "a,#0x%02x",
6336 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6338 emitcode ("", "%05d$:", tlbl->key + 100);
6339 break; // SSSSAAAA:BBBCCCCC
6341 case 6: // AABBBBBB:CCDDDDDD
6343 tlbl = newiTempLabel (NULL);
6344 emitcode ("mov", "c,acc.7");
6345 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6347 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6349 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6351 emitcode ("anl", "a,#0x%02x",
6352 SRMask[shCount]); // 000000AA:BBBBBBCC
6354 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6355 emitcode ("orl", "a,#0x%02x",
6356 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6358 emitcode ("", "%05d$:", tlbl->key + 100);
6360 case 7: // ABBBBBBB:CDDDDDDD
6362 tlbl = newiTempLabel (NULL);
6363 emitcode ("mov", "c,acc.7"); // c = A
6365 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6367 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6369 emitcode ("anl", "a,#0x%02x",
6370 SRMask[shCount]); // 0000000A:BBBBBBBC
6372 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6373 emitcode ("orl", "a,#0x%02x",
6374 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6376 emitcode ("", "%05d$:", tlbl->key + 100);
6386 /*-----------------------------------------------------------------*/
6387 /* shiftL2Left2Result - shift left two bytes from left to result */
6388 /*-----------------------------------------------------------------*/
6390 shiftL2Left2Result (operand * left, int offl,
6391 operand * result, int offr, int shCount)
6393 if (sameRegs (AOP (result), AOP (left)) &&
6394 ((offl + MSB16) == offr))
6396 /* don't crash result[offr] */
6397 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6398 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6402 movLeft2Result (left, offl, result, offr, 0);
6403 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6405 /* ax << shCount (x = lsb(result)) */
6406 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6407 aopPut (AOP (result), "a", offr + MSB16);
6413 /*-----------------------------------------------------------------*/
6414 /* shiftR2Left2Result - shift right two bytes from left to result */
6415 /*-----------------------------------------------------------------*/
6417 shiftR2Left2Result (operand * left, int offl,
6418 operand * result, int offr,
6419 int shCount, int sign)
6421 if (sameRegs (AOP (result), AOP (left)) &&
6422 ((offl + MSB16) == offr))
6424 /* don't crash result[offr] */
6425 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6426 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6430 movLeft2Result (left, offl, result, offr, 0);
6431 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6433 /* a:x >> shCount (x = lsb(result)) */
6435 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6437 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6438 if (getDataSize (result) > 1)
6439 aopPut (AOP (result), "a", offr + MSB16);
6445 /*-----------------------------------------------------------------*/
6446 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6447 /*-----------------------------------------------------------------*/
6449 shiftLLeftOrResult (operand * left, int offl,
6450 operand * result, int offr, int shCount)
6452 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6453 /* shift left accumulator */
6455 /* or with result */
6456 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6457 /* back to result */
6458 aopPut (AOP (result), "a", offr);
6464 /*-----------------------------------------------------------------*/
6465 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6466 /*-----------------------------------------------------------------*/
6468 shiftRLeftOrResult (operand * left, int offl,
6469 operand * result, int offr, int shCount)
6471 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6472 /* shift right accumulator */
6474 /* or with result */
6475 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6476 /* back to result */
6477 aopPut (AOP (result), "a", offr);
6483 /*-----------------------------------------------------------------*/
6484 /* genlshOne - left shift a one byte quantity by known count */
6485 /*-----------------------------------------------------------------*/
6487 genlshOne (operand * result, operand * left, int shCount)
6489 D (emitcode (";", "genlshOne ");
6491 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6497 /*-----------------------------------------------------------------*/
6498 /* genlshTwo - left shift two bytes by known amount != 0 */
6499 /*-----------------------------------------------------------------*/
6501 genlshTwo (operand * result, operand * left, int shCount)
6505 D (emitcode (";", "genlshTwo ");
6508 size = getDataSize (result);
6510 /* if shCount >= 8 */
6518 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6520 movLeft2Result (left, LSB, result, MSB16, 0);
6522 aopPut (AOP (result), zero, LSB);
6525 /* 1 <= shCount <= 7 */
6529 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6531 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6538 /*-----------------------------------------------------------------*/
6539 /* shiftLLong - shift left one long from left to result */
6540 /* offl = LSB or MSB16 */
6541 /*-----------------------------------------------------------------*/
6543 shiftLLong (operand * left, operand * result, int offr)
6546 int size = AOP_SIZE (result);
6548 if (size >= LSB + offr)
6550 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6552 emitcode ("add", "a,acc");
6553 if (sameRegs (AOP (left), AOP (result)) &&
6554 size >= MSB16 + offr && offr != LSB)
6555 emitcode ("xch", "a,%s",
6556 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6558 aopPut (AOP (result), "a", LSB + offr);
6561 if (size >= MSB16 + offr)
6563 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6565 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6568 emitcode ("rlc", "a");
6569 if (sameRegs (AOP (left), AOP (result)) &&
6570 size >= MSB24 + offr && offr != LSB)
6571 emitcode ("xch", "a,%s",
6572 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6574 aopPut (AOP (result), "a", MSB16 + offr);
6577 if (size >= MSB24 + offr)
6579 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6581 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6584 emitcode ("rlc", "a");
6585 if (sameRegs (AOP (left), AOP (result)) &&
6586 size >= MSB32 + offr && offr != LSB)
6587 emitcode ("xch", "a,%s",
6588 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6590 aopPut (AOP (result), "a", MSB24 + offr);
6593 if (size > MSB32 + offr)
6595 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6597 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6600 emitcode ("rlc", "a");
6601 aopPut (AOP (result), "a", MSB32 + offr);
6604 aopPut (AOP (result), zero, LSB);
6610 /*-----------------------------------------------------------------*/
6611 /* genlshFour - shift four byte by a known amount != 0 */
6612 /*-----------------------------------------------------------------*/
6614 genlshFour (operand * result, operand * left, int shCount)
6618 D (emitcode (";", "genlshFour ");
6621 size = AOP_SIZE (result);
6623 /* if shifting more that 3 bytes */
6628 /* lowest order of left goes to the highest
6629 order of the destination */
6630 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6632 movLeft2Result (left, LSB, result, MSB32, 0);
6633 aopPut (AOP (result), zero, LSB);
6634 aopPut (AOP (result), zero, MSB16);
6635 aopPut (AOP (result), zero, MSB24);
6639 /* more than two bytes */
6640 else if (shCount >= 16)
6642 /* lower order two bytes goes to higher order two bytes */
6644 /* if some more remaining */
6646 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6649 movLeft2Result (left, MSB16, result, MSB32, 0);
6650 movLeft2Result (left, LSB, result, MSB24, 0);
6652 aopPut (AOP (result), zero, MSB16);
6653 aopPut (AOP (result), zero, LSB);
6657 /* if more than 1 byte */
6658 else if (shCount >= 8)
6660 /* lower order three bytes goes to higher order three bytes */
6665 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6667 movLeft2Result (left, LSB, result, MSB16, 0);
6673 movLeft2Result (left, MSB24, result, MSB32, 0);
6674 movLeft2Result (left, MSB16, result, MSB24, 0);
6675 movLeft2Result (left, LSB, result, MSB16, 0);
6676 aopPut (AOP (result), zero, LSB);
6678 else if (shCount == 1)
6679 shiftLLong (left, result, MSB16);
6682 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6683 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6684 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6685 aopPut (AOP (result), zero, LSB);
6690 /* 1 <= shCount <= 7 */
6691 else if (shCount <= 2)
6693 shiftLLong (left, result, LSB);
6695 shiftLLong (result, result, LSB);
6697 /* 3 <= shCount <= 7, optimize */
6700 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6701 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6702 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6709 /*-----------------------------------------------------------------*/
6710 /* genLeftShiftLiteral - left shifting by known count */
6711 /*-----------------------------------------------------------------*/
6713 genLeftShiftLiteral (operand * left,
6718 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6721 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6724 freeAsmop (right, NULL, ic, TRUE);
6726 aopOp (left, ic, FALSE, FALSE);
6727 aopOp (result, ic, FALSE, TRUE);
6729 size = getSize (operandType (result));
6732 emitcode ("; shift left ", "result %d, left %d", size,
6736 /* I suppose that the left size >= result size */
6741 movLeft2Result (left, size, result, size, 0);
6745 else if (shCount >= (size * 8))
6747 aopPut (AOP (result), zero, size);
6753 genlshOne (result, left, shCount);
6757 case 3: /* bug: this is for generic pointers, I bet. */
6758 genlshTwo (result, left, shCount);
6762 genlshFour (result, left, shCount);
6766 freeAsmop (left, NULL, ic, TRUE);
6767 freeAsmop (result, NULL, ic, TRUE);
6771 /*-----------------------------------------------------------------*/
6772 /* genLeftShift - generates code for left shifting */
6773 /*-----------------------------------------------------------------*/
6775 genLeftShift (iCode * ic)
6777 operand *left, *right, *result;
6780 symbol *tlbl, *tlbl1;
6782 D (emitcode (";", "genLeftShift ");
6785 right = IC_RIGHT (ic);
6786 left = IC_LEFT (ic);
6787 result = IC_RESULT (ic);
6789 aopOp (right, ic, FALSE, FALSE);
6792 /* if the shift count is known then do it
6793 as efficiently as possible */
6794 if (AOP_TYPE (right) == AOP_LIT)
6796 genLeftShiftLiteral (left, right, result, ic);
6801 /* shift count is unknown then we have to form
6802 a loop get the loop count in B : Note: we take
6803 only the lower order byte since shifting
6804 more that 32 bits make no sense anyway, ( the
6805 largest size of an object can be only 32 bits ) */
6807 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6808 emitcode ("inc", "b");
6809 freeAsmop (right, NULL, ic, TRUE);
6810 aopOp (left, ic, FALSE, FALSE);
6811 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6813 /* now move the left to the result if they are not the
6815 if (!sameRegs (AOP (left), AOP (result)) &&
6816 AOP_SIZE (result) > 1)
6819 size = AOP_SIZE (result);
6821 _startLazyDPSEvaluation ();
6824 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6825 if (*l == '@' && (IS_AOP_PREG (result)))
6828 emitcode ("mov", "a,%s", l);
6829 aopPut (AOP (result), "a", offset);
6832 aopPut (AOP (result), l, offset);
6835 _endLazyDPSEvaluation ();
6838 tlbl = newiTempLabel (NULL);
6839 size = AOP_SIZE (result);
6841 tlbl1 = newiTempLabel (NULL);
6843 /* if it is only one byte then */
6846 symbol *tlbl1 = newiTempLabel (NULL);
6848 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6850 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6851 emitcode ("", "%05d$:", tlbl->key + 100);
6852 emitcode ("add", "a,acc");
6853 emitcode ("", "%05d$:", tlbl1->key + 100);
6854 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6855 aopPut (AOP (result), "a", 0);
6859 reAdjustPreg (AOP (result));
6861 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6862 emitcode ("", "%05d$:", tlbl->key + 100);
6863 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6865 emitcode ("add", "a,acc");
6866 aopPut (AOP (result), "a", offset++);
6867 _startLazyDPSEvaluation ();
6870 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6872 emitcode ("rlc", "a");
6873 aopPut (AOP (result), "a", offset++);
6875 _endLazyDPSEvaluation ();
6876 reAdjustPreg (AOP (result));
6878 emitcode ("", "%05d$:", tlbl1->key + 100);
6879 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6881 freeAsmop (left, NULL, ic, TRUE);
6882 freeAsmop (result, NULL, ic, TRUE);
6887 /*-----------------------------------------------------------------*/
6888 /* genrshOne - right shift a one byte quantity by known count */
6889 /*-----------------------------------------------------------------*/
6891 genrshOne (operand * result, operand * left,
6892 int shCount, int sign)
6894 D (emitcode (";", "genrshOne");
6896 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6902 /*-----------------------------------------------------------------*/
6903 /* genrshTwo - right shift two bytes by known amount != 0 */
6904 /*-----------------------------------------------------------------*/
6906 genrshTwo (operand * result, operand * left,
6907 int shCount, int sign)
6909 D (emitcode (";", "genrshTwo");
6912 /* if shCount >= 8 */
6917 shiftR1Left2Result (left, MSB16, result, LSB,
6920 movLeft2Result (left, MSB16, result, LSB, sign);
6921 addSign (result, MSB16, sign);
6924 /* 1 <= shCount <= 7 */
6926 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6932 /*-----------------------------------------------------------------*/
6933 /* shiftRLong - shift right one long from left to result */
6934 /* offl = LSB or MSB16 */
6935 /*-----------------------------------------------------------------*/
6937 shiftRLong (operand * left, int offl,
6938 operand * result, int sign)
6941 emitcode ("clr", "c");
6942 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6944 emitcode ("mov", "c,acc.7");
6945 emitcode ("rrc", "a");
6946 aopPut (AOP (result), "a", MSB32 - offl);
6948 /* add sign of "a" */
6949 addSign (result, MSB32, sign);
6951 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6952 emitcode ("rrc", "a");
6953 aopPut (AOP (result), "a", MSB24 - offl);
6955 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6956 emitcode ("rrc", "a");
6957 aopPut (AOP (result), "a", MSB16 - offl);
6961 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6962 emitcode ("rrc", "a");
6963 aopPut (AOP (result), "a", LSB);
6970 /*-----------------------------------------------------------------*/
6971 /* genrshFour - shift four byte by a known amount != 0 */
6972 /*-----------------------------------------------------------------*/
6974 genrshFour (operand * result, operand * left,
6975 int shCount, int sign)
6977 D (emitcode (";", "genrshFour");
6980 /* if shifting more that 3 bytes */
6985 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6987 movLeft2Result (left, MSB32, result, LSB, sign);
6988 addSign (result, MSB16, sign);
6990 else if (shCount >= 16)
6994 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6997 movLeft2Result (left, MSB24, result, LSB, 0);
6998 movLeft2Result (left, MSB32, result, MSB16, sign);
7000 addSign (result, MSB24, sign);
7002 else if (shCount >= 8)
7006 shiftRLong (left, MSB16, result, sign);
7007 else if (shCount == 0)
7009 movLeft2Result (left, MSB16, result, LSB, 0);
7010 movLeft2Result (left, MSB24, result, MSB16, 0);
7011 movLeft2Result (left, MSB32, result, MSB24, sign);
7012 addSign (result, MSB32, sign);
7016 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7017 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7018 /* the last shift is signed */
7019 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7020 addSign (result, MSB32, sign);
7024 { /* 1 <= shCount <= 7 */
7027 shiftRLong (left, LSB, result, sign);
7029 shiftRLong (result, LSB, result, sign);
7033 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7034 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7035 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7043 /*-----------------------------------------------------------------*/
7044 /* genRightShiftLiteral - right shifting by known count */
7045 /*-----------------------------------------------------------------*/
7047 genRightShiftLiteral (operand * left,
7053 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7056 D (emitcode (";", "genRightShiftLiteral");
7059 freeAsmop (right, NULL, ic, TRUE);
7061 aopOp (left, ic, FALSE, FALSE);
7062 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7065 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7069 size = getDataSize (left);
7070 /* test the LEFT size !!! */
7072 /* I suppose that the left size >= result size */
7075 size = getDataSize (result);
7077 movLeft2Result (left, size, result, size, 0);
7080 else if (shCount >= (size * 8))
7083 /* get sign in acc.7 */
7084 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7085 addSign (result, LSB, sign);
7092 genrshOne (result, left, shCount, sign);
7096 genrshTwo (result, left, shCount, sign);
7100 genrshFour (result, left, shCount, sign);
7106 freeAsmop (left, NULL, ic, TRUE);
7107 freeAsmop (result, NULL, ic, TRUE);
7112 /*-----------------------------------------------------------------*/
7113 /* genSignedRightShift - right shift of signed number */
7114 /*-----------------------------------------------------------------*/
7116 genSignedRightShift (iCode * ic)
7118 operand *right, *left, *result;
7121 symbol *tlbl, *tlbl1;
7123 D (emitcode (";", "genSignedRightShift ");
7126 /* we do it the hard way put the shift count in b
7127 and loop thru preserving the sign */
7129 right = IC_RIGHT (ic);
7130 left = IC_LEFT (ic);
7131 result = IC_RESULT (ic);
7133 aopOp (right, ic, FALSE, FALSE);
7136 if (AOP_TYPE (right) == AOP_LIT)
7138 genRightShiftLiteral (left, right, result, ic, 1);
7142 /* shift count is unknown then we have to form
7143 a loop get the loop count in B : Note: we take
7144 only the lower order byte since shifting
7145 more that 32 bits make no sense anyway, ( the
7146 largest size of an object can be only 32 bits ) */
7148 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7149 emitcode ("inc", "b");
7150 freeAsmop (right, NULL, ic, TRUE);
7151 aopOp (left, ic, FALSE, FALSE);
7152 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7154 /* now move the left to the result if they are not the
7156 if (!sameRegs (AOP (left), AOP (result)) &&
7157 AOP_SIZE (result) > 1)
7160 size = AOP_SIZE (result);
7162 _startLazyDPSEvaluation ();
7165 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7166 if (*l == '@' && IS_AOP_PREG (result))
7169 emitcode ("mov", "a,%s", l);
7170 aopPut (AOP (result), "a", offset);
7173 aopPut (AOP (result), l, offset);
7176 _endLazyDPSEvaluation ();
7179 /* mov the highest order bit to OVR */
7180 tlbl = newiTempLabel (NULL);
7181 tlbl1 = newiTempLabel (NULL);
7183 size = AOP_SIZE (result);
7185 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7186 emitcode ("rlc", "a");
7187 emitcode ("mov", "ov,c");
7188 /* if it is only one byte then */
7191 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7193 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7194 emitcode ("", "%05d$:", tlbl->key + 100);
7195 emitcode ("mov", "c,ov");
7196 emitcode ("rrc", "a");
7197 emitcode ("", "%05d$:", tlbl1->key + 100);
7198 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7199 aopPut (AOP (result), "a", 0);
7203 reAdjustPreg (AOP (result));
7204 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7205 emitcode ("", "%05d$:", tlbl->key + 100);
7206 emitcode ("mov", "c,ov");
7207 _startLazyDPSEvaluation ();
7210 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7212 emitcode ("rrc", "a");
7213 aopPut (AOP (result), "a", offset--);
7215 _endLazyDPSEvaluation ();
7216 reAdjustPreg (AOP (result));
7217 emitcode ("", "%05d$:", tlbl1->key + 100);
7218 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7221 freeAsmop (left, NULL, ic, TRUE);
7222 freeAsmop (result, NULL, ic, TRUE);
7225 /*-----------------------------------------------------------------*/
7226 /* genRightShift - generate code for right shifting */
7227 /*-----------------------------------------------------------------*/
7229 genRightShift (iCode * ic)
7231 operand *right, *left, *result;
7235 symbol *tlbl, *tlbl1;
7237 D (emitcode (";", "genRightShift ");
7240 /* if signed then we do it the hard way preserve the
7241 sign bit moving it inwards */
7242 retype = getSpec (operandType (IC_RESULT (ic)));
7244 if (!SPEC_USIGN (retype))
7246 genSignedRightShift (ic);
7250 /* signed & unsigned types are treated the same : i.e. the
7251 signed is NOT propagated inwards : quoting from the
7252 ANSI - standard : "for E1 >> E2, is equivalent to division
7253 by 2**E2 if unsigned or if it has a non-negative value,
7254 otherwise the result is implementation defined ", MY definition
7255 is that the sign does not get propagated */
7257 right = IC_RIGHT (ic);
7258 left = IC_LEFT (ic);
7259 result = IC_RESULT (ic);
7261 aopOp (right, ic, FALSE, FALSE);
7264 /* if the shift count is known then do it
7265 as efficiently as possible */
7266 if (AOP_TYPE (right) == AOP_LIT)
7268 genRightShiftLiteral (left, right, result, ic, 0);
7273 /* shift count is unknown then we have to form
7274 a loop get the loop count in B : Note: we take
7275 only the lower order byte since shifting
7276 more that 32 bits make no sense anyway, ( the
7277 largest size of an object can be only 32 bits ) */
7279 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7280 emitcode ("inc", "b");
7281 freeAsmop (right, NULL, ic, TRUE);
7282 aopOp (left, ic, FALSE, FALSE);
7283 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7285 /* now move the left to the result if they are not the
7287 if (!sameRegs (AOP (left), AOP (result)) &&
7288 AOP_SIZE (result) > 1)
7291 size = AOP_SIZE (result);
7293 _startLazyDPSEvaluation ();
7296 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7297 if (*l == '@' && IS_AOP_PREG (result))
7300 emitcode ("mov", "a,%s", l);
7301 aopPut (AOP (result), "a", offset);
7304 aopPut (AOP (result), l, offset);
7307 _endLazyDPSEvaluation ();
7310 tlbl = newiTempLabel (NULL);
7311 tlbl1 = newiTempLabel (NULL);
7312 size = AOP_SIZE (result);
7315 /* if it is only one byte then */
7318 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7320 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7321 emitcode ("", "%05d$:", tlbl->key + 100);
7323 emitcode ("rrc", "a");
7324 emitcode ("", "%05d$:", tlbl1->key + 100);
7325 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7326 aopPut (AOP (result), "a", 0);
7330 reAdjustPreg (AOP (result));
7331 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7332 emitcode ("", "%05d$:", tlbl->key + 100);
7334 _startLazyDPSEvaluation ();
7337 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7339 emitcode ("rrc", "a");
7340 aopPut (AOP (result), "a", offset--);
7342 _endLazyDPSEvaluation ();
7343 reAdjustPreg (AOP (result));
7345 emitcode ("", "%05d$:", tlbl1->key + 100);
7346 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7349 freeAsmop (left, NULL, ic, TRUE);
7350 freeAsmop (result, NULL, ic, TRUE);
7353 /*-----------------------------------------------------------------*/
7354 /* genUnpackBits - generates code for unpacking bits */
7355 /*-----------------------------------------------------------------*/
7357 genUnpackBits (operand * result, char *rname, int ptype)
7364 D (emitcode (";", "genUnpackBits ");
7367 etype = getSpec (operandType (result));
7369 /* read the first byte */
7375 emitcode ("mov", "a,@%s", rname);
7379 emitcode ("movx", "a,@%s", rname);
7383 emitcode ("movx", "a,@dptr");
7387 emitcode ("clr", "a");
7388 emitcode ("movc", "a", "@a+dptr");
7392 emitcode ("lcall", "__gptrget");
7396 /* if we have bitdisplacement then it fits */
7397 /* into this byte completely or if length is */
7398 /* less than a byte */
7399 if ((shCnt = SPEC_BSTR (etype)) ||
7400 (SPEC_BLEN (etype) <= 8))
7403 /* shift right acc */
7406 emitcode ("anl", "a,#0x%02x",
7407 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7408 aopPut (AOP (result), "a", offset);
7412 /* bit field did not fit in a byte */
7413 rlen = SPEC_BLEN (etype) - 8;
7414 aopPut (AOP (result), "a", offset++);
7423 emitcode ("inc", "%s", rname);
7424 emitcode ("mov", "a,@%s", rname);
7428 emitcode ("inc", "%s", rname);
7429 emitcode ("movx", "a,@%s", rname);
7433 emitcode ("inc", "dptr");
7434 emitcode ("movx", "a,@dptr");
7438 emitcode ("clr", "a");
7439 emitcode ("inc", "dptr");
7440 emitcode ("movc", "a", "@a+dptr");
7444 emitcode ("inc", "dptr");
7445 emitcode ("lcall", "__gptrget");
7450 /* if we are done */
7454 aopPut (AOP (result), "a", offset++);
7460 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7461 aopPut (AOP (result), "a", offset);
7468 /*-----------------------------------------------------------------*/
7469 /* genDataPointerGet - generates code when ptr offset is known */
7470 /*-----------------------------------------------------------------*/
7472 genDataPointerGet (operand * left,
7478 int size, offset = 0;
7479 aopOp (result, ic, TRUE, FALSE);
7481 /* get the string representation of the name */
7482 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7483 size = AOP_SIZE (result);
7484 _startLazyDPSEvaluation ();
7488 sprintf (buffer, "(%s + %d)", l + 1, offset);
7490 sprintf (buffer, "%s", l + 1);
7491 aopPut (AOP (result), buffer, offset++);
7493 _endLazyDPSEvaluation ();
7495 freeAsmop (left, NULL, ic, TRUE);
7496 freeAsmop (result, NULL, ic, TRUE);
7499 /*-----------------------------------------------------------------*/
7500 /* genNearPointerGet - emitcode for near pointer fetch */
7501 /*-----------------------------------------------------------------*/
7503 genNearPointerGet (operand * left,
7510 sym_link *rtype, *retype, *letype;
7511 sym_link *ltype = operandType (left);
7514 rtype = operandType (result);
7515 retype = getSpec (rtype);
7516 letype = getSpec (ltype);
7518 aopOp (left, ic, FALSE, FALSE);
7520 /* if left is rematerialisable and
7521 result is not bit variable type and
7522 the left is pointer to data space i.e
7523 lower 128 bytes of space */
7524 if (AOP_TYPE (left) == AOP_IMMD &&
7525 !IS_BITVAR (retype) &&
7526 !IS_BITVAR (letype) &&
7527 DCL_TYPE (ltype) == POINTER)
7529 genDataPointerGet (left, result, ic);
7533 /* if the value is already in a pointer register
7534 then don't need anything more */
7535 if (!AOP_INPREG (AOP (left)))
7537 /* otherwise get a free pointer register */
7539 preg = getFreePtr (ic, &aop, FALSE);
7540 emitcode ("mov", "%s,%s",
7542 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7546 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7548 freeAsmop (left, NULL, ic, TRUE);
7549 aopOp (result, ic, FALSE, FALSE);
7551 /* if bitfield then unpack the bits */
7552 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7553 genUnpackBits (result, rname, POINTER);
7556 /* we have can just get the values */
7557 int size = AOP_SIZE (result);
7562 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7565 emitcode ("mov", "a,@%s", rname);
7566 aopPut (AOP (result), "a", offset);
7570 sprintf (buffer, "@%s", rname);
7571 aopPut (AOP (result), buffer, offset);
7575 emitcode ("inc", "%s", rname);
7579 /* now some housekeeping stuff */
7582 /* we had to allocate for this iCode */
7583 freeAsmop (NULL, aop, ic, TRUE);
7587 /* we did not allocate which means left
7588 already in a pointer register, then
7589 if size > 0 && this could be used again
7590 we have to point it back to where it
7592 if (AOP_SIZE (result) > 1 &&
7593 !OP_SYMBOL (left)->remat &&
7594 (OP_SYMBOL (left)->liveTo > ic->seq ||
7597 int size = AOP_SIZE (result) - 1;
7599 emitcode ("dec", "%s", rname);
7604 freeAsmop (result, NULL, ic, TRUE);
7608 /*-----------------------------------------------------------------*/
7609 /* genPagedPointerGet - emitcode for paged pointer fetch */
7610 /*-----------------------------------------------------------------*/
7612 genPagedPointerGet (operand * left,
7619 sym_link *rtype, *retype, *letype;
7621 rtype = operandType (result);
7622 retype = getSpec (rtype);
7623 letype = getSpec (operandType (left));
7624 aopOp (left, ic, FALSE, FALSE);
7626 /* if the value is already in a pointer register
7627 then don't need anything more */
7628 if (!AOP_INPREG (AOP (left)))
7630 /* otherwise get a free pointer register */
7632 preg = getFreePtr (ic, &aop, FALSE);
7633 emitcode ("mov", "%s,%s",
7635 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7639 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7641 freeAsmop (left, NULL, ic, TRUE);
7642 aopOp (result, ic, FALSE, FALSE);
7644 /* if bitfield then unpack the bits */
7645 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7646 genUnpackBits (result, rname, PPOINTER);
7649 /* we have can just get the values */
7650 int size = AOP_SIZE (result);
7656 emitcode ("movx", "a,@%s", rname);
7657 aopPut (AOP (result), "a", offset);
7662 emitcode ("inc", "%s", rname);
7666 /* now some housekeeping stuff */
7669 /* we had to allocate for this iCode */
7670 freeAsmop (NULL, aop, ic, TRUE);
7674 /* we did not allocate which means left
7675 already in a pointer register, then
7676 if size > 0 && this could be used again
7677 we have to point it back to where it
7679 if (AOP_SIZE (result) > 1 &&
7680 !OP_SYMBOL (left)->remat &&
7681 (OP_SYMBOL (left)->liveTo > ic->seq ||
7684 int size = AOP_SIZE (result) - 1;
7686 emitcode ("dec", "%s", rname);
7691 freeAsmop (result, NULL, ic, TRUE);
7696 /*-----------------------------------------------------------------*/
7697 /* genFarPointerGet - gget value from far space */
7698 /*-----------------------------------------------------------------*/
7700 genFarPointerGet (operand * left,
7701 operand * result, iCode * ic)
7704 sym_link *retype = getSpec (operandType (result));
7705 sym_link *letype = getSpec (operandType (left));
7706 D (emitcode (";", "genFarPointerGet");
7709 aopOp (left, ic, FALSE, FALSE);
7711 /* if the operand is already in dptr
7712 then we do nothing else we move the value to dptr */
7713 if (AOP_TYPE (left) != AOP_STR)
7715 /* if this is remateriazable */
7716 if (AOP_TYPE (left) == AOP_IMMD)
7718 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7722 /* we need to get it byte by byte */
7723 _startLazyDPSEvaluation ();
7724 if (AOP_TYPE (left) != AOP_DPTR)
7726 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7727 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7728 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7732 /* We need to generate a load to DPTR indirect through DPTR. */
7733 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7735 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7736 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7737 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7738 emitcode ("pop", "dph");
7739 emitcode ("pop", "dpl");
7741 _endLazyDPSEvaluation ();
7744 /* so dptr know contains the address */
7745 freeAsmop (left, NULL, ic, TRUE);
7746 aopOp (result, ic, FALSE, TRUE);
7748 /* if bit then unpack */
7749 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7750 genUnpackBits (result, "dptr", FPOINTER);
7753 size = AOP_SIZE (result);
7756 _startLazyDPSEvaluation ();
7763 emitcode ("movx", "a,@dptr");
7765 emitcode ("inc", "dptr");
7767 aopPut (AOP (result), "a", offset++);
7769 _endLazyDPSEvaluation ();
7772 freeAsmop (result, NULL, ic, TRUE);
7775 /*-----------------------------------------------------------------*/
7776 /* emitcodePointerGet - gget value from code space */
7777 /*-----------------------------------------------------------------*/
7779 emitcodePointerGet (operand * left,
7780 operand * result, iCode * ic)
7783 sym_link *retype = getSpec (operandType (result));
7785 aopOp (left, ic, FALSE, FALSE);
7787 /* if the operand is already in dptr
7788 then we do nothing else we move the value to dptr */
7789 if (AOP_TYPE (left) != AOP_STR)
7791 /* if this is remateriazable */
7792 if (AOP_TYPE (left) == AOP_IMMD)
7794 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7797 { /* we need to get it byte by byte */
7798 _startLazyDPSEvaluation ();
7799 if (AOP_TYPE (left) != AOP_DPTR)
7801 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7802 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7803 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7807 /* We need to generate a load to DPTR indirect through DPTR. */
7808 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7810 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7811 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7812 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7813 emitcode ("pop", "dph");
7814 emitcode ("pop", "dpl");
7816 _endLazyDPSEvaluation ();
7819 /* so dptr know contains the address */
7820 freeAsmop (left, NULL, ic, TRUE);
7821 aopOp (result, ic, FALSE, TRUE);
7823 /* if bit then unpack */
7824 if (IS_BITVAR (retype))
7825 genUnpackBits (result, "dptr", CPOINTER);
7828 size = AOP_SIZE (result);
7831 _startLazyDPSEvaluation ();
7837 emitcode ("clr", "a");
7838 emitcode ("movc", "a,@a+dptr");
7840 emitcode ("inc", "dptr");
7841 aopPut (AOP (result), "a", offset++);
7843 _endLazyDPSEvaluation ();
7846 freeAsmop (result, NULL, ic, TRUE);
7849 /*-----------------------------------------------------------------*/
7850 /* genGenPointerGet - gget value from generic pointer space */
7851 /*-----------------------------------------------------------------*/
7853 genGenPointerGet (operand * left,
7854 operand * result, iCode * ic)
7857 sym_link *retype = getSpec (operandType (result));
7858 sym_link *letype = getSpec (operandType (left));
7860 D (emitcode (";", "genGenPointerGet "); );
7862 aopOp (left, ic, FALSE, TRUE);
7864 /* if the operand is already in dptr
7865 then we do nothing else we move the value to dptr */
7866 if (AOP_TYPE (left) != AOP_STR)
7868 /* if this is remateriazable */
7869 if (AOP_TYPE (left) == AOP_IMMD)
7871 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7872 emitcode ("mov", "b,#%d", pointerCode (retype));
7875 { /* we need to get it byte by byte */
7876 _startLazyDPSEvaluation ();
7877 if (AOP(left)->type==AOP_DPTR2) {
7879 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7882 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7883 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7886 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7887 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7890 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7891 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7893 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7894 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7895 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7896 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7898 _endLazyDPSEvaluation ();
7901 /* so dptr know contains the address */
7902 freeAsmop (left, NULL, ic, TRUE);
7903 aopOp (result, ic, FALSE, TRUE);
7905 /* if bit then unpack */
7906 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7907 genUnpackBits (result, "dptr", GPOINTER);
7910 size = AOP_SIZE (result);
7915 emitcode ("lcall", "__gptrget");
7916 aopPut (AOP (result), "a", offset++);
7918 emitcode ("inc", "dptr");
7922 freeAsmop (result, NULL, ic, TRUE);
7925 /*-----------------------------------------------------------------*/
7926 /* genPointerGet - generate code for pointer get */
7927 /*-----------------------------------------------------------------*/
7929 genPointerGet (iCode * ic)
7931 operand *left, *result;
7932 sym_link *type, *etype;
7935 D (emitcode (";", "genPointerGet ");
7938 left = IC_LEFT (ic);
7939 result = IC_RESULT (ic);
7941 /* depending on the type of pointer we need to
7942 move it to the correct pointer register */
7943 type = operandType (left);
7944 etype = getSpec (type);
7945 /* if left is of type of pointer then it is simple */
7946 if (IS_PTR (type) && !IS_FUNC (type->next))
7947 p_type = DCL_TYPE (type);
7950 /* we have to go by the storage class */
7951 p_type = PTR_TYPE (SPEC_OCLS (etype));
7954 /* now that we have the pointer type we assign
7955 the pointer values */
7961 genNearPointerGet (left, result, ic);
7965 genPagedPointerGet (left, result, ic);
7969 genFarPointerGet (left, result, ic);
7973 emitcodePointerGet (left, result, ic);
7977 genGenPointerGet (left, result, ic);
7983 /*-----------------------------------------------------------------*/
7984 /* genPackBits - generates code for packed bit storage */
7985 /*-----------------------------------------------------------------*/
7987 genPackBits (sym_link * etype,
7989 char *rname, int p_type)
7997 blen = SPEC_BLEN (etype);
7998 bstr = SPEC_BSTR (etype);
8000 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8003 /* if the bit lenth is less than or */
8004 /* it exactly fits a byte then */
8005 if (SPEC_BLEN (etype) <= 8)
8007 shCount = SPEC_BSTR (etype);
8009 /* shift left acc */
8012 if (SPEC_BLEN (etype) < 8)
8013 { /* if smaller than a byte */
8019 emitcode ("mov", "b,a");
8020 emitcode ("mov", "a,@%s", rname);
8024 emitcode ("mov", "b,a");
8025 emitcode ("movx", "a,@dptr");
8029 emitcode ("push", "b");
8030 emitcode ("push", "acc");
8031 emitcode ("lcall", "__gptrget");
8032 emitcode ("pop", "b");
8036 emitcode ("anl", "a,#0x%02x", (unsigned char)
8037 ((unsigned char) (0xFF << (blen + bstr)) |
8038 (unsigned char) (0xFF >> (8 - bstr))));
8039 emitcode ("orl", "a,b");
8040 if (p_type == GPOINTER)
8041 emitcode ("pop", "b");
8048 emitcode ("mov", "@%s,a", rname);
8052 emitcode ("movx", "@dptr,a");
8056 emitcode ("lcall", "__gptrput");
8061 if (SPEC_BLEN (etype) <= 8)
8064 emitcode ("inc", "%s", rname);
8065 rLen = SPEC_BLEN (etype);
8067 /* now generate for lengths greater than one byte */
8071 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8083 emitcode ("mov", "@%s,a", rname);
8086 emitcode ("mov", "@%s,%s", rname, l);
8091 emitcode ("movx", "@dptr,a");
8096 emitcode ("lcall", "__gptrput");
8099 emitcode ("inc", "%s", rname);
8104 /* last last was not complete */
8107 /* save the byte & read byte */
8111 emitcode ("mov", "b,a");
8112 emitcode ("mov", "a,@%s", rname);
8116 emitcode ("mov", "b,a");
8117 emitcode ("movx", "a,@dptr");
8121 emitcode ("push", "b");
8122 emitcode ("push", "acc");
8123 emitcode ("lcall", "__gptrget");
8124 emitcode ("pop", "b");
8128 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8129 emitcode ("orl", "a,b");
8132 if (p_type == GPOINTER)
8133 emitcode ("pop", "b");
8139 emitcode ("mov", "@%s,a", rname);
8143 emitcode ("movx", "@dptr,a");
8147 emitcode ("lcall", "__gptrput");
8151 /*-----------------------------------------------------------------*/
8152 /* genDataPointerSet - remat pointer to data space */
8153 /*-----------------------------------------------------------------*/
8155 genDataPointerSet (operand * right,
8159 int size, offset = 0;
8160 char *l, buffer[256];
8162 aopOp (right, ic, FALSE, FALSE);
8164 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8165 size = AOP_SIZE (right);
8169 sprintf (buffer, "(%s + %d)", l + 1, offset);
8171 sprintf (buffer, "%s", l + 1);
8172 emitcode ("mov", "%s,%s", buffer,
8173 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8176 freeAsmop (right, NULL, ic, TRUE);
8177 freeAsmop (result, NULL, ic, TRUE);
8180 /*-----------------------------------------------------------------*/
8181 /* genNearPointerSet - emitcode for near pointer put */
8182 /*-----------------------------------------------------------------*/
8184 genNearPointerSet (operand * right,
8191 sym_link *retype, *letype;
8192 sym_link *ptype = operandType (result);
8194 retype = getSpec (operandType (right));
8195 letype = getSpec (ptype);
8197 aopOp (result, ic, FALSE, FALSE);
8199 /* if the result is rematerializable &
8200 in data space & not a bit variable */
8201 if (AOP_TYPE (result) == AOP_IMMD &&
8202 DCL_TYPE (ptype) == POINTER &&
8203 !IS_BITVAR (retype) &&
8204 !IS_BITVAR (letype))
8206 genDataPointerSet (right, result, ic);
8210 /* if the value is already in a pointer register
8211 then don't need anything more */
8212 if (!AOP_INPREG (AOP (result)))
8214 /* otherwise get a free pointer register */
8216 preg = getFreePtr (ic, &aop, FALSE);
8217 emitcode ("mov", "%s,%s",
8219 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8223 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8225 freeAsmop (result, NULL, ic, TRUE);
8226 aopOp (right, ic, FALSE, FALSE);
8228 /* if bitfield then unpack the bits */
8229 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8230 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8233 /* we have can just get the values */
8234 int size = AOP_SIZE (right);
8239 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8243 emitcode ("mov", "@%s,a", rname);
8246 emitcode ("mov", "@%s,%s", rname, l);
8248 emitcode ("inc", "%s", rname);
8253 /* now some housekeeping stuff */
8256 /* we had to allocate for this iCode */
8257 freeAsmop (NULL, aop, ic, TRUE);
8261 /* we did not allocate which means left
8262 already in a pointer register, then
8263 if size > 0 && this could be used again
8264 we have to point it back to where it
8266 if (AOP_SIZE (right) > 1 &&
8267 !OP_SYMBOL (result)->remat &&
8268 (OP_SYMBOL (result)->liveTo > ic->seq ||
8271 int size = AOP_SIZE (right) - 1;
8273 emitcode ("dec", "%s", rname);
8278 freeAsmop (right, NULL, ic, TRUE);
8283 /*-----------------------------------------------------------------*/
8284 /* genPagedPointerSet - emitcode for Paged pointer put */
8285 /*-----------------------------------------------------------------*/
8287 genPagedPointerSet (operand * right,
8294 sym_link *retype, *letype;
8296 retype = getSpec (operandType (right));
8297 letype = getSpec (operandType (result));
8299 aopOp (result, ic, FALSE, FALSE);
8301 /* if the value is already in a pointer register
8302 then don't need anything more */
8303 if (!AOP_INPREG (AOP (result)))
8305 /* otherwise get a free pointer register */
8307 preg = getFreePtr (ic, &aop, FALSE);
8308 emitcode ("mov", "%s,%s",
8310 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8314 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8316 freeAsmop (result, NULL, ic, TRUE);
8317 aopOp (right, ic, FALSE, FALSE);
8319 /* if bitfield then unpack the bits */
8320 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8321 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8324 /* we have can just get the values */
8325 int size = AOP_SIZE (right);
8330 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8333 emitcode ("movx", "@%s,a", rname);
8336 emitcode ("inc", "%s", rname);
8342 /* now some housekeeping stuff */
8345 /* we had to allocate for this iCode */
8346 freeAsmop (NULL, aop, ic, TRUE);
8350 /* we did not allocate which means left
8351 already in a pointer register, then
8352 if size > 0 && this could be used again
8353 we have to point it back to where it
8355 if (AOP_SIZE (right) > 1 &&
8356 !OP_SYMBOL (result)->remat &&
8357 (OP_SYMBOL (result)->liveTo > ic->seq ||
8360 int size = AOP_SIZE (right) - 1;
8362 emitcode ("dec", "%s", rname);
8367 freeAsmop (right, NULL, ic, TRUE);
8372 /*-----------------------------------------------------------------*/
8373 /* genFarPointerSet - set value from far space */
8374 /*-----------------------------------------------------------------*/
8376 genFarPointerSet (operand * right,
8377 operand * result, iCode * ic)
8380 sym_link *retype = getSpec (operandType (right));
8381 sym_link *letype = getSpec (operandType (result));
8383 aopOp (result, ic, FALSE, FALSE);
8385 /* if the operand is already in dptr
8386 then we do nothing else we move the value to dptr */
8387 if (AOP_TYPE (result) != AOP_STR)
8389 /* if this is remateriazable */
8390 if (AOP_TYPE (result) == AOP_IMMD)
8391 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8394 /* we need to get it byte by byte */
8395 _startLazyDPSEvaluation ();
8396 if (AOP_TYPE (result) != AOP_DPTR)
8398 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8399 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8400 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8404 /* We need to generate a load to DPTR indirect through DPTR. */
8405 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8407 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8408 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8409 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8410 emitcode ("pop", "dph");
8411 emitcode ("pop", "dpl");
8413 _endLazyDPSEvaluation ();
8416 /* so dptr know contains the address */
8417 freeAsmop (result, NULL, ic, TRUE);
8418 aopOp (right, ic, FALSE, TRUE);
8420 /* if bit then unpack */
8421 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8422 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8425 size = AOP_SIZE (right);
8428 _startLazyDPSEvaluation ();
8431 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8437 emitcode ("movx", "@dptr,a");
8439 emitcode ("inc", "dptr");
8441 _endLazyDPSEvaluation ();
8444 freeAsmop (right, NULL, ic, TRUE);
8447 /*-----------------------------------------------------------------*/
8448 /* genGenPointerSet - set value from generic pointer space */
8449 /*-----------------------------------------------------------------*/
8451 genGenPointerSet (operand * right,
8452 operand * result, iCode * ic)
8455 sym_link *retype = getSpec (operandType (right));
8456 sym_link *letype = getSpec (operandType (result));
8458 aopOp (result, ic, FALSE, TRUE);
8460 /* if the operand is already in dptr
8461 then we do nothing else we move the value to dptr */
8462 if (AOP_TYPE (result) != AOP_STR)
8464 _startLazyDPSEvaluation ();
8465 /* if this is remateriazable */
8466 if (AOP_TYPE (result) == AOP_IMMD)
8468 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8469 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8472 { /* we need to get it byte by byte */
8473 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8474 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8475 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8476 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8478 _endLazyDPSEvaluation ();
8480 /* so dptr know contains the address */
8481 freeAsmop (result, NULL, ic, TRUE);
8482 aopOp (right, ic, FALSE, TRUE);
8484 /* if bit then unpack */
8485 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8486 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8489 size = AOP_SIZE (right);
8492 _startLazyDPSEvaluation ();
8495 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8501 emitcode ("lcall", "__gptrput");
8503 emitcode ("inc", "dptr");
8505 _endLazyDPSEvaluation ();
8508 freeAsmop (right, NULL, ic, TRUE);
8511 /*-----------------------------------------------------------------*/
8512 /* genPointerSet - stores the value into a pointer location */
8513 /*-----------------------------------------------------------------*/
8515 genPointerSet (iCode * ic)
8517 operand *right, *result;
8518 sym_link *type, *etype;
8521 D (emitcode (";", "genPointerSet ");
8524 right = IC_RIGHT (ic);
8525 result = IC_RESULT (ic);
8527 /* depending on the type of pointer we need to
8528 move it to the correct pointer register */
8529 type = operandType (result);
8530 etype = getSpec (type);
8531 /* if left is of type of pointer then it is simple */
8532 if (IS_PTR (type) && !IS_FUNC (type->next))
8534 p_type = DCL_TYPE (type);
8538 /* we have to go by the storage class */
8539 p_type = PTR_TYPE (SPEC_OCLS (etype));
8542 /* now that we have the pointer type we assign
8543 the pointer values */
8549 genNearPointerSet (right, result, ic);
8553 genPagedPointerSet (right, result, ic);
8557 genFarPointerSet (right, result, ic);
8561 genGenPointerSet (right, result, ic);
8567 /*-----------------------------------------------------------------*/
8568 /* genIfx - generate code for Ifx statement */
8569 /*-----------------------------------------------------------------*/
8571 genIfx (iCode * ic, iCode * popIc)
8573 operand *cond = IC_COND (ic);
8576 D (emitcode (";", "genIfx ");
8579 aopOp (cond, ic, FALSE, FALSE);
8581 /* get the value into acc */
8582 if (AOP_TYPE (cond) != AOP_CRY)
8586 /* the result is now in the accumulator */
8587 freeAsmop (cond, NULL, ic, TRUE);
8589 /* if there was something to be popped then do it */
8593 /* if the condition is a bit variable */
8594 if (isbit && IS_ITEMP (cond) &&
8596 genIfxJump (ic, SPIL_LOC (cond)->rname);
8597 else if (isbit && !IS_ITEMP (cond))
8598 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8600 genIfxJump (ic, "a");
8605 /*-----------------------------------------------------------------*/
8606 /* genAddrOf - generates code for address of */
8607 /*-----------------------------------------------------------------*/
8609 genAddrOf (iCode * ic)
8611 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8614 D (emitcode (";", "genAddrOf ");
8617 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8619 /* if the operand is on the stack then we
8620 need to get the stack offset of this
8624 /* if it has an offset then we need to compute
8628 emitcode ("mov", "a,_bp");
8629 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8630 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8634 /* we can just move _bp */
8635 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8637 /* fill the result with zero */
8638 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8641 if (options.stack10bit && size < (FPTRSIZE - 1))
8644 "*** warning: pointer to stack var truncated.\n");
8651 if (options.stack10bit && offset == 2)
8653 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8657 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8664 /* object not on stack then we need the name */
8665 size = AOP_SIZE (IC_RESULT (ic));
8670 char s[SDCC_NAME_MAX];
8672 sprintf (s, "#(%s >> %d)",
8676 sprintf (s, "#%s", sym->rname);
8677 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8681 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8685 /*-----------------------------------------------------------------*/
8686 /* genFarFarAssign - assignment when both are in far space */
8687 /*-----------------------------------------------------------------*/
8689 genFarFarAssign (operand * result, operand * right, iCode * ic)
8691 int size = AOP_SIZE (right);
8697 /* This is a net loss for size == 1, but a big gain
8700 D (emitcode (";", "genFarFarAssign (improved)");
8703 aopOp (result, ic, TRUE, TRUE);
8705 _startLazyDPSEvaluation ();
8708 aopPut (AOP (result),
8709 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8712 _endLazyDPSEvaluation ();
8713 freeAsmop (result, NULL, ic, FALSE);
8714 freeAsmop (right, NULL, ic, FALSE);
8718 D (emitcode (";", "genFarFarAssign ");
8721 /* first push the right side on to the stack */
8722 _startLazyDPSEvaluation ();
8725 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8727 emitcode ("push", "acc");
8730 freeAsmop (right, NULL, ic, FALSE);
8731 /* now assign DPTR to result */
8732 aopOp (result, ic, FALSE, FALSE);
8733 size = AOP_SIZE (result);
8736 emitcode ("pop", "acc");
8737 aopPut (AOP (result), "a", --offset);
8739 freeAsmop (result, NULL, ic, FALSE);
8740 _endLazyDPSEvaluation ();
8744 /*-----------------------------------------------------------------*/
8745 /* genAssign - generate code for assignment */
8746 /*-----------------------------------------------------------------*/
8748 genAssign (iCode * ic)
8750 operand *result, *right;
8752 unsigned long lit = 0L;
8754 D (emitcode (";", "genAssign ");
8757 result = IC_RESULT (ic);
8758 right = IC_RIGHT (ic);
8760 /* if they are the same */
8761 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8764 aopOp (right, ic, FALSE, FALSE);
8766 emitcode (";", "genAssign: resultIsFar = %s",
8767 isOperandInFarSpace (result) ?
8770 /* special case both in far space */
8771 if ((AOP_TYPE (right) == AOP_DPTR ||
8772 AOP_TYPE (right) == AOP_DPTR2) &&
8773 /* IS_TRUE_SYMOP(result) && */
8774 isOperandInFarSpace (result))
8776 genFarFarAssign (result, right, ic);
8780 aopOp (result, ic, TRUE, FALSE);
8782 /* if they are the same registers */
8783 if (sameRegs (AOP (right), AOP (result)))
8786 /* if the result is a bit */
8787 if (AOP_TYPE (result) == AOP_CRY)
8790 /* if the right size is a literal then
8791 we know what the value is */
8792 if (AOP_TYPE (right) == AOP_LIT)
8794 if (((int) operandLitValue (right)))
8795 aopPut (AOP (result), one, 0);
8797 aopPut (AOP (result), zero, 0);
8801 /* the right is also a bit variable */
8802 if (AOP_TYPE (right) == AOP_CRY)
8804 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8805 aopPut (AOP (result), "c", 0);
8811 aopPut (AOP (result), "a", 0);
8815 /* bit variables done */
8817 size = AOP_SIZE (result);
8819 if (AOP_TYPE (right) == AOP_LIT)
8820 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8823 (AOP_TYPE (result) != AOP_REG) &&
8824 (AOP_TYPE (right) == AOP_LIT) &&
8825 !IS_FLOAT (operandType (right)))
8827 D (emitcode (";", "Kevin's better literal load code");
8829 _startLazyDPSEvaluation ();
8830 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8832 aopPut (AOP (result),
8833 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8838 /* And now fill the rest with zeros. */
8841 emitcode ("clr", "a");
8845 aopPut (AOP (result), "a", offset++);
8847 _endLazyDPSEvaluation ();
8851 _startLazyDPSEvaluation ();
8854 aopPut (AOP (result),
8855 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8859 _endLazyDPSEvaluation ();
8863 freeAsmop (right, NULL, ic, FALSE);
8864 freeAsmop (result, NULL, ic, TRUE);
8867 /*-----------------------------------------------------------------*/
8868 /* genJumpTab - generates code for jump table */
8869 /*-----------------------------------------------------------------*/
8871 genJumpTab (iCode * ic)
8876 D (emitcode (";", "genJumpTab ");
8879 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8880 /* get the condition into accumulator */
8881 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8883 /* multiply by four! */
8884 emitcode ("add", "a,acc");
8885 emitcode ("add", "a,acc");
8886 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8888 jtab = newiTempLabel (NULL);
8889 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8890 emitcode ("jmp", "@a+dptr");
8891 emitcode ("", "%05d$:", jtab->key + 100);
8892 /* now generate the jump labels */
8893 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8894 jtab = setNextItem (IC_JTLABELS (ic)))
8895 emitcode ("ljmp", "%05d$", jtab->key + 100);
8899 /*-----------------------------------------------------------------*/
8900 /* genCast - gen code for casting */
8901 /*-----------------------------------------------------------------*/
8903 genCast (iCode * ic)
8905 operand *result = IC_RESULT (ic);
8906 sym_link *ctype = operandType (IC_LEFT (ic));
8907 sym_link *rtype = operandType (IC_RIGHT (ic));
8908 operand *right = IC_RIGHT (ic);
8911 D (emitcode (";", "genCast ");
8914 /* if they are equivalent then do nothing */
8915 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8918 aopOp (right, ic, FALSE, FALSE);
8919 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8921 /* if the result is a bit */
8922 if (AOP_TYPE (result) == AOP_CRY)
8924 /* if the right size is a literal then
8925 we know what the value is */
8926 if (AOP_TYPE (right) == AOP_LIT)
8928 if (((int) operandLitValue (right)))
8929 aopPut (AOP (result), one, 0);
8931 aopPut (AOP (result), zero, 0);
8936 /* the right is also a bit variable */
8937 if (AOP_TYPE (right) == AOP_CRY)
8939 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8940 aopPut (AOP (result), "c", 0);
8946 aopPut (AOP (result), "a", 0);
8950 /* if they are the same size : or less */
8951 if (AOP_SIZE (result) <= AOP_SIZE (right))
8954 /* if they are in the same place */
8955 if (sameRegs (AOP (right), AOP (result)))
8958 /* if they in different places then copy */
8959 size = AOP_SIZE (result);
8961 _startLazyDPSEvaluation ();
8964 aopPut (AOP (result),
8965 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8969 _endLazyDPSEvaluation ();
8974 /* if the result is of type pointer */
8979 sym_link *type = operandType (right);
8981 /* pointer to generic pointer */
8982 if (IS_GENPTR (ctype))
8988 p_type = DCL_TYPE (type);
8992 #if OLD_CAST_BEHAVIOR
8993 /* KV: we are converting a non-pointer type to
8994 * a generic pointer. This (ifdef'd out) code
8995 * says that the resulting generic pointer
8996 * should have the same class as the storage
8997 * location of the non-pointer variable.
8999 * For example, converting an int (which happens
9000 * to be stored in DATA space) to a pointer results
9001 * in a DATA generic pointer; if the original int
9002 * in XDATA space, so will be the resulting pointer.
9004 * I don't like that behavior, and thus this change:
9005 * all such conversions will be forced to XDATA and
9006 * throw a warning. If you want some non-XDATA
9007 * type, or you want to suppress the warning, you
9008 * must go through an intermediate cast, like so:
9010 * char _generic *gp = (char _xdata *)(intVar);
9012 sym_link *etype = getSpec (type);
9014 /* we have to go by the storage class */
9015 if (SPEC_OCLS (etype) != generic)
9017 p_type = PTR_TYPE (SPEC_OCLS (etype));
9022 /* Converting unknown class (i.e. register variable)
9023 * to generic pointer. This is not good, but
9024 * we'll make a guess (and throw a warning).
9027 werror (W_INT_TO_GEN_PTR_CAST);
9031 /* the first two bytes are known */
9032 size = GPTRSIZE - 1;
9034 _startLazyDPSEvaluation ();
9037 aopPut (AOP (result),
9038 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9042 _endLazyDPSEvaluation ();
9044 /* the last byte depending on type */
9062 /* this should never happen */
9063 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9064 "got unknown pointer type");
9067 aopPut (AOP (result), l, GPTRSIZE - 1);
9071 /* just copy the pointers */
9072 size = AOP_SIZE (result);
9074 _startLazyDPSEvaluation ();
9077 aopPut (AOP (result),
9078 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9082 _endLazyDPSEvaluation ();
9086 /* so we now know that the size of destination is greater
9087 than the size of the source */
9088 /* we move to result for the size of source */
9089 size = AOP_SIZE (right);
9091 _startLazyDPSEvaluation ();
9094 aopPut (AOP (result),
9095 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9099 _endLazyDPSEvaluation ();
9101 /* now depending on the sign of the source && destination */
9102 size = AOP_SIZE (result) - AOP_SIZE (right);
9103 /* if unsigned or not an integral type */
9104 /* also, if the source is a bit, we don't need to sign extend, because
9105 * it can't possibly have set the sign bit.
9107 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9111 aopPut (AOP (result), zero, offset++);
9116 /* we need to extend the sign :{ */
9117 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9118 FALSE, FALSE, TRUE);
9120 emitcode ("rlc", "a");
9121 emitcode ("subb", "a,acc");
9123 aopPut (AOP (result), "a", offset++);
9126 /* we are done hurray !!!! */
9129 freeAsmop (right, NULL, ic, TRUE);
9130 freeAsmop (result, NULL, ic, TRUE);
9134 /*-----------------------------------------------------------------*/
9135 /* genDjnz - generate decrement & jump if not zero instrucion */
9136 /*-----------------------------------------------------------------*/
9138 genDjnz (iCode * ic, iCode * ifx)
9144 /* if the if condition has a false label
9145 then we cannot save */
9149 /* if the minus is not of the form
9151 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9152 !IS_OP_LITERAL (IC_RIGHT (ic)))
9155 if (operandLitValue (IC_RIGHT (ic)) != 1)
9158 /* if the size of this greater than one then no
9160 if (getSize (operandType (IC_RESULT (ic))) > 1)
9163 /* otherwise we can save BIG */
9164 lbl = newiTempLabel (NULL);
9165 lbl1 = newiTempLabel (NULL);
9167 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9169 if (IS_AOP_PREG (IC_RESULT (ic)))
9171 emitcode ("dec", "%s",
9172 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9173 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9174 emitcode ("jnz", "%05d$", lbl->key + 100);
9178 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9181 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9182 emitcode ("", "%05d$:", lbl->key + 100);
9183 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9184 emitcode ("", "%05d$:", lbl1->key + 100);
9186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9191 /*-----------------------------------------------------------------*/
9192 /* genReceive - generate code for a receive iCode */
9193 /*-----------------------------------------------------------------*/
9195 genReceive (iCode * ic)
9198 D (emitcode (";", "genReceive ");
9201 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9202 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9203 IS_TRUE_SYMOP (IC_RESULT (ic))))
9205 int size = getSize (operandType (IC_RESULT (ic)));
9206 int offset = fReturnSizeDS390 - size;
9209 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9210 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9213 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9214 size = AOP_SIZE (IC_RESULT (ic));
9218 emitcode ("pop", "acc");
9219 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9226 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9228 assignResultValue (IC_RESULT (ic));
9231 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9234 /*-----------------------------------------------------------------*/
9235 /* gen390Code - generate code for Dallas 390 based controllers */
9236 /*-----------------------------------------------------------------*/
9238 gen390Code (iCode * lic)
9243 lineHead = lineCurr = NULL;
9247 /* print the allocation information */
9249 printAllocInfo (currFunc, codeOutFile);
9251 /* if debug information required */
9252 if (options.debug && currFunc)
9254 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9256 if (IS_STATIC (currFunc->etype))
9257 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9259 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9262 /* stack pointer name */
9263 if (options.useXstack)
9269 for (ic = lic; ic; ic = ic->next)
9272 if (cln != ic->lineno)
9277 emitcode ("", "C$%s$%d$%d$%d ==.",
9278 FileBaseName (ic->filename), ic->lineno,
9279 ic->level, ic->block);
9282 emitcode (";", "%s %d", ic->filename, ic->lineno);
9285 /* if the result is marked as
9286 spilt and rematerializable or code for
9287 this has already been generated then
9289 if (resultRemat (ic) || ic->generated)
9292 /* depending on the operation */
9312 /* IPOP happens only when trying to restore a
9313 spilt live range, if there is an ifx statement
9314 following this pop then the if statement might
9315 be using some of the registers being popped which
9316 would destory the contents of the register so
9317 we need to check for this condition and handle it */
9319 ic->next->op == IFX &&
9320 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9321 genIfx (ic->next, ic);
9339 genEndFunction (ic);
9359 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9376 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9380 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9387 /* note these two are xlated by algebraic equivalence
9388 during parsing SDCC.y */
9389 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9390 "got '>=' or '<=' shouldn't have come here");
9394 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9406 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9410 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9414 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9441 case GET_VALUE_AT_ADDRESS:
9446 if (POINTER_SET (ic))
9473 addSet (&_G.sendSet, ic);
9482 /* now we are ready to call the
9483 peep hole optimizer */
9484 if (!options.nopeep)
9485 peepHole (&lineHead);
9487 /* now do the actual printing */
9488 printLine (lineHead, codeOutFile);