1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
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!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 extern int mcs51_ptrRegReq;
97 extern int mcs51_nRegs;
98 extern FILE *codeOutFile;
99 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 sprintf (lb, "%s\t", inst);
140 sprintf (lb, "%s", inst);
141 vsprintf (lb + (strlen (lb)), fmt, ap);
144 vsprintf (lb, fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
386 val += (int) operandLitValue (IC_RIGHT (ic));
387 else if (ic->op == '-')
388 val -= (int) operandLitValue (IC_RIGHT (ic));
389 else if (IS_CAST_ICODE(ic)) {
390 sym_link *from_type = operandType(IC_RIGHT(ic));
391 aop->aopu.aop_immd.from_cast_remat = 1;
392 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
393 ptr_type = DCL_TYPE(from_type);
397 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
401 sprintf (buffer, "(%s %c 0x%04x)",
402 OP_SYMBOL (IC_LEFT (ic))->rname,
403 val >= 0 ? '+' : '-',
406 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
408 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
409 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
410 /* set immd2 field if required */
411 if (aop->aopu.aop_immd.from_cast_remat) {
412 sprintf(buffer,"#0x%02x",ptr_type);
413 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
414 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
420 /*-----------------------------------------------------------------*/
421 /* regsInCommon - two operands have some registers in common */
422 /*-----------------------------------------------------------------*/
424 regsInCommon (operand * op1, operand * op2)
429 /* if they have registers in common */
430 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
433 sym1 = OP_SYMBOL (op1);
434 sym2 = OP_SYMBOL (op2);
436 if (sym1->nRegs == 0 || sym2->nRegs == 0)
439 for (i = 0; i < sym1->nRegs; i++)
445 for (j = 0; j < sym2->nRegs; j++)
450 if (sym2->regs[j] == sym1->regs[i])
458 /*-----------------------------------------------------------------*/
459 /* operandsEqu - equivalent */
460 /*-----------------------------------------------------------------*/
462 operandsEqu (operand * op1, operand * op2)
466 /* if they not symbols */
467 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
470 sym1 = OP_SYMBOL (op1);
471 sym2 = OP_SYMBOL (op2);
473 /* if both are itemps & one is spilt
474 and the other is not then false */
475 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
476 sym1->isspilt != sym2->isspilt)
479 /* if they are the same */
483 if (strcmp (sym1->rname, sym2->rname) == 0)
487 /* if left is a tmp & right is not */
488 if (IS_ITEMP (op1) &&
491 (sym1->usl.spillLoc == sym2))
494 if (IS_ITEMP (op2) &&
498 (sym2->usl.spillLoc == sym1))
504 /*-----------------------------------------------------------------*/
505 /* sameRegs - two asmops have the same registers */
506 /*-----------------------------------------------------------------*/
508 sameRegs (asmop * aop1, asmop * aop2)
515 if (aop1->type != AOP_REG ||
516 aop2->type != AOP_REG)
519 if (aop1->size != aop2->size)
522 for (i = 0; i < aop1->size; i++)
523 if (aop1->aopu.aop_reg[i] !=
524 aop2->aopu.aop_reg[i])
530 /*-----------------------------------------------------------------*/
531 /* aopOp - allocates an asmop for an operand : */
532 /*-----------------------------------------------------------------*/
534 aopOp (operand * op, iCode * ic, bool result)
543 /* if this a literal */
544 if (IS_OP_LITERAL (op))
546 op->aop = aop = newAsmop (AOP_LIT);
547 aop->aopu.aop_lit = op->operand.valOperand;
548 aop->size = getSize (operandType (op));
552 /* if already has a asmop then continue */
556 /* if the underlying symbol has a aop */
557 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
559 op->aop = OP_SYMBOL (op)->aop;
563 /* if this is a true symbol */
564 if (IS_TRUE_SYMOP (op))
566 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
570 /* this is a temporary : this has
576 e) can be a return use only */
578 sym = OP_SYMBOL (op);
580 /* if the type is a conditional */
581 if (sym->regType == REG_CND)
583 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
588 /* if it is spilt then two situations
590 b) has a spill location */
591 if (sym->isspilt || sym->nRegs == 0)
594 /* rematerialize it NOW */
597 sym->aop = op->aop = aop =
599 aop->size = getSize (sym->type);
606 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
607 aop->size = getSize (sym->type);
608 for (i = 0; i < 2; i++)
609 aop->aopu.aop_str[i] = accUse[i];
617 aop = op->aop = sym->aop = newAsmop (AOP_STR);
618 aop->size = getSize (sym->type);
619 for (i = 0; i < fReturnSizeMCS51; i++)
620 aop->aopu.aop_str[i] = fReturn[i];
624 /* else spill location */
625 sym->aop = op->aop = aop =
626 aopForSym (ic, sym->usl.spillLoc, result);
627 aop->size = getSize (sym->type);
631 /* must be in a register */
632 sym->aop = op->aop = aop = newAsmop (AOP_REG);
633 aop->size = sym->nRegs;
634 for (i = 0; i < sym->nRegs; i++)
635 aop->aopu.aop_reg[i] = sym->regs[i];
638 /*-----------------------------------------------------------------*/
639 /* freeAsmop - free up the asmop given to an operand */
640 /*----------------------------------------------------------------*/
642 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
659 /* depending on the asmop type only three cases need work AOP_RO
660 , AOP_R1 && AOP_STK */
668 emitcode ("pop", "ar0");
672 bitVectUnSetBit (ic->rUsed, R0_IDX);
680 emitcode ("pop", "ar1");
684 bitVectUnSetBit (ic->rUsed, R1_IDX);
690 int stk = aop->aopu.aop_stk + aop->size;
691 bitVectUnSetBit (ic->rUsed, R0_IDX);
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
694 getFreePtr (ic, &aop, FALSE);
698 emitcode ("mov", "a,_bp");
699 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
700 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
704 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
709 emitcode ("pop", "acc");
710 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
713 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
716 freeAsmop (op, NULL, ic, TRUE);
719 emitcode ("pop", "ar0");
725 emitcode ("pop", "ar1");
732 /* all other cases just dealloc */
738 OP_SYMBOL (op)->aop = NULL;
739 /* if the symbol has a spill */
741 SPIL_LOC (op)->aop = NULL;
746 /*-----------------------------------------------------------------*/
747 /* aopGet - for fetching value of the aop */
748 /*-----------------------------------------------------------------*/
750 aopGet (asmop * aop, int offset, bool bit16, bool dname)
755 /* offset is greater than
757 if (offset > (aop->size - 1) &&
758 aop->type != AOP_LIT)
761 /* depending on type */
767 /* if we need to increment it */
768 while (offset > aop->coff)
770 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
774 while (offset < aop->coff)
776 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
783 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
784 return (dname ? "acc" : "a");
786 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
787 rs = Safe_calloc (1, strlen (s) + 1);
792 while (offset > aop->coff)
794 emitcode ("inc", "dptr");
798 while (offset < aop->coff)
800 emitcode ("lcall", "__decdptr");
807 emitcode ("clr", "a");
808 emitcode ("movc", "a,@a+dptr");
812 emitcode ("movx", "a,@dptr");
814 return (dname ? "acc" : "a");
818 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
819 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
821 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
823 sprintf (s, "#(%s >> %d)",
824 aop->aopu.aop_immd.aop_immd1,
828 aop->aopu.aop_immd.aop_immd1);
829 rs = Safe_calloc (1, strlen (s) + 1);
835 sprintf (s, "(%s + %d)",
839 sprintf (s, "%s", aop->aopu.aop_dir);
840 rs = Safe_calloc (1, strlen (s) + 1);
846 return aop->aopu.aop_reg[offset]->dname;
848 return aop->aopu.aop_reg[offset]->name;
851 emitcode ("clr", "a");
852 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
853 emitcode ("rlc", "a");
854 return (dname ? "acc" : "a");
857 if (!offset && dname)
859 return aop->aopu.aop_str[offset];
862 return aopLiteral (aop->aopu.aop_lit, offset);
866 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
870 return aop->aopu.aop_str[offset];
874 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
875 "aopget got unsupported aop->type");
878 /*-----------------------------------------------------------------*/
879 /* aopPut - puts a string for a aop */
880 /*-----------------------------------------------------------------*/
882 aopPut (asmop * aop, char *s, int offset)
886 if (aop->size && offset > (aop->size - 1))
888 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
889 "aopPut got offset > aop->size");
893 /* will assign value to value */
894 /* depending on where it is ofcourse */
899 sprintf (d, "(%s + %d)",
900 aop->aopu.aop_dir, offset);
902 sprintf (d, "%s", aop->aopu.aop_dir);
905 emitcode ("mov", "%s,%s", d, s);
910 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
911 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
914 strcmp (s, "r0") == 0 ||
915 strcmp (s, "r1") == 0 ||
916 strcmp (s, "r2") == 0 ||
917 strcmp (s, "r3") == 0 ||
918 strcmp (s, "r4") == 0 ||
919 strcmp (s, "r5") == 0 ||
920 strcmp (s, "r6") == 0 ||
921 strcmp (s, "r7") == 0)
922 emitcode ("mov", "%s,%s",
923 aop->aopu.aop_reg[offset]->dname, s);
925 emitcode ("mov", "%s,%s",
926 aop->aopu.aop_reg[offset]->name, s);
933 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
934 "aopPut writting to code space");
938 while (offset > aop->coff)
941 emitcode ("inc", "dptr");
944 while (offset < aop->coff)
947 emitcode ("lcall", "__decdptr");
952 /* if not in accumulater */
955 emitcode ("movx", "@dptr,a");
960 while (offset > aop->coff)
963 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
965 while (offset < aop->coff)
968 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
975 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
981 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
983 else if (strcmp (s, "r0") == 0 ||
984 strcmp (s, "r1") == 0 ||
985 strcmp (s, "r2") == 0 ||
986 strcmp (s, "r3") == 0 ||
987 strcmp (s, "r4") == 0 ||
988 strcmp (s, "r5") == 0 ||
989 strcmp (s, "r6") == 0 ||
990 strcmp (s, "r7") == 0)
993 sprintf (buffer, "a%s", s);
994 emitcode ("mov", "@%s,%s",
995 aop->aopu.aop_ptr->name, buffer);
998 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1003 if (strcmp (s, "a") == 0)
1004 emitcode ("push", "acc");
1008 emitcode ("push", "acc");
1010 emitcode ("push", s);
1016 /* if bit variable */
1017 if (!aop->aopu.aop_dir)
1019 emitcode ("clr", "a");
1020 emitcode ("rlc", "a");
1025 emitcode ("clr", "%s", aop->aopu.aop_dir);
1027 emitcode ("setb", "%s", aop->aopu.aop_dir);
1028 else if (!strcmp (s, "c"))
1029 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1032 if (strcmp (s, "a"))
1037 symbol *lbl = newiTempLabel (NULL);
1038 emitcode ("clr", "c");
1039 emitcode ("jz", "%05d$", lbl->key + 100);
1040 emitcode ("cpl", "c");
1041 emitcode ("", "%05d$:", lbl->key + 100);
1042 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1050 if (strcmp (aop->aopu.aop_str[offset], s))
1051 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1056 if (!offset && (strcmp (s, "acc") == 0))
1059 if (strcmp (aop->aopu.aop_str[offset], s))
1060 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1064 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1065 "aopPut got unsupported aop->type");
1073 /*-----------------------------------------------------------------*/
1074 /* pointToEnd :- points to the last byte of the operand */
1075 /*-----------------------------------------------------------------*/
1077 pointToEnd (asmop * aop)
1083 aop->coff = count = (aop->size - 1);
1089 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1093 emitcode ("inc", "dptr");
1100 /*-----------------------------------------------------------------*/
1101 /* reAdjustPreg - points a register back to where it should */
1102 /*-----------------------------------------------------------------*/
1104 reAdjustPreg (asmop * aop)
1106 if ((aop->coff==0) || aop->size <= 1)
1114 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1119 emitcode ("lcall", "__decdptr");
1126 #define AOP(op) op->aop
1127 #define AOP_TYPE(op) AOP(op)->type
1128 #define AOP_SIZE(op) AOP(op)->size
1129 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1130 AOP_TYPE(x) == AOP_R0))
1132 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1133 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1135 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1136 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1137 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1139 /*-----------------------------------------------------------------*/
1140 /* genNotFloat - generates not for float operations */
1141 /*-----------------------------------------------------------------*/
1143 genNotFloat (operand * op, operand * res)
1149 D(emitcode (";", "genNotFloat"));
1151 /* we will put 127 in the first byte of
1153 aopPut (AOP (res), "#127", 0);
1154 size = AOP_SIZE (op) - 1;
1157 l = aopGet (op->aop, offset++, FALSE, FALSE);
1162 emitcode ("orl", "a,%s",
1164 offset++, FALSE, FALSE));
1167 tlbl = newiTempLabel (NULL);
1168 aopPut (res->aop, one, 1);
1169 emitcode ("jz", "%05d$", (tlbl->key + 100));
1170 aopPut (res->aop, zero, 1);
1171 emitcode ("", "%05d$:", (tlbl->key + 100));
1173 size = res->aop->size - 2;
1175 /* put zeros in the rest */
1177 aopPut (res->aop, zero, offset++);
1180 /*-----------------------------------------------------------------*/
1181 /* opIsGptr: returns non-zero if the passed operand is */
1182 /* a generic pointer type. */
1183 /*-----------------------------------------------------------------*/
1185 opIsGptr (operand * op)
1187 sym_link *type = operandType (op);
1189 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1196 /*-----------------------------------------------------------------*/
1197 /* getDataSize - get the operand data size */
1198 /*-----------------------------------------------------------------*/
1200 getDataSize (operand * op)
1203 size = AOP_SIZE (op);
1204 if (size == GPTRSIZE)
1206 sym_link *type = operandType (op);
1207 if (IS_GENPTR (type))
1209 /* generic pointer; arithmetic operations
1210 * should ignore the high byte (pointer type).
1218 /*-----------------------------------------------------------------*/
1219 /* outAcc - output Acc */
1220 /*-----------------------------------------------------------------*/
1222 outAcc (operand * result)
1225 size = getDataSize (result);
1228 aopPut (AOP (result), "a", 0);
1231 /* unsigned or positive */
1234 aopPut (AOP (result), zero, offset++);
1239 /*-----------------------------------------------------------------*/
1240 /* outBitC - output a bit C */
1241 /*-----------------------------------------------------------------*/
1243 outBitC (operand * result)
1245 /* if the result is bit */
1246 if (AOP_TYPE (result) == AOP_CRY)
1247 aopPut (AOP (result), "c", 0);
1250 emitcode ("clr", "a");
1251 emitcode ("rlc", "a");
1256 /*-----------------------------------------------------------------*/
1257 /* toBoolean - emit code for orl a,operator(sizeop) */
1258 /*-----------------------------------------------------------------*/
1260 toBoolean (operand * oper)
1262 int size = AOP_SIZE (oper) - 1;
1264 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1266 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1270 /*-----------------------------------------------------------------*/
1271 /* genNot - generate code for ! operation */
1272 /*-----------------------------------------------------------------*/
1277 sym_link *optype = operandType (IC_LEFT (ic));
1279 D(emitcode (";", "genNot"));
1281 /* assign asmOps to operand & result */
1282 aopOp (IC_LEFT (ic), ic, FALSE);
1283 aopOp (IC_RESULT (ic), ic, TRUE);
1285 /* if in bit space then a special case */
1286 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1288 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1289 emitcode ("cpl", "c");
1290 outBitC (IC_RESULT (ic));
1294 /* if type float then do float */
1295 if (IS_FLOAT (optype))
1297 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1301 toBoolean (IC_LEFT (ic));
1303 tlbl = newiTempLabel (NULL);
1304 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1305 emitcode ("", "%05d$:", tlbl->key + 100);
1306 outBitC (IC_RESULT (ic));
1309 /* release the aops */
1310 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1311 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1315 /*-----------------------------------------------------------------*/
1316 /* genCpl - generate code for complement */
1317 /*-----------------------------------------------------------------*/
1325 D(emitcode (";", "genCpl"));
1327 /* assign asmOps to operand & result */
1328 aopOp (IC_LEFT (ic), ic, FALSE);
1329 aopOp (IC_RESULT (ic), ic, TRUE);
1331 /* if both are in bit space then
1333 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1334 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1337 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1338 emitcode ("cpl", "c");
1339 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1343 size = AOP_SIZE (IC_RESULT (ic));
1346 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1348 emitcode ("cpl", "a");
1349 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1354 /* release the aops */
1355 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1356 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1359 /*-----------------------------------------------------------------*/
1360 /* genUminusFloat - unary minus for floating points */
1361 /*-----------------------------------------------------------------*/
1363 genUminusFloat (operand * op, operand * result)
1365 int size, offset = 0;
1368 D(emitcode (";", "genUminusFloat"));
1370 /* for this we just need to flip the
1371 first it then copy the rest in place */
1372 size = AOP_SIZE (op) - 1;
1373 l = aopGet (AOP (op), 3, FALSE, FALSE);
1377 emitcode ("cpl", "acc.7");
1378 aopPut (AOP (result), "a", 3);
1382 aopPut (AOP (result),
1383 aopGet (AOP (op), offset, FALSE, FALSE),
1389 /*-----------------------------------------------------------------*/
1390 /* genUminus - unary minus code generation */
1391 /*-----------------------------------------------------------------*/
1393 genUminus (iCode * ic)
1396 sym_link *optype, *rtype;
1399 D(emitcode (";", "genUminus"));
1402 aopOp (IC_LEFT (ic), ic, FALSE);
1403 aopOp (IC_RESULT (ic), ic, TRUE);
1405 /* if both in bit space then special
1407 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1408 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1411 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1412 emitcode ("cpl", "c");
1413 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1417 optype = operandType (IC_LEFT (ic));
1418 rtype = operandType (IC_RESULT (ic));
1420 /* if float then do float stuff */
1421 if (IS_FLOAT (optype))
1423 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1427 /* otherwise subtract from zero */
1428 size = AOP_SIZE (IC_LEFT (ic));
1433 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1434 if (!strcmp (l, "a"))
1438 emitcode ("cpl", "a");
1439 emitcode ("addc", "a,#0");
1445 emitcode ("clr", "a");
1446 emitcode ("subb", "a,%s", l);
1448 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1451 /* if any remaining bytes in the result */
1452 /* we just need to propagate the sign */
1453 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1455 emitcode ("rlc", "a");
1456 emitcode ("subb", "a,acc");
1458 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1462 /* release the aops */
1463 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1464 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1467 /*-----------------------------------------------------------------*/
1468 /* saveRegisters - will look for a call and save the registers */
1469 /*-----------------------------------------------------------------*/
1471 saveRegisters (iCode * lic)
1478 for (ic = lic; ic; ic = ic->next)
1479 if (ic->op == CALL || ic->op == PCALL)
1484 fprintf (stderr, "found parameter push with no function call\n");
1488 /* if the registers have been saved already or don't need to be then
1490 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1491 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1494 /* safe the registers in use at this time but skip the
1495 ones for the result */
1496 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1497 mcs51_rUmaskForOp (IC_RESULT(ic)));
1500 if (options.useXstack)
1502 if (bitVectBitValue (rsave, R0_IDX))
1503 emitcode ("mov", "b,r0");
1504 emitcode ("mov", "r0,%s", spname);
1505 for (i = 0; i < mcs51_nRegs; i++)
1507 if (bitVectBitValue (rsave, i))
1510 emitcode ("mov", "a,b");
1512 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1513 emitcode ("movx", "@r0,a");
1514 emitcode ("inc", "r0");
1517 emitcode ("mov", "%s,r0", spname);
1518 if (bitVectBitValue (rsave, R0_IDX))
1519 emitcode ("mov", "r0,b");
1522 for (i = 0; i < mcs51_nRegs; i++)
1524 if (bitVectBitValue (rsave, i))
1525 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1529 /*-----------------------------------------------------------------*/
1530 /* unsaveRegisters - pop the pushed registers */
1531 /*-----------------------------------------------------------------*/
1533 unsaveRegisters (iCode * ic)
1538 /* restore the registers in use at this time but skip the
1539 ones for the result */
1540 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1541 mcs51_rUmaskForOp (IC_RESULT(ic)));
1543 if (options.useXstack)
1545 emitcode ("mov", "r0,%s", spname);
1546 for (i = mcs51_nRegs; i >= 0; i--)
1548 if (bitVectBitValue (rsave, i))
1550 emitcode ("dec", "r0");
1551 emitcode ("movx", "a,@r0");
1553 emitcode ("mov", "b,a");
1555 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1559 emitcode ("mov", "%s,r0", spname);
1560 if (bitVectBitValue (rsave, R0_IDX))
1561 emitcode ("mov", "r0,b");
1564 for (i = mcs51_nRegs; i >= 0; i--)
1566 if (bitVectBitValue (rsave, i))
1567 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1573 /*-----------------------------------------------------------------*/
1575 /*-----------------------------------------------------------------*/
1577 pushSide (operand * oper, int size)
1582 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1583 if (AOP_TYPE (oper) != AOP_REG &&
1584 AOP_TYPE (oper) != AOP_DIR &&
1587 emitcode ("mov", "a,%s", l);
1588 emitcode ("push", "acc");
1591 emitcode ("push", "%s", l);
1595 /*-----------------------------------------------------------------*/
1596 /* assignResultValue - */
1597 /*-----------------------------------------------------------------*/
1599 assignResultValue (operand * oper)
1602 int size = AOP_SIZE (oper);
1605 aopPut (AOP (oper), fReturn[offset], offset);
1611 /*-----------------------------------------------------------------*/
1612 /* genXpush - pushes onto the external stack */
1613 /*-----------------------------------------------------------------*/
1615 genXpush (iCode * ic)
1617 asmop *aop = newAsmop (0);
1619 int size, offset = 0;
1621 D(emitcode (";", "genXpush"));
1623 aopOp (IC_LEFT (ic), ic, FALSE);
1624 r = getFreePtr (ic, &aop, FALSE);
1627 emitcode ("mov", "%s,_spx", r->name);
1629 size = AOP_SIZE (IC_LEFT (ic));
1633 char *l = aopGet (AOP (IC_LEFT (ic)),
1634 offset++, FALSE, FALSE);
1636 emitcode ("movx", "@%s,a", r->name);
1637 emitcode ("inc", "%s", r->name);
1642 emitcode ("mov", "_spx,%s", r->name);
1644 freeAsmop (NULL, aop, ic, TRUE);
1645 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1648 /*-----------------------------------------------------------------*/
1649 /* genIpush - genrate code for pushing this gets a little complex */
1650 /*-----------------------------------------------------------------*/
1652 genIpush (iCode * ic)
1654 int size, offset = 0;
1657 D(emitcode (";", "genIpush"));
1659 /* if this is not a parm push : ie. it is spill push
1660 and spill push is always done on the local stack */
1664 /* and the item is spilt then do nothing */
1665 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1668 aopOp (IC_LEFT (ic), ic, FALSE);
1669 size = AOP_SIZE (IC_LEFT (ic));
1670 /* push it on the stack */
1673 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1679 emitcode ("push", "%s", l);
1684 /* this is a paramter push: in this case we call
1685 the routine to find the call and save those
1686 registers that need to be saved */
1689 /* if use external stack then call the external
1690 stack pushing routine */
1691 if (options.useXstack)
1697 /* then do the push */
1698 aopOp (IC_LEFT (ic), ic, FALSE);
1701 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1702 size = AOP_SIZE (IC_LEFT (ic));
1706 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1707 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1708 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1711 emitcode ("mov", "a,%s", l);
1712 emitcode ("push", "acc");
1715 emitcode ("push", "%s", l);
1718 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1721 /*-----------------------------------------------------------------*/
1722 /* genIpop - recover the registers: can happen only for spilling */
1723 /*-----------------------------------------------------------------*/
1725 genIpop (iCode * ic)
1729 D(emitcode (";", "genIpop"));
1731 /* if the temp was not pushed then */
1732 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1735 aopOp (IC_LEFT (ic), ic, FALSE);
1736 size = AOP_SIZE (IC_LEFT (ic));
1737 offset = (size - 1);
1739 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1742 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1745 /*-----------------------------------------------------------------*/
1746 /* unsaveRBank - restores the resgister bank from stack */
1747 /*-----------------------------------------------------------------*/
1749 unsaveRBank (int bank, iCode * ic, bool popPsw)
1755 if (options.useXstack)
1759 /* Assume r0 is available for use. */
1760 r = mcs51_regWithIdx (R0_IDX);;
1765 r = getFreePtr (ic, &aop, FALSE);
1767 emitcode ("mov", "%s,_spx", r->name);
1772 if (options.useXstack)
1774 emitcode ("movx", "a,@%s", r->name);
1775 emitcode ("mov", "psw,a");
1776 emitcode ("dec", "%s", r->name);
1780 emitcode ("pop", "psw");
1784 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1786 if (options.useXstack)
1788 emitcode ("movx", "a,@%s", r->name);
1789 emitcode ("mov", "(%s+%d),a",
1790 regs8051[i].base, 8 * bank + regs8051[i].offset);
1791 emitcode ("dec", "%s", r->name);
1795 emitcode ("pop", "(%s+%d)",
1796 regs8051[i].base, 8 * bank + regs8051[i].offset);
1799 if (options.useXstack)
1801 emitcode ("mov", "_spx,%s", r->name);
1806 freeAsmop (NULL, aop, ic, TRUE);
1810 /*-----------------------------------------------------------------*/
1811 /* saveRBank - saves an entire register bank on the stack */
1812 /*-----------------------------------------------------------------*/
1814 saveRBank (int bank, iCode * ic, bool pushPsw)
1820 if (options.useXstack)
1824 /* Assume r0 is available for use. */
1825 r = mcs51_regWithIdx (R0_IDX);;
1830 r = getFreePtr (ic, &aop, FALSE);
1832 emitcode ("mov", "%s,_spx", r->name);
1835 for (i = 0; i < mcs51_nRegs; i++)
1837 if (options.useXstack)
1839 emitcode ("inc", "%s", r->name);
1840 emitcode ("mov", "a,(%s+%d)",
1841 regs8051[i].base, 8 * bank + regs8051[i].offset);
1842 emitcode ("movx", "@%s,a", r->name);
1845 emitcode ("push", "(%s+%d)",
1846 regs8051[i].base, 8 * bank + regs8051[i].offset);
1851 if (options.useXstack)
1853 emitcode ("mov", "a,psw");
1854 emitcode ("movx", "@%s,a", r->name);
1855 emitcode ("inc", "%s", r->name);
1856 emitcode ("mov", "_spx,%s", r->name);
1861 emitcode ("push", "psw");
1864 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1869 freeAsmop (NULL, aop, ic, TRUE);
1878 /*-----------------------------------------------------------------*/
1879 /* genCall - generates a call statement */
1880 /*-----------------------------------------------------------------*/
1882 genCall (iCode * ic)
1885 bool restoreBank = FALSE;
1886 bool swapBanks = FALSE;
1888 D(emitcode(";", "genCall"));
1890 /* if send set is not empty the assign */
1895 for (sic = setFirstItem (_G.sendSet); sic;
1896 sic = setNextItem (_G.sendSet))
1898 int size, offset = 0;
1899 aopOp (IC_LEFT (sic), sic, FALSE);
1900 size = AOP_SIZE (IC_LEFT (sic));
1903 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1905 if (strcmp (l, fReturn[offset]))
1906 emitcode ("mov", "%s,%s",
1911 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1916 /* if we are calling a not _naked function that is not using
1917 the same register bank then we need to save the
1918 destination registers on the stack */
1919 dtype = operandType (IC_LEFT (ic));
1920 if (dtype && !IFFUNC_ISNAKED(dtype) &&
1921 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1922 IFFUNC_ISISR (currFunc->type))
1926 /* This is unexpected; the bank should have been saved in
1929 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1935 /* if caller saves & we have not saved then */
1941 emitcode ("mov", "psw,#0x%02x",
1942 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1946 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1947 OP_SYMBOL (IC_LEFT (ic))->rname :
1948 OP_SYMBOL (IC_LEFT (ic))->name));
1952 emitcode ("mov", "psw,#0x%02x",
1953 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1956 /* if we need assign a result value */
1957 if ((IS_ITEMP (IC_RESULT (ic)) &&
1958 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1959 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1960 IS_TRUE_SYMOP (IC_RESULT (ic)))
1964 aopOp (IC_RESULT (ic), ic, FALSE);
1967 assignResultValue (IC_RESULT (ic));
1969 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1972 /* adjust the stack for parameters if
1977 if (ic->parmBytes > 3)
1979 emitcode ("mov", "a,%s", spname);
1980 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1981 emitcode ("mov", "%s,a", spname);
1984 for (i = 0; i < ic->parmBytes; i++)
1985 emitcode ("dec", "%s", spname);
1988 /* if we hade saved some registers then unsave them */
1989 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1990 unsaveRegisters (ic);
1992 /* if register bank was saved then pop them */
1994 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1997 /*-----------------------------------------------------------------*/
1998 /* genPcall - generates a call by pointer statement */
1999 /*-----------------------------------------------------------------*/
2001 genPcall (iCode * ic)
2004 symbol *rlbl = newiTempLabel (NULL);
2005 bool restoreBank=FALSE;
2007 D(emitcode(";", "genPCall"));
2009 /* if caller saves & we have not saved then */
2013 /* if we are calling a function that is not using
2014 the same register bank then we need to save the
2015 destination registers on the stack */
2016 dtype = operandType (IC_LEFT (ic));
2017 if (dtype && !FUNC_ISNAKED(dtype) &&
2018 IFFUNC_ISISR (currFunc->type) &&
2019 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2020 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2024 /* push the return address on to the stack */
2025 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2026 emitcode ("push", "acc");
2027 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2028 emitcode ("push", "acc");
2030 /* now push the calling address */
2031 aopOp (IC_LEFT (ic), ic, FALSE);
2033 pushSide (IC_LEFT (ic), FPTRSIZE);
2035 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2037 /* if send set is not empty the assign */
2042 for (sic = setFirstItem (_G.sendSet); sic;
2043 sic = setNextItem (_G.sendSet))
2045 int size, offset = 0;
2046 aopOp (IC_LEFT (sic), sic, FALSE);
2047 size = AOP_SIZE (IC_LEFT (sic));
2050 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2052 if (strcmp (l, fReturn[offset]))
2053 emitcode ("mov", "%s,%s",
2058 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2063 emitcode ("ret", "");
2064 emitcode ("", "%05d$:", (rlbl->key + 100));
2067 /* if we need assign a result value */
2068 if ((IS_ITEMP (IC_RESULT (ic)) &&
2069 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2070 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2071 IS_TRUE_SYMOP (IC_RESULT (ic)))
2075 aopOp (IC_RESULT (ic), ic, FALSE);
2078 assignResultValue (IC_RESULT (ic));
2080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2083 /* adjust the stack for parameters if
2088 if (ic->parmBytes > 3)
2090 emitcode ("mov", "a,%s", spname);
2091 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2092 emitcode ("mov", "%s,a", spname);
2095 for (i = 0; i < ic->parmBytes; i++)
2096 emitcode ("dec", "%s", spname);
2100 /* if register bank was saved then unsave them */
2102 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2104 /* if we hade saved some registers then
2106 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2107 unsaveRegisters (ic);
2110 /*-----------------------------------------------------------------*/
2111 /* resultRemat - result is rematerializable */
2112 /*-----------------------------------------------------------------*/
2114 resultRemat (iCode * ic)
2116 if (SKIP_IC (ic) || ic->op == IFX)
2119 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2121 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2122 if (sym->remat && !POINTER_SET (ic))
2129 #if defined(__BORLANDC__) || defined(_MSC_VER)
2130 #define STRCASECMP stricmp
2132 #define STRCASECMP strcasecmp
2135 /*-----------------------------------------------------------------*/
2136 /* inExcludeList - return 1 if the string is in exclude Reg list */
2137 /*-----------------------------------------------------------------*/
2139 inExcludeList (char *s)
2143 if (options.excludeRegs[i] &&
2144 STRCASECMP (options.excludeRegs[i], "none") == 0)
2147 for (i = 0; options.excludeRegs[i]; i++)
2149 if (options.excludeRegs[i] &&
2150 STRCASECMP (s, options.excludeRegs[i]) == 0)
2156 /*-----------------------------------------------------------------*/
2157 /* genFunction - generated code for function entry */
2158 /*-----------------------------------------------------------------*/
2160 genFunction (iCode * ic)
2164 bool switchedPSW = FALSE;
2167 /* create the function header */
2168 emitcode (";", "-----------------------------------------");
2169 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2170 emitcode (";", "-----------------------------------------");
2172 emitcode ("", "%s:", sym->rname);
2173 ftype = operandType (IC_LEFT (ic));
2175 if (IFFUNC_ISNAKED(ftype))
2177 emitcode(";", "naked function: no prologue.");
2181 /* if critical function then turn interrupts off */
2182 if (IFFUNC_ISCRITICAL (ftype))
2183 emitcode ("clr", "ea");
2185 /* here we need to generate the equates for the
2186 register bank if required */
2187 if (FUNC_REGBANK (ftype) != rbank)
2191 rbank = FUNC_REGBANK (ftype);
2192 for (i = 0; i < mcs51_nRegs; i++)
2194 if (strcmp (regs8051[i].base, "0") == 0)
2195 emitcode ("", "%s = 0x%02x",
2197 8 * rbank + regs8051[i].offset);
2199 emitcode ("", "%s = %s + 0x%02x",
2202 8 * rbank + regs8051[i].offset);
2206 /* if this is an interrupt service routine then
2207 save acc, b, dpl, dph */
2208 if (IFFUNC_ISISR (sym->type))
2211 if (!inExcludeList ("acc"))
2212 emitcode ("push", "acc");
2213 if (!inExcludeList ("b"))
2214 emitcode ("push", "b");
2215 if (!inExcludeList ("dpl"))
2216 emitcode ("push", "dpl");
2217 if (!inExcludeList ("dph"))
2218 emitcode ("push", "dph");
2219 /* if this isr has no bank i.e. is going to
2220 run with bank 0 , then we need to save more
2222 if (!FUNC_REGBANK (sym->type))
2225 /* if this function does not call any other
2226 function then we can be economical and
2227 save only those registers that are used */
2228 if (!IFFUNC_HASFCALL(sym->type))
2232 /* if any registers used */
2235 /* save the registers used */
2236 for (i = 0; i < sym->regsUsed->size; i++)
2238 if (bitVectBitValue (sym->regsUsed, i) ||
2239 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2240 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2247 /* this function has a function call cannot
2248 determines register usage so we will have to push the
2250 saveRBank (0, ic, FALSE);
2255 /* This ISR uses a non-zero bank.
2257 * We assume that the bank is available for our
2260 * However, if this ISR calls a function which uses some
2261 * other bank, we must save that bank entirely.
2263 unsigned long banksToSave = 0;
2265 if (IFFUNC_HASFCALL(sym->type))
2268 #define MAX_REGISTER_BANKS 4
2273 for (i = ic; i; i = i->next)
2275 if (i->op == ENDFUNCTION)
2277 /* we got to the end OK. */
2285 dtype = operandType (IC_LEFT(i));
2287 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2289 /* Mark this bank for saving. */
2290 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2292 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2296 banksToSave |= (1 << FUNC_REGBANK(dtype));
2299 /* And note that we don't need to do it in
2307 /* This is a mess; we have no idea what
2308 * register bank the called function might
2311 * The only thing I can think of to do is
2312 * throw a warning and hope.
2314 werror(W_FUNCPTR_IN_USING_ISR);
2318 if (banksToSave && options.useXstack)
2320 /* Since we aren't passing it an ic,
2321 * saveRBank will assume r0 is available to abuse.
2323 * So switch to our (trashable) bank now, so
2324 * the caller's R0 isn't trashed.
2326 emitcode ("push", "psw");
2327 emitcode ("mov", "psw,#0x%02x",
2328 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2332 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2334 if (banksToSave & (1 << ix))
2336 saveRBank(ix, NULL, FALSE);
2340 // jwk: this needs a closer look
2341 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2346 /* if callee-save to be used for this function
2347 then save the registers being used in this function */
2348 if (IFFUNC_CALLEESAVES(sym->type))
2352 /* if any registers used */
2355 /* save the registers used */
2356 for (i = 0; i < sym->regsUsed->size; i++)
2358 if (bitVectBitValue (sym->regsUsed, i) ||
2359 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2361 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2369 /* set the register bank to the desired value */
2370 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2373 emitcode ("push", "psw");
2374 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2377 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2380 if (options.useXstack)
2382 emitcode ("mov", "r0,%s", spname);
2383 emitcode ("mov", "a,_bp");
2384 emitcode ("movx", "@r0,a");
2385 emitcode ("inc", "%s", spname);
2389 /* set up the stack */
2390 emitcode ("push", "_bp"); /* save the callers stack */
2392 emitcode ("mov", "_bp,%s", spname);
2395 /* adjust the stack for the function */
2401 werror (W_STACK_OVERFLOW, sym->name);
2403 if (i > 3 && sym->recvSize < 4)
2406 emitcode ("mov", "a,sp");
2407 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2408 emitcode ("mov", "sp,a");
2413 emitcode ("inc", "sp");
2419 emitcode ("mov", "a,_spx");
2420 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2421 emitcode ("mov", "_spx,a");
2426 /*-----------------------------------------------------------------*/
2427 /* genEndFunction - generates epilogue for functions */
2428 /*-----------------------------------------------------------------*/
2430 genEndFunction (iCode * ic)
2432 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2434 if (IFFUNC_ISNAKED(sym->type))
2436 emitcode(";", "naked function: no epilogue.");
2440 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2442 emitcode ("mov", "%s,_bp", spname);
2445 /* if use external stack but some variables were
2446 added to the local stack then decrement the
2448 if (options.useXstack && sym->stack)
2450 emitcode ("mov", "a,sp");
2451 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2452 emitcode ("mov", "sp,a");
2456 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2458 if (options.useXstack)
2460 emitcode ("mov", "r0,%s", spname);
2461 emitcode ("movx", "a,@r0");
2462 emitcode ("mov", "_bp,a");
2463 emitcode ("dec", "%s", spname);
2467 emitcode ("pop", "_bp");
2471 /* restore the register bank */
2472 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2474 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2475 || !options.useXstack)
2477 /* Special case of ISR using non-zero bank with useXstack
2480 emitcode ("pop", "psw");
2484 if (IFFUNC_ISISR (sym->type))
2487 /* now we need to restore the registers */
2488 /* if this isr has no bank i.e. is going to
2489 run with bank 0 , then we need to save more
2491 if (!FUNC_REGBANK (sym->type))
2493 /* if this function does not call any other
2494 function then we can be economical and
2495 save only those registers that are used */
2496 if (!IFFUNC_HASFCALL(sym->type))
2500 /* if any registers used */
2503 /* save the registers used */
2504 for (i = sym->regsUsed->size; i >= 0; i--)
2506 if (bitVectBitValue (sym->regsUsed, i) ||
2507 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2508 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2515 /* this function has a function call cannot
2516 determines register usage so we will have to pop the
2518 unsaveRBank (0, ic, FALSE);
2523 /* This ISR uses a non-zero bank.
2525 * Restore any register banks saved by genFunction
2528 // jwk: this needs a closer look
2529 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2532 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2534 if (savedBanks & (1 << ix))
2536 unsaveRBank(ix, NULL, FALSE);
2540 if (options.useXstack)
2542 /* Restore bank AFTER calling unsaveRBank,
2543 * since it can trash r0.
2545 emitcode ("pop", "psw");
2549 if (!inExcludeList ("dph"))
2550 emitcode ("pop", "dph");
2551 if (!inExcludeList ("dpl"))
2552 emitcode ("pop", "dpl");
2553 if (!inExcludeList ("b"))
2554 emitcode ("pop", "b");
2555 if (!inExcludeList ("acc"))
2556 emitcode ("pop", "acc");
2558 if (IFFUNC_ISCRITICAL (sym->type))
2559 emitcode ("setb", "ea");
2561 /* if debug then send end of function */
2562 /* if (options.debug && currFunc) */
2563 if (options.debug && currFunc)
2566 emitcode ("", "C$%s$%d$%d$%d ==.",
2567 FileBaseName (ic->filename), currFunc->lastLine,
2568 ic->level, ic->block);
2569 if (IS_STATIC (currFunc->etype))
2570 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2572 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2576 emitcode ("reti", "");
2580 if (IFFUNC_ISCRITICAL (sym->type))
2581 emitcode ("setb", "ea");
2583 if (IFFUNC_CALLEESAVES(sym->type))
2587 /* if any registers used */
2590 /* save the registers used */
2591 for (i = sym->regsUsed->size; i >= 0; i--)
2593 if (bitVectBitValue (sym->regsUsed, i) ||
2594 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2595 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2601 /* if debug then send end of function */
2602 if (options.debug && currFunc)
2605 emitcode ("", "C$%s$%d$%d$%d ==.",
2606 FileBaseName (ic->filename), currFunc->lastLine,
2607 ic->level, ic->block);
2608 if (IS_STATIC (currFunc->etype))
2609 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2611 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2615 emitcode ("ret", "");
2620 /*-----------------------------------------------------------------*/
2621 /* genRet - generate code for return statement */
2622 /*-----------------------------------------------------------------*/
2626 int size, offset = 0, pushed = 0;
2628 /* if we have no return value then
2629 just generate the "ret" */
2633 /* we have something to return then
2634 move the return value into place */
2635 aopOp (IC_LEFT (ic), ic, FALSE);
2636 size = AOP_SIZE (IC_LEFT (ic));
2641 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2644 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2646 emitcode ("push", "%s", l);
2651 l = aopGet (AOP (IC_LEFT (ic)), offset,
2653 if (strcmp (fReturn[offset], l))
2654 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2663 if (strcmp (fReturn[pushed], "a"))
2664 emitcode ("pop", fReturn[pushed]);
2666 emitcode ("pop", "acc");
2669 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2672 /* generate a jump to the return label
2673 if the next is not the return statement */
2674 if (!(ic->next && ic->next->op == LABEL &&
2675 IC_LABEL (ic->next) == returnLabel))
2677 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2681 /*-----------------------------------------------------------------*/
2682 /* genLabel - generates a label */
2683 /*-----------------------------------------------------------------*/
2685 genLabel (iCode * ic)
2687 /* special case never generate */
2688 if (IC_LABEL (ic) == entryLabel)
2691 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2694 /*-----------------------------------------------------------------*/
2695 /* genGoto - generates a ljmp */
2696 /*-----------------------------------------------------------------*/
2698 genGoto (iCode * ic)
2700 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2703 /*-----------------------------------------------------------------*/
2704 /* findLabelBackwards: walks back through the iCode chain looking */
2705 /* for the given label. Returns number of iCode instructions */
2706 /* between that label and given ic. */
2707 /* Returns zero if label not found. */
2708 /*-----------------------------------------------------------------*/
2710 findLabelBackwards (iCode * ic, int key)
2719 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2721 /* printf("findLabelBackwards = %d\n", count); */
2729 /*-----------------------------------------------------------------*/
2730 /* genPlusIncr :- does addition with increment if possible */
2731 /*-----------------------------------------------------------------*/
2733 genPlusIncr (iCode * ic)
2735 unsigned int icount;
2736 unsigned int size = getDataSize (IC_RESULT (ic));
2738 /* will try to generate an increment */
2739 /* if the right side is not a literal
2741 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2744 /* if the literal value of the right hand side
2745 is greater than 4 then it is not worth it */
2746 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2749 D(emitcode (";", "genPlusIncr"));
2751 /* if increment 16 bits in register */
2752 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2760 /* If the next instruction is a goto and the goto target
2761 * is < 10 instructions previous to this, we can generate
2762 * jumps straight to that target.
2764 if (ic->next && ic->next->op == GOTO
2765 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2766 && labelRange <= 10)
2768 emitcode (";", "tail increment optimized");
2769 tlbl = IC_LABEL (ic->next);
2774 tlbl = newiTempLabel (NULL);
2777 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2778 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2779 IS_AOP_PREG (IC_RESULT (ic)))
2780 emitcode ("cjne", "%s,#0x00,%05d$"
2781 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2785 emitcode ("clr", "a");
2786 emitcode ("cjne", "a,%s,%05d$"
2787 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2791 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2794 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2795 IS_AOP_PREG (IC_RESULT (ic)))
2796 emitcode ("cjne", "%s,#0x00,%05d$"
2797 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2800 emitcode ("cjne", "a,%s,%05d$"
2801 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2804 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2808 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2809 IS_AOP_PREG (IC_RESULT (ic)))
2810 emitcode ("cjne", "%s,#0x00,%05d$"
2811 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2815 emitcode ("cjne", "a,%s,%05d$"
2816 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2819 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2824 emitcode ("", "%05d$:", tlbl->key + 100);
2829 /* if the sizes are greater than 1 then we cannot */
2830 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2831 AOP_SIZE (IC_LEFT (ic)) > 1)
2834 /* we can if the aops of the left & result match or
2835 if they are in registers and the registers are the
2837 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2842 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2843 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2844 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2850 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2859 /*-----------------------------------------------------------------*/
2860 /* outBitAcc - output a bit in acc */
2861 /*-----------------------------------------------------------------*/
2863 outBitAcc (operand * result)
2865 symbol *tlbl = newiTempLabel (NULL);
2866 /* if the result is a bit */
2867 if (AOP_TYPE (result) == AOP_CRY)
2869 aopPut (AOP (result), "a", 0);
2873 emitcode ("jz", "%05d$", tlbl->key + 100);
2874 emitcode ("mov", "a,%s", one);
2875 emitcode ("", "%05d$:", tlbl->key + 100);
2880 /*-----------------------------------------------------------------*/
2881 /* genPlusBits - generates code for addition of two bits */
2882 /*-----------------------------------------------------------------*/
2884 genPlusBits (iCode * ic)
2886 D(emitcode (";", "genPlusBits"));
2888 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2890 symbol *lbl = newiTempLabel (NULL);
2891 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2892 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2893 emitcode ("cpl", "c");
2894 emitcode ("", "%05d$:", (lbl->key + 100));
2895 outBitC (IC_RESULT (ic));
2899 emitcode ("clr", "a");
2900 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2901 emitcode ("rlc", "a");
2902 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2903 emitcode ("addc", "a,#0x00");
2904 outAcc (IC_RESULT (ic));
2909 /* This is the original version of this code.
2911 * This is being kept around for reference,
2912 * because I am not entirely sure I got it right...
2915 adjustArithmeticResult (iCode * ic)
2917 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2918 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2919 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2920 aopPut (AOP (IC_RESULT (ic)),
2921 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2924 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2925 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2926 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2927 aopPut (AOP (IC_RESULT (ic)),
2928 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2931 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2932 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2933 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2934 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2935 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2938 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2939 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2943 /* This is the pure and virtuous version of this code.
2944 * I'm pretty certain it's right, but not enough to toss the old
2948 adjustArithmeticResult (iCode * ic)
2950 if (opIsGptr (IC_RESULT (ic)) &&
2951 opIsGptr (IC_LEFT (ic)) &&
2952 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2954 aopPut (AOP (IC_RESULT (ic)),
2955 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2959 if (opIsGptr (IC_RESULT (ic)) &&
2960 opIsGptr (IC_RIGHT (ic)) &&
2961 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2963 aopPut (AOP (IC_RESULT (ic)),
2964 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2968 if (opIsGptr (IC_RESULT (ic)) &&
2969 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2970 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2971 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2972 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2975 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2976 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2981 /*-----------------------------------------------------------------*/
2982 /* genPlus - generates code for addition */
2983 /*-----------------------------------------------------------------*/
2985 genPlus (iCode * ic)
2987 int size, offset = 0;
2989 /* special cases :- */
2991 D(emitcode (";", "genPlus"));
2993 aopOp (IC_LEFT (ic), ic, FALSE);
2994 aopOp (IC_RIGHT (ic), ic, FALSE);
2995 aopOp (IC_RESULT (ic), ic, TRUE);
2997 /* if literal, literal on the right or
2998 if left requires ACC or right is already
3000 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3001 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3002 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3004 operand *t = IC_RIGHT (ic);
3005 IC_RIGHT (ic) = IC_LEFT (ic);
3009 /* if both left & right are in bit
3011 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3012 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3018 /* if left in bit space & right literal */
3019 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3020 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3022 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3023 /* if result in bit space */
3024 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3026 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3027 emitcode ("cpl", "c");
3028 outBitC (IC_RESULT (ic));
3032 size = getDataSize (IC_RESULT (ic));
3035 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3036 emitcode ("addc", "a,#00");
3037 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3043 /* if I can do an increment instead
3044 of add then GOOD for ME */
3045 if (genPlusIncr (ic) == TRUE)
3048 size = getDataSize (IC_RESULT (ic));
3052 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3054 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3056 emitcode ("add", "a,%s",
3057 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3059 emitcode ("addc", "a,%s",
3060 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3064 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3066 emitcode ("add", "a,%s",
3067 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3069 emitcode ("addc", "a,%s",
3070 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3072 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3075 adjustArithmeticResult (ic);
3078 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3079 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3083 /*-----------------------------------------------------------------*/
3084 /* genMinusDec :- does subtraction with deccrement if possible */
3085 /*-----------------------------------------------------------------*/
3087 genMinusDec (iCode * ic)
3089 unsigned int icount;
3090 unsigned int size = getDataSize (IC_RESULT (ic));
3092 /* will try to generate an increment */
3093 /* if the right side is not a literal
3095 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3098 /* if the literal value of the right hand side
3099 is greater than 4 then it is not worth it */
3100 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3103 D(emitcode (";", "genMinusDec"));
3105 /* if decrement 16 bits in register */
3106 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3114 /* If the next instruction is a goto and the goto target
3115 * is <= 10 instructions previous to this, we can generate
3116 * jumps straight to that target.
3118 if (ic->next && ic->next->op == GOTO
3119 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3120 && labelRange <= 10)
3122 emitcode (";", "tail decrement optimized");
3123 tlbl = IC_LABEL (ic->next);
3128 tlbl = newiTempLabel (NULL);
3132 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3133 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3134 IS_AOP_PREG (IC_RESULT (ic)))
3135 emitcode ("cjne", "%s,#0xff,%05d$"
3136 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3140 emitcode ("mov", "a,#0xff");
3141 emitcode ("cjne", "a,%s,%05d$"
3142 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3145 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3148 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3149 IS_AOP_PREG (IC_RESULT (ic)))
3150 emitcode ("cjne", "%s,#0xff,%05d$"
3151 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3155 emitcode ("cjne", "a,%s,%05d$"
3156 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3159 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3163 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3164 IS_AOP_PREG (IC_RESULT (ic)))
3165 emitcode ("cjne", "%s,#0xff,%05d$"
3166 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3170 emitcode ("cjne", "a,%s,%05d$"
3171 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3174 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3178 emitcode ("", "%05d$:", tlbl->key + 100);
3183 /* if the sizes are greater than 1 then we cannot */
3184 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3185 AOP_SIZE (IC_LEFT (ic)) > 1)
3188 /* we can if the aops of the left & result match or
3189 if they are in registers and the registers are the
3191 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3195 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3203 /*-----------------------------------------------------------------*/
3204 /* addSign - complete with sign */
3205 /*-----------------------------------------------------------------*/
3207 addSign (operand * result, int offset, int sign)
3209 int size = (getDataSize (result) - offset);
3214 emitcode ("rlc", "a");
3215 emitcode ("subb", "a,acc");
3217 aopPut (AOP (result), "a", offset++);
3221 aopPut (AOP (result), zero, offset++);
3225 /*-----------------------------------------------------------------*/
3226 /* genMinusBits - generates code for subtraction of two bits */
3227 /*-----------------------------------------------------------------*/
3229 genMinusBits (iCode * ic)
3231 symbol *lbl = newiTempLabel (NULL);
3233 D(emitcode (";", "genMinusBits"));
3235 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3237 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3238 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3239 emitcode ("cpl", "c");
3240 emitcode ("", "%05d$:", (lbl->key + 100));
3241 outBitC (IC_RESULT (ic));
3245 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3246 emitcode ("subb", "a,acc");
3247 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3248 emitcode ("inc", "a");
3249 emitcode ("", "%05d$:", (lbl->key + 100));
3250 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3251 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3255 /*-----------------------------------------------------------------*/
3256 /* genMinus - generates code for subtraction */
3257 /*-----------------------------------------------------------------*/
3259 genMinus (iCode * ic)
3261 int size, offset = 0;
3262 unsigned long lit = 0L;
3264 D(emitcode (";", "genMinus"));
3266 aopOp (IC_LEFT (ic), ic, FALSE);
3267 aopOp (IC_RIGHT (ic), ic, FALSE);
3268 aopOp (IC_RESULT (ic), ic, TRUE);
3270 /* special cases :- */
3271 /* if both left & right are in bit space */
3272 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3273 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3279 /* if I can do an decrement instead
3280 of subtract then GOOD for ME */
3281 if (genMinusDec (ic) == TRUE)
3284 size = getDataSize (IC_RESULT (ic));
3286 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3292 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3296 /* if literal, add a,#-lit, else normal subb */
3299 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3300 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3301 emitcode ("subb", "a,%s",
3302 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3305 /* first add without previous c */
3307 if (!size && lit==-1) {
3308 emitcode ("dec", "a");
3310 emitcode ("add", "a,#0x%02x",
3311 (unsigned int) (lit & 0x0FFL));
3314 emitcode ("addc", "a,#0x%02x",
3315 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3318 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3321 adjustArithmeticResult (ic);
3324 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3325 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3326 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3330 /*-----------------------------------------------------------------*/
3331 /* genMultbits :- multiplication of bits */
3332 /*-----------------------------------------------------------------*/
3334 genMultbits (operand * left,
3338 D(emitcode (";", "genMultbits"));
3340 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3341 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3346 /*-----------------------------------------------------------------*/
3347 /* genMultOneByte : 8*8=8/16 bit multiplication */
3348 /*-----------------------------------------------------------------*/
3350 genMultOneByte (operand * left,
3354 sym_link *opetype = operandType (result);
3356 int size=AOP_SIZE(result);
3358 D(emitcode (";", "genMultOneByte"));
3360 if (size<1 || size>2) {
3361 // this should never happen
3362 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3363 AOP_SIZE(result), __FILE__, lineno);
3367 /* (if two literals: the value is computed before) */
3368 /* if one literal, literal on the right */
3369 if (AOP_TYPE (left) == AOP_LIT)
3374 //emitcode (";", "swapped left and right");
3377 if (SPEC_USIGN(opetype)
3378 // ignore the sign of left and right, what else can we do?
3379 || (SPEC_USIGN(operandType(left)) &&
3380 SPEC_USIGN(operandType(right)))) {
3381 // just an unsigned 8*8=8/16 multiply
3382 //emitcode (";","unsigned");
3383 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3384 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3385 emitcode ("mul", "ab");
3386 aopPut (AOP (result), "a", 0);
3388 aopPut (AOP (result), "b", 1);
3393 // we have to do a signed multiply
3395 //emitcode (";", "signed");
3396 emitcode ("clr", "F0"); // reset sign flag
3397 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3399 lbl=newiTempLabel(NULL);
3400 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3401 // left side is negative, 8-bit two's complement, this fails for -128
3402 emitcode ("setb", "F0"); // set sign flag
3403 emitcode ("cpl", "a");
3404 emitcode ("inc", "a");
3406 emitcode ("", "%05d$:", lbl->key+100);
3409 if (AOP_TYPE(right)==AOP_LIT) {
3410 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3411 /* AND literal negative */
3413 emitcode ("cpl", "F0"); // complement sign flag
3414 emitcode ("mov", "b,#0x%02x", -val);
3416 emitcode ("mov", "b,#0x%02x", val);
3419 lbl=newiTempLabel(NULL);
3420 emitcode ("mov", "b,a");
3421 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3422 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3423 // right side is negative, 8-bit two's complement
3424 emitcode ("cpl", "F0"); // complement sign flag
3425 emitcode ("cpl", "a");
3426 emitcode ("inc", "a");
3427 emitcode ("", "%05d$:", lbl->key+100);
3429 emitcode ("mul", "ab");
3431 lbl=newiTempLabel(NULL);
3432 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3433 // only ONE op was negative, we have to do a 8/16-bit two's complement
3434 emitcode ("cpl", "a"); // lsb
3436 emitcode ("inc", "a");
3438 emitcode ("add", "a,#1");
3439 emitcode ("xch", "a,b");
3440 emitcode ("cpl", "a"); // msb
3441 emitcode ("addc", "a,#0");
3442 emitcode ("xch", "a,b");
3445 emitcode ("", "%05d$:", lbl->key+100);
3446 aopPut (AOP (result), "a", 0);
3448 aopPut (AOP (result), "b", 1);
3452 /*-----------------------------------------------------------------*/
3453 /* genMult - generates code for multiplication */
3454 /*-----------------------------------------------------------------*/
3456 genMult (iCode * ic)
3458 operand *left = IC_LEFT (ic);
3459 operand *right = IC_RIGHT (ic);
3460 operand *result = IC_RESULT (ic);
3462 D(emitcode (";", "genMult"));
3464 /* assign the amsops */
3465 aopOp (left, ic, FALSE);
3466 aopOp (right, ic, FALSE);
3467 aopOp (result, ic, TRUE);
3469 /* special cases first */
3471 if (AOP_TYPE (left) == AOP_CRY &&
3472 AOP_TYPE (right) == AOP_CRY)
3474 genMultbits (left, right, result);
3478 /* if both are of size == 1 */
3479 #if 0 // one of them can be a sloc shared with the result
3480 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3482 if (getSize(operandType(left)) == 1 &&
3483 getSize(operandType(right)) == 1)
3486 genMultOneByte (left, right, result);
3490 /* should have been converted to function call */
3491 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3492 getSize(OP_SYMBOL(right)->type));
3496 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3497 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3498 freeAsmop (result, NULL, ic, TRUE);
3501 /*-----------------------------------------------------------------*/
3502 /* genDivbits :- division of bits */
3503 /*-----------------------------------------------------------------*/
3505 genDivbits (operand * left,
3512 D(emitcode (";", "genDivbits"));
3514 /* the result must be bit */
3515 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3516 l = aopGet (AOP (left), 0, FALSE, FALSE);
3520 emitcode ("div", "ab");
3521 emitcode ("rrc", "a");
3522 aopPut (AOP (result), "c", 0);
3525 /*-----------------------------------------------------------------*/
3526 /* genDivOneByte : 8 bit division */
3527 /*-----------------------------------------------------------------*/
3529 genDivOneByte (operand * left,
3533 sym_link *opetype = operandType (result);
3538 D(emitcode (";", "genDivOneByte"));
3540 size = AOP_SIZE (result) - 1;
3542 /* signed or unsigned */
3543 if (SPEC_USIGN (opetype))
3545 /* unsigned is easy */
3546 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3547 l = aopGet (AOP (left), 0, FALSE, FALSE);
3549 emitcode ("div", "ab");
3550 aopPut (AOP (result), "a", 0);
3552 aopPut (AOP (result), zero, offset++);
3556 /* signed is a little bit more difficult */
3558 /* save the signs of the operands */
3559 l = aopGet (AOP (left), 0, FALSE, FALSE);
3561 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3562 emitcode ("push", "acc"); /* save it on the stack */
3564 /* now sign adjust for both left & right */
3565 l = aopGet (AOP (right), 0, FALSE, FALSE);
3567 lbl = newiTempLabel (NULL);
3568 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3569 emitcode ("cpl", "a");
3570 emitcode ("inc", "a");
3571 emitcode ("", "%05d$:", (lbl->key + 100));
3572 emitcode ("mov", "b,a");
3574 /* sign adjust left side */
3575 l = aopGet (AOP (left), 0, FALSE, FALSE);
3578 lbl = newiTempLabel (NULL);
3579 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3580 emitcode ("cpl", "a");
3581 emitcode ("inc", "a");
3582 emitcode ("", "%05d$:", (lbl->key + 100));
3584 /* now the division */
3585 emitcode ("div", "ab");
3586 /* we are interested in the lower order
3588 emitcode ("mov", "b,a");
3589 lbl = newiTempLabel (NULL);
3590 emitcode ("pop", "acc");
3591 /* if there was an over flow we don't
3592 adjust the sign of the result */
3593 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3594 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3596 emitcode ("clr", "a");
3597 emitcode ("subb", "a,b");
3598 emitcode ("mov", "b,a");
3599 emitcode ("", "%05d$:", (lbl->key + 100));
3601 /* now we are done */
3602 aopPut (AOP (result), "b", 0);
3605 emitcode ("mov", "c,b.7");
3606 emitcode ("subb", "a,acc");
3609 aopPut (AOP (result), "a", offset++);
3613 /*-----------------------------------------------------------------*/
3614 /* genDiv - generates code for division */
3615 /*-----------------------------------------------------------------*/
3619 operand *left = IC_LEFT (ic);
3620 operand *right = IC_RIGHT (ic);
3621 operand *result = IC_RESULT (ic);
3623 D(emitcode (";", "genDiv"));
3625 /* assign the amsops */
3626 aopOp (left, ic, FALSE);
3627 aopOp (right, ic, FALSE);
3628 aopOp (result, ic, TRUE);
3630 /* special cases first */
3632 if (AOP_TYPE (left) == AOP_CRY &&
3633 AOP_TYPE (right) == AOP_CRY)
3635 genDivbits (left, right, result);
3639 /* if both are of size == 1 */
3640 if (AOP_SIZE (left) == 1 &&
3641 AOP_SIZE (right) == 1)
3643 genDivOneByte (left, right, result);
3647 /* should have been converted to function call */
3650 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3652 freeAsmop (result, NULL, ic, TRUE);
3655 /*-----------------------------------------------------------------*/
3656 /* genModbits :- modulus of bits */
3657 /*-----------------------------------------------------------------*/
3659 genModbits (operand * left,
3666 D(emitcode (";", "genModbits"));
3668 /* the result must be bit */
3669 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3670 l = aopGet (AOP (left), 0, FALSE, FALSE);
3674 emitcode ("div", "ab");
3675 emitcode ("mov", "a,b");
3676 emitcode ("rrc", "a");
3677 aopPut (AOP (result), "c", 0);
3680 /*-----------------------------------------------------------------*/
3681 /* genModOneByte : 8 bit modulus */
3682 /*-----------------------------------------------------------------*/
3684 genModOneByte (operand * left,
3688 sym_link *opetype = operandType (result);
3692 D(emitcode (";", "genModOneByte"));
3694 /* signed or unsigned */
3695 if (SPEC_USIGN (opetype))
3697 /* unsigned is easy */
3698 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3699 l = aopGet (AOP (left), 0, FALSE, FALSE);
3701 emitcode ("div", "ab");
3702 aopPut (AOP (result), "b", 0);
3706 /* signed is a little bit more difficult */
3708 /* save the signs of the operands */
3709 l = aopGet (AOP (left), 0, FALSE, FALSE);
3712 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3713 emitcode ("push", "acc"); /* save it on the stack */
3715 /* now sign adjust for both left & right */
3716 l = aopGet (AOP (right), 0, FALSE, FALSE);
3719 lbl = newiTempLabel (NULL);
3720 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3721 emitcode ("cpl", "a");
3722 emitcode ("inc", "a");
3723 emitcode ("", "%05d$:", (lbl->key + 100));
3724 emitcode ("mov", "b,a");
3726 /* sign adjust left side */
3727 l = aopGet (AOP (left), 0, FALSE, FALSE);
3730 lbl = newiTempLabel (NULL);
3731 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3732 emitcode ("cpl", "a");
3733 emitcode ("inc", "a");
3734 emitcode ("", "%05d$:", (lbl->key + 100));
3736 /* now the multiplication */
3737 emitcode ("div", "ab");
3738 /* we are interested in the lower order
3740 lbl = newiTempLabel (NULL);
3741 emitcode ("pop", "acc");
3742 /* if there was an over flow we don't
3743 adjust the sign of the result */
3744 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3745 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3747 emitcode ("clr", "a");
3748 emitcode ("subb", "a,b");
3749 emitcode ("mov", "b,a");
3750 emitcode ("", "%05d$:", (lbl->key + 100));
3752 /* now we are done */
3753 aopPut (AOP (result), "b", 0);
3757 /*-----------------------------------------------------------------*/
3758 /* genMod - generates code for division */
3759 /*-----------------------------------------------------------------*/
3763 operand *left = IC_LEFT (ic);
3764 operand *right = IC_RIGHT (ic);
3765 operand *result = IC_RESULT (ic);
3767 D(emitcode (";", "genMod"));
3769 /* assign the amsops */
3770 aopOp (left, ic, FALSE);
3771 aopOp (right, ic, FALSE);
3772 aopOp (result, ic, TRUE);
3774 /* special cases first */
3776 if (AOP_TYPE (left) == AOP_CRY &&
3777 AOP_TYPE (right) == AOP_CRY)
3779 genModbits (left, right, result);
3783 /* if both are of size == 1 */
3784 if (AOP_SIZE (left) == 1 &&
3785 AOP_SIZE (right) == 1)
3787 genModOneByte (left, right, result);
3791 /* should have been converted to function call */
3795 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3796 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3797 freeAsmop (result, NULL, ic, TRUE);
3800 /*-----------------------------------------------------------------*/
3801 /* genIfxJump :- will create a jump depending on the ifx */
3802 /*-----------------------------------------------------------------*/
3804 genIfxJump (iCode * ic, char *jval)
3807 symbol *tlbl = newiTempLabel (NULL);
3810 D(emitcode (";", "genIfxJump"));
3812 /* if true label then we jump if condition
3816 jlbl = IC_TRUE (ic);
3817 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3818 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3822 /* false label is present */
3823 jlbl = IC_FALSE (ic);
3824 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3825 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3827 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3828 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3830 emitcode (inst, "%05d$", tlbl->key + 100);
3831 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3832 emitcode ("", "%05d$:", tlbl->key + 100);
3834 /* mark the icode as generated */
3838 /*-----------------------------------------------------------------*/
3839 /* genCmp :- greater or less than comparison */
3840 /*-----------------------------------------------------------------*/
3842 genCmp (operand * left, operand * right,
3843 operand * result, iCode * ifx, int sign, iCode *ic)
3845 int size, offset = 0;
3846 unsigned long lit = 0L;
3848 D(emitcode (";", "genCmp"));
3850 /* if left & right are bit variables */
3851 if (AOP_TYPE (left) == AOP_CRY &&
3852 AOP_TYPE (right) == AOP_CRY)
3854 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3855 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3859 /* subtract right from left if at the
3860 end the carry flag is set then we know that
3861 left is greater than right */
3862 size = max (AOP_SIZE (left), AOP_SIZE (right));
3864 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3865 if ((size == 1) && !sign &&
3866 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3868 symbol *lbl = newiTempLabel (NULL);
3869 emitcode ("cjne", "%s,%s,%05d$",
3870 aopGet (AOP (left), offset, FALSE, FALSE),
3871 aopGet (AOP (right), offset, FALSE, FALSE),
3873 emitcode ("", "%05d$:", lbl->key + 100);
3877 if (AOP_TYPE (right) == AOP_LIT)
3879 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3880 /* optimize if(x < 0) or if(x >= 0) */
3889 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3890 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3892 genIfxJump (ifx, "acc.7");
3896 emitcode ("rlc", "a");
3904 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3905 if (sign && size == 0)
3907 emitcode ("xrl", "a,#0x80");
3908 if (AOP_TYPE (right) == AOP_LIT)
3910 unsigned long lit = (unsigned long)
3911 floatFromVal (AOP (right)->aopu.aop_lit);
3912 emitcode ("subb", "a,#0x%02x",
3913 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3917 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3918 emitcode ("xrl", "b,#0x80");
3919 emitcode ("subb", "a,b");
3923 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3929 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3930 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3931 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3937 /* if the result is used in the next
3938 ifx conditional branch then generate
3939 code a little differently */
3941 genIfxJump (ifx, "c");
3944 /* leave the result in acc */
3948 /*-----------------------------------------------------------------*/
3949 /* genCmpGt :- greater than comparison */
3950 /*-----------------------------------------------------------------*/
3952 genCmpGt (iCode * ic, iCode * ifx)
3954 operand *left, *right, *result;
3955 sym_link *letype, *retype;
3958 D(emitcode (";", "genCmpGt"));
3960 left = IC_LEFT (ic);
3961 right = IC_RIGHT (ic);
3962 result = IC_RESULT (ic);
3964 letype = getSpec (operandType (left));
3965 retype = getSpec (operandType (right));
3966 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3967 /* assign the amsops */
3968 aopOp (left, ic, FALSE);
3969 aopOp (right, ic, FALSE);
3970 aopOp (result, ic, TRUE);
3972 genCmp (right, left, result, ifx, sign,ic);
3974 freeAsmop (result, NULL, ic, TRUE);
3977 /*-----------------------------------------------------------------*/
3978 /* genCmpLt - less than comparisons */
3979 /*-----------------------------------------------------------------*/
3981 genCmpLt (iCode * ic, iCode * ifx)
3983 operand *left, *right, *result;
3984 sym_link *letype, *retype;
3987 D(emitcode (";", "genCmpLt"));
3989 left = IC_LEFT (ic);
3990 right = IC_RIGHT (ic);
3991 result = IC_RESULT (ic);
3993 letype = getSpec (operandType (left));
3994 retype = getSpec (operandType (right));
3995 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3997 /* assign the amsops */
3998 aopOp (left, ic, FALSE);
3999 aopOp (right, ic, FALSE);
4000 aopOp (result, ic, TRUE);
4002 genCmp (left, right, result, ifx, sign,ic);
4004 freeAsmop (result, NULL, ic, TRUE);
4007 /*-----------------------------------------------------------------*/
4008 /* gencjneshort - compare and jump if not equal */
4009 /*-----------------------------------------------------------------*/
4011 gencjneshort (operand * left, operand * right, symbol * lbl)
4013 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4015 unsigned long lit = 0L;
4017 /* if the left side is a literal or
4018 if the right is in a pointer register and left
4020 if ((AOP_TYPE (left) == AOP_LIT) ||
4021 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4027 if (AOP_TYPE (right) == AOP_LIT)
4028 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4030 /* if the right side is a literal then anything goes */
4031 if (AOP_TYPE (right) == AOP_LIT &&
4032 AOP_TYPE (left) != AOP_DIR)
4036 emitcode ("cjne", "%s,%s,%05d$",
4037 aopGet (AOP (left), offset, FALSE, FALSE),
4038 aopGet (AOP (right), offset, FALSE, FALSE),
4044 /* if the right side is in a register or in direct space or
4045 if the left is a pointer register & right is not */
4046 else if (AOP_TYPE (right) == AOP_REG ||
4047 AOP_TYPE (right) == AOP_DIR ||
4048 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4049 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4053 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4054 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4055 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4056 emitcode ("jnz", "%05d$", lbl->key + 100);
4058 emitcode ("cjne", "a,%s,%05d$",
4059 aopGet (AOP (right), offset, FALSE, TRUE),
4066 /* right is a pointer reg need both a & b */
4069 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4070 if (strcmp (l, "b"))
4071 emitcode ("mov", "b,%s", l);
4072 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4073 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4079 /*-----------------------------------------------------------------*/
4080 /* gencjne - compare and jump if not equal */
4081 /*-----------------------------------------------------------------*/
4083 gencjne (operand * left, operand * right, symbol * lbl)
4085 symbol *tlbl = newiTempLabel (NULL);
4087 gencjneshort (left, right, lbl);
4089 emitcode ("mov", "a,%s", one);
4090 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4091 emitcode ("", "%05d$:", lbl->key + 100);
4092 emitcode ("clr", "a");
4093 emitcode ("", "%05d$:", tlbl->key + 100);
4096 /*-----------------------------------------------------------------*/
4097 /* genCmpEq - generates code for equal to */
4098 /*-----------------------------------------------------------------*/
4100 genCmpEq (iCode * ic, iCode * ifx)
4102 operand *left, *right, *result;
4104 D(emitcode (";", "genCmpEq"));
4106 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4107 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4108 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4110 /* if literal, literal on the right or
4111 if the right is in a pointer register and left
4113 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4114 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4116 operand *t = IC_RIGHT (ic);
4117 IC_RIGHT (ic) = IC_LEFT (ic);
4121 if (ifx && !AOP_SIZE (result))
4124 /* if they are both bit variables */
4125 if (AOP_TYPE (left) == AOP_CRY &&
4126 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4128 if (AOP_TYPE (right) == AOP_LIT)
4130 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4133 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4134 emitcode ("cpl", "c");
4138 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4142 emitcode ("clr", "c");
4144 /* AOP_TYPE(right) == AOP_CRY */
4148 symbol *lbl = newiTempLabel (NULL);
4149 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4150 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4151 emitcode ("cpl", "c");
4152 emitcode ("", "%05d$:", (lbl->key + 100));
4154 /* if true label then we jump if condition
4156 tlbl = newiTempLabel (NULL);
4159 emitcode ("jnc", "%05d$", tlbl->key + 100);
4160 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4164 emitcode ("jc", "%05d$", tlbl->key + 100);
4165 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4167 emitcode ("", "%05d$:", tlbl->key + 100);
4171 tlbl = newiTempLabel (NULL);
4172 gencjneshort (left, right, tlbl);
4175 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4176 emitcode ("", "%05d$:", tlbl->key + 100);
4180 symbol *lbl = newiTempLabel (NULL);
4181 emitcode ("sjmp", "%05d$", lbl->key + 100);
4182 emitcode ("", "%05d$:", tlbl->key + 100);
4183 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4184 emitcode ("", "%05d$:", lbl->key + 100);
4187 /* mark the icode as generated */
4192 /* if they are both bit variables */
4193 if (AOP_TYPE (left) == AOP_CRY &&
4194 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4196 if (AOP_TYPE (right) == AOP_LIT)
4198 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4201 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4202 emitcode ("cpl", "c");
4206 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4210 emitcode ("clr", "c");
4212 /* AOP_TYPE(right) == AOP_CRY */
4216 symbol *lbl = newiTempLabel (NULL);
4217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4218 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4219 emitcode ("cpl", "c");
4220 emitcode ("", "%05d$:", (lbl->key + 100));
4223 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4230 genIfxJump (ifx, "c");
4233 /* if the result is used in an arithmetic operation
4234 then put the result in place */
4239 gencjne (left, right, newiTempLabel (NULL));
4240 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4242 aopPut (AOP (result), "a", 0);
4247 genIfxJump (ifx, "a");
4250 /* if the result is used in an arithmetic operation
4251 then put the result in place */
4252 if (AOP_TYPE (result) != AOP_CRY)
4254 /* leave the result in acc */
4258 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4259 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4260 freeAsmop (result, NULL, ic, TRUE);
4263 /*-----------------------------------------------------------------*/
4264 /* ifxForOp - returns the icode containing the ifx for operand */
4265 /*-----------------------------------------------------------------*/
4267 ifxForOp (operand * op, iCode * ic)
4269 /* if true symbol then needs to be assigned */
4270 if (IS_TRUE_SYMOP (op))
4273 /* if this has register type condition and
4274 the next instruction is ifx with the same operand
4275 and live to of the operand is upto the ifx only then */
4277 ic->next->op == IFX &&
4278 IC_COND (ic->next)->key == op->key &&
4279 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4285 /*-----------------------------------------------------------------*/
4286 /* hasInc - operand is incremented before any other use */
4287 /*-----------------------------------------------------------------*/
4289 hasInc (operand *op, iCode *ic)
4291 sym_link *type = operandType(op);
4292 sym_link *retype = getSpec (type);
4293 iCode *lic = ic->next;
4296 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4297 if (!IS_SYMOP(op)) return NULL;
4299 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4300 isize = getSize(type->next);
4302 /* if operand of the form op = op + <sizeof *op> */
4303 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4304 isOperandEqual(IC_RESULT(lic),op) &&
4305 isOperandLiteral(IC_RIGHT(lic)) &&
4306 operandLitValue(IC_RIGHT(lic)) == isize) {
4309 /* if the operand used or deffed */
4310 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4318 /*-----------------------------------------------------------------*/
4319 /* genAndOp - for && operation */
4320 /*-----------------------------------------------------------------*/
4322 genAndOp (iCode * ic)
4324 operand *left, *right, *result;
4327 D(emitcode (";", "genAndOp"));
4329 /* note here that && operations that are in an
4330 if statement are taken away by backPatchLabels
4331 only those used in arthmetic operations remain */
4332 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4333 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4334 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4336 /* if both are bit variables */
4337 if (AOP_TYPE (left) == AOP_CRY &&
4338 AOP_TYPE (right) == AOP_CRY)
4340 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4341 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4346 tlbl = newiTempLabel (NULL);
4348 emitcode ("jz", "%05d$", tlbl->key + 100);
4350 emitcode ("", "%05d$:", tlbl->key + 100);
4354 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4355 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4356 freeAsmop (result, NULL, ic, TRUE);
4360 /*-----------------------------------------------------------------*/
4361 /* genOrOp - for || operation */
4362 /*-----------------------------------------------------------------*/
4364 genOrOp (iCode * ic)
4366 operand *left, *right, *result;
4369 D(emitcode (";", "genOrOp"));
4371 /* note here that || operations that are in an
4372 if statement are taken away by backPatchLabels
4373 only those used in arthmetic operations remain */
4374 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4375 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4376 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4378 /* if both are bit variables */
4379 if (AOP_TYPE (left) == AOP_CRY &&
4380 AOP_TYPE (right) == AOP_CRY)
4382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4383 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4388 tlbl = newiTempLabel (NULL);
4390 emitcode ("jnz", "%05d$", tlbl->key + 100);
4392 emitcode ("", "%05d$:", tlbl->key + 100);
4396 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4397 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4398 freeAsmop (result, NULL, ic, TRUE);
4401 /*-----------------------------------------------------------------*/
4402 /* isLiteralBit - test if lit == 2^n */
4403 /*-----------------------------------------------------------------*/
4405 isLiteralBit (unsigned long lit)
4407 unsigned long pw[32] =
4408 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4409 0x100L, 0x200L, 0x400L, 0x800L,
4410 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4411 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4412 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4413 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4414 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4417 for (idx = 0; idx < 32; idx++)
4423 /*-----------------------------------------------------------------*/
4424 /* continueIfTrue - */
4425 /*-----------------------------------------------------------------*/
4427 continueIfTrue (iCode * ic)
4430 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4434 /*-----------------------------------------------------------------*/
4436 /*-----------------------------------------------------------------*/
4438 jumpIfTrue (iCode * ic)
4441 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4445 /*-----------------------------------------------------------------*/
4446 /* jmpTrueOrFalse - */
4447 /*-----------------------------------------------------------------*/
4449 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4451 // ugly but optimized by peephole
4454 symbol *nlbl = newiTempLabel (NULL);
4455 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4456 emitcode ("", "%05d$:", tlbl->key + 100);
4457 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4458 emitcode ("", "%05d$:", nlbl->key + 100);
4462 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4463 emitcode ("", "%05d$:", tlbl->key + 100);
4468 /*-----------------------------------------------------------------*/
4469 /* genAnd - code for and */
4470 /*-----------------------------------------------------------------*/
4472 genAnd (iCode * ic, iCode * ifx)
4474 operand *left, *right, *result;
4475 int size, offset = 0;
4476 unsigned long lit = 0L;
4480 D(emitcode (";", "genAnd"));
4482 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4483 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4484 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4487 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4489 AOP_TYPE (left), AOP_TYPE (right));
4490 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4492 AOP_SIZE (left), AOP_SIZE (right));
4495 /* if left is a literal & right is not then exchange them */
4496 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4497 AOP_NEEDSACC (left))
4499 operand *tmp = right;
4504 /* if result = right then exchange them */
4505 if (sameRegs (AOP (result), AOP (right)))
4507 operand *tmp = right;
4512 /* if right is bit then exchange them */
4513 if (AOP_TYPE (right) == AOP_CRY &&
4514 AOP_TYPE (left) != AOP_CRY)
4516 operand *tmp = right;
4520 if (AOP_TYPE (right) == AOP_LIT)
4521 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4523 size = AOP_SIZE (result);
4526 // result = bit & yy;
4527 if (AOP_TYPE (left) == AOP_CRY)
4529 // c = bit & literal;
4530 if (AOP_TYPE (right) == AOP_LIT)
4534 if (size && sameRegs (AOP (result), AOP (left)))
4537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4542 if (size && (AOP_TYPE (result) == AOP_CRY))
4544 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4547 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4552 emitcode ("clr", "c");
4557 if (AOP_TYPE (right) == AOP_CRY)
4560 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4561 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4566 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4568 emitcode ("rrc", "a");
4569 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4577 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4578 genIfxJump (ifx, "c");
4582 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4583 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4584 if ((AOP_TYPE (right) == AOP_LIT) &&
4585 (AOP_TYPE (result) == AOP_CRY) &&
4586 (AOP_TYPE (left) != AOP_CRY))
4588 int posbit = isLiteralBit (lit);
4593 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4596 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4602 sprintf (buffer, "acc.%d", posbit & 0x07);
4603 genIfxJump (ifx, buffer);
4610 symbol *tlbl = newiTempLabel (NULL);
4611 int sizel = AOP_SIZE (left);
4613 emitcode ("setb", "c");
4616 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4618 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4620 if ((posbit = isLiteralBit (bytelit)) != 0)
4621 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4624 if (bytelit != 0x0FFL)
4625 emitcode ("anl", "a,%s",
4626 aopGet (AOP (right), offset, FALSE, TRUE));
4627 emitcode ("jnz", "%05d$", tlbl->key + 100);
4632 // bit = left & literal
4635 emitcode ("clr", "c");
4636 emitcode ("", "%05d$:", tlbl->key + 100);
4638 // if(left & literal)
4642 jmpTrueOrFalse (ifx, tlbl);
4650 /* if left is same as result */
4651 if (sameRegs (AOP (result), AOP (left)))
4653 for (; size--; offset++)
4655 if (AOP_TYPE (right) == AOP_LIT)
4657 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4659 else if (bytelit == 0)
4660 aopPut (AOP (result), zero, offset);
4661 else if (IS_AOP_PREG (result))
4663 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4664 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4665 aopPut (AOP (result), "a", offset);
4668 emitcode ("anl", "%s,%s",
4669 aopGet (AOP (left), offset, FALSE, TRUE),
4670 aopGet (AOP (right), offset, FALSE, FALSE));
4674 if (AOP_TYPE (left) == AOP_ACC)
4675 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4678 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4679 if (IS_AOP_PREG (result))
4681 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4682 aopPut (AOP (result), "a", offset);
4686 emitcode ("anl", "%s,a",
4687 aopGet (AOP (left), offset, FALSE, TRUE));
4694 // left & result in different registers
4695 if (AOP_TYPE (result) == AOP_CRY)
4698 // if(size), result in bit
4699 // if(!size && ifx), conditional oper: if(left & right)
4700 symbol *tlbl = newiTempLabel (NULL);
4701 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4703 emitcode ("setb", "c");
4706 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4707 emitcode ("anl", "a,%s",
4708 aopGet (AOP (right), offset, FALSE, FALSE));
4710 if (AOP_TYPE(left)==AOP_ACC) {
4711 emitcode("mov", "b,a");
4712 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4713 emitcode("anl", "a,b");
4715 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4716 emitcode ("anl", "a,%s",
4717 aopGet (AOP (left), offset, FALSE, FALSE));
4720 emitcode ("jnz", "%05d$", tlbl->key + 100);
4726 emitcode ("", "%05d$:", tlbl->key + 100);
4730 jmpTrueOrFalse (ifx, tlbl);
4734 for (; (size--); offset++)
4737 // result = left & right
4738 if (AOP_TYPE (right) == AOP_LIT)
4740 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4742 aopPut (AOP (result),
4743 aopGet (AOP (left), offset, FALSE, FALSE),
4747 else if (bytelit == 0)
4749 aopPut (AOP (result), zero, offset);
4753 // faster than result <- left, anl result,right
4754 // and better if result is SFR
4755 if (AOP_TYPE (left) == AOP_ACC)
4756 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4759 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4760 emitcode ("anl", "a,%s",
4761 aopGet (AOP (left), offset, FALSE, FALSE));
4763 aopPut (AOP (result), "a", offset);
4769 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4770 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771 freeAsmop (result, NULL, ic, TRUE);
4774 /*-----------------------------------------------------------------*/
4775 /* genOr - code for or */
4776 /*-----------------------------------------------------------------*/
4778 genOr (iCode * ic, iCode * ifx)
4780 operand *left, *right, *result;
4781 int size, offset = 0;
4782 unsigned long lit = 0L;
4784 D(emitcode (";", "genOr"));
4786 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4787 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4788 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4791 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4793 AOP_TYPE (left), AOP_TYPE (right));
4794 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4796 AOP_SIZE (left), AOP_SIZE (right));
4799 /* if left is a literal & right is not then exchange them */
4800 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4801 AOP_NEEDSACC (left))
4803 operand *tmp = right;
4808 /* if result = right then exchange them */
4809 if (sameRegs (AOP (result), AOP (right)))
4811 operand *tmp = right;
4816 /* if right is bit then exchange them */
4817 if (AOP_TYPE (right) == AOP_CRY &&
4818 AOP_TYPE (left) != AOP_CRY)
4820 operand *tmp = right;
4824 if (AOP_TYPE (right) == AOP_LIT)
4825 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4827 size = AOP_SIZE (result);
4831 if (AOP_TYPE (left) == AOP_CRY)
4833 if (AOP_TYPE (right) == AOP_LIT)
4835 // c = bit & literal;
4838 // lit != 0 => result = 1
4839 if (AOP_TYPE (result) == AOP_CRY)
4842 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4844 continueIfTrue (ifx);
4847 emitcode ("setb", "c");
4851 // lit == 0 => result = left
4852 if (size && sameRegs (AOP (result), AOP (left)))
4854 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4859 if (AOP_TYPE (right) == AOP_CRY)
4862 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4863 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4868 symbol *tlbl = newiTempLabel (NULL);
4869 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4870 emitcode ("setb", "c");
4871 emitcode ("jb", "%s,%05d$",
4872 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4874 emitcode ("jnz", "%05d$", tlbl->key + 100);
4875 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4877 jmpTrueOrFalse (ifx, tlbl);
4883 emitcode ("", "%05d$:", tlbl->key + 100);
4892 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4893 genIfxJump (ifx, "c");
4897 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4898 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4899 if ((AOP_TYPE (right) == AOP_LIT) &&
4900 (AOP_TYPE (result) == AOP_CRY) &&
4901 (AOP_TYPE (left) != AOP_CRY))
4907 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4909 continueIfTrue (ifx);
4914 // lit = 0, result = boolean(left)
4916 emitcode ("setb", "c");
4920 symbol *tlbl = newiTempLabel (NULL);
4921 emitcode ("jnz", "%05d$", tlbl->key + 100);
4923 emitcode ("", "%05d$:", tlbl->key + 100);
4927 genIfxJump (ifx, "a");
4935 /* if left is same as result */
4936 if (sameRegs (AOP (result), AOP (left)))
4938 for (; size--; offset++)
4940 if (AOP_TYPE (right) == AOP_LIT)
4942 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4944 else if (IS_AOP_PREG (left))
4946 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4947 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4948 aopPut (AOP (result), "a", offset);
4951 emitcode ("orl", "%s,%s",
4952 aopGet (AOP (left), offset, FALSE, TRUE),
4953 aopGet (AOP (right), offset, FALSE, FALSE));
4957 if (AOP_TYPE (left) == AOP_ACC)
4958 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4961 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4962 if (IS_AOP_PREG (left))
4964 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4965 aopPut (AOP (result), "a", offset);
4968 emitcode ("orl", "%s,a",
4969 aopGet (AOP (left), offset, FALSE, TRUE));
4976 // left & result in different registers
4977 if (AOP_TYPE (result) == AOP_CRY)
4980 // if(size), result in bit
4981 // if(!size && ifx), conditional oper: if(left | right)
4982 symbol *tlbl = newiTempLabel (NULL);
4983 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4985 emitcode ("setb", "c");
4988 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4989 emitcode ("orl", "a,%s",
4990 aopGet (AOP (right), offset, FALSE, FALSE));
4992 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4993 emitcode ("orl", "a,%s",
4994 aopGet (AOP (left), offset, FALSE, FALSE));
4996 emitcode ("jnz", "%05d$", tlbl->key + 100);
5002 emitcode ("", "%05d$:", tlbl->key + 100);
5006 jmpTrueOrFalse (ifx, tlbl);
5009 for (; (size--); offset++)
5012 // result = left & right
5013 if (AOP_TYPE (right) == AOP_LIT)
5015 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5017 aopPut (AOP (result),
5018 aopGet (AOP (left), offset, FALSE, FALSE),
5023 // faster than result <- left, anl result,right
5024 // and better if result is SFR
5025 if (AOP_TYPE (left) == AOP_ACC)
5026 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5029 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5030 emitcode ("orl", "a,%s",
5031 aopGet (AOP (left), offset, FALSE, FALSE));
5033 aopPut (AOP (result), "a", offset);
5038 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5039 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5040 freeAsmop (result, NULL, ic, TRUE);
5043 /*-----------------------------------------------------------------*/
5044 /* genXor - code for xclusive or */
5045 /*-----------------------------------------------------------------*/
5047 genXor (iCode * ic, iCode * ifx)
5049 operand *left, *right, *result;
5050 int size, offset = 0;
5051 unsigned long lit = 0L;
5053 D(emitcode (";", "genXor"));
5055 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5056 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5057 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5060 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5062 AOP_TYPE (left), AOP_TYPE (right));
5063 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5065 AOP_SIZE (left), AOP_SIZE (right));
5068 /* if left is a literal & right is not ||
5069 if left needs acc & right does not */
5070 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5071 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5073 operand *tmp = right;
5078 /* if result = right then exchange them */
5079 if (sameRegs (AOP (result), AOP (right)))
5081 operand *tmp = right;
5086 /* if right is bit then exchange them */
5087 if (AOP_TYPE (right) == AOP_CRY &&
5088 AOP_TYPE (left) != AOP_CRY)
5090 operand *tmp = right;
5094 if (AOP_TYPE (right) == AOP_LIT)
5095 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5097 size = AOP_SIZE (result);
5101 if (AOP_TYPE (left) == AOP_CRY)
5103 if (AOP_TYPE (right) == AOP_LIT)
5105 // c = bit & literal;
5108 // lit>>1 != 0 => result = 1
5109 if (AOP_TYPE (result) == AOP_CRY)
5112 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5114 continueIfTrue (ifx);
5117 emitcode ("setb", "c");
5124 // lit == 0, result = left
5125 if (size && sameRegs (AOP (result), AOP (left)))
5127 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5131 // lit == 1, result = not(left)
5132 if (size && sameRegs (AOP (result), AOP (left)))
5134 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5139 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5140 emitcode ("cpl", "c");
5149 symbol *tlbl = newiTempLabel (NULL);
5150 if (AOP_TYPE (right) == AOP_CRY)
5153 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5157 int sizer = AOP_SIZE (right);
5159 // if val>>1 != 0, result = 1
5160 emitcode ("setb", "c");
5163 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5165 // test the msb of the lsb
5166 emitcode ("anl", "a,#0xfe");
5167 emitcode ("jnz", "%05d$", tlbl->key + 100);
5171 emitcode ("rrc", "a");
5173 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5174 emitcode ("cpl", "c");
5175 emitcode ("", "%05d$:", (tlbl->key + 100));
5182 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5183 genIfxJump (ifx, "c");
5187 if (sameRegs (AOP (result), AOP (left)))
5189 /* if left is same as result */
5190 for (; size--; offset++)
5192 if (AOP_TYPE (right) == AOP_LIT)
5194 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5196 else if (IS_AOP_PREG (left))
5198 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5199 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5200 aopPut (AOP (result), "a", offset);
5203 emitcode ("xrl", "%s,%s",
5204 aopGet (AOP (left), offset, FALSE, TRUE),
5205 aopGet (AOP (right), offset, FALSE, FALSE));
5209 if (AOP_TYPE (left) == AOP_ACC)
5210 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5213 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5214 if (IS_AOP_PREG (left))
5216 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5217 aopPut (AOP (result), "a", offset);
5220 emitcode ("xrl", "%s,a",
5221 aopGet (AOP (left), offset, FALSE, TRUE));
5228 // left & result in different registers
5229 if (AOP_TYPE (result) == AOP_CRY)
5232 // if(size), result in bit
5233 // if(!size && ifx), conditional oper: if(left ^ right)
5234 symbol *tlbl = newiTempLabel (NULL);
5235 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5237 emitcode ("setb", "c");
5240 if ((AOP_TYPE (right) == AOP_LIT) &&
5241 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5243 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5247 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5248 emitcode ("xrl", "a,%s",
5249 aopGet (AOP (right), offset, FALSE, FALSE));
5251 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5252 emitcode ("xrl", "a,%s",
5253 aopGet (AOP (left), offset, FALSE, FALSE));
5256 emitcode ("jnz", "%05d$", tlbl->key + 100);
5262 emitcode ("", "%05d$:", tlbl->key + 100);
5266 jmpTrueOrFalse (ifx, tlbl);
5269 for (; (size--); offset++)
5272 // result = left & right
5273 if (AOP_TYPE (right) == AOP_LIT)
5275 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5277 aopPut (AOP (result),
5278 aopGet (AOP (left), offset, FALSE, FALSE),
5283 // faster than result <- left, anl result,right
5284 // and better if result is SFR
5285 if (AOP_TYPE (left) == AOP_ACC)
5286 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5289 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5290 emitcode ("xrl", "a,%s",
5291 aopGet (AOP (left), offset, FALSE, TRUE));
5293 aopPut (AOP (result), "a", offset);
5298 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5299 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5300 freeAsmop (result, NULL, ic, TRUE);
5303 /*-----------------------------------------------------------------*/
5304 /* genInline - write the inline code out */
5305 /*-----------------------------------------------------------------*/
5307 genInline (iCode * ic)
5309 char *buffer, *bp, *bp1;
5311 D(emitcode (";", "genInline"));
5313 _G.inLine += (!options.asmpeep);
5315 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5316 strcpy (buffer, IC_INLINE (ic));
5318 /* emit each line as a code */
5343 /* emitcode("",buffer); */
5344 _G.inLine -= (!options.asmpeep);
5347 /*-----------------------------------------------------------------*/
5348 /* genRRC - rotate right with carry */
5349 /*-----------------------------------------------------------------*/
5353 operand *left, *result;
5354 int size, offset = 0;
5357 D(emitcode (";", "genRRC"));
5359 /* rotate right with carry */
5360 left = IC_LEFT (ic);
5361 result = IC_RESULT (ic);
5362 aopOp (left, ic, FALSE);
5363 aopOp (result, ic, FALSE);
5365 /* move it to the result */
5366 size = AOP_SIZE (result);
5368 if (size == 1) { /* special case for 1 byte */
5369 l = aopGet (AOP (left), offset, FALSE, FALSE);
5371 emitcode ("rr", "a");
5377 l = aopGet (AOP (left), offset, FALSE, FALSE);
5379 emitcode ("rrc", "a");
5380 if (AOP_SIZE (result) > 1)
5381 aopPut (AOP (result), "a", offset--);
5383 /* now we need to put the carry into the
5384 highest order byte of the result */
5385 if (AOP_SIZE (result) > 1)
5387 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5390 emitcode ("mov", "acc.7,c");
5392 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5393 freeAsmop (left, NULL, ic, TRUE);
5394 freeAsmop (result, NULL, ic, TRUE);
5397 /*-----------------------------------------------------------------*/
5398 /* genRLC - generate code for rotate left with carry */
5399 /*-----------------------------------------------------------------*/
5403 operand *left, *result;
5404 int size, offset = 0;
5407 D(emitcode (";", "genRLC"));
5409 /* rotate right with carry */
5410 left = IC_LEFT (ic);
5411 result = IC_RESULT (ic);
5412 aopOp (left, ic, FALSE);
5413 aopOp (result, ic, FALSE);
5415 /* move it to the result */
5416 size = AOP_SIZE (result);
5420 l = aopGet (AOP (left), offset, FALSE, FALSE);
5422 if (size == 0) { /* special case for 1 byte */
5426 emitcode ("add", "a,acc");
5427 if (AOP_SIZE (result) > 1)
5428 aopPut (AOP (result), "a", offset++);
5431 l = aopGet (AOP (left), offset, FALSE, FALSE);
5433 emitcode ("rlc", "a");
5434 if (AOP_SIZE (result) > 1)
5435 aopPut (AOP (result), "a", offset++);
5438 /* now we need to put the carry into the
5439 highest order byte of the result */
5440 if (AOP_SIZE (result) > 1)
5442 l = aopGet (AOP (result), 0, FALSE, FALSE);
5445 emitcode ("mov", "acc.0,c");
5447 aopPut (AOP (result), "a", 0);
5448 freeAsmop (left, NULL, ic, TRUE);
5449 freeAsmop (result, NULL, ic, TRUE);
5452 /*-----------------------------------------------------------------*/
5453 /* genGetHbit - generates code get highest order bit */
5454 /*-----------------------------------------------------------------*/
5456 genGetHbit (iCode * ic)
5458 operand *left, *result;
5460 D(emitcode (";", "genGetHbit"));
5462 left = IC_LEFT (ic);
5463 result = IC_RESULT (ic);
5464 aopOp (left, ic, FALSE);
5465 aopOp (result, ic, FALSE);
5467 /* get the highest order byte into a */
5468 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5469 if (AOP_TYPE (result) == AOP_CRY)
5471 emitcode ("rlc", "a");
5476 emitcode ("rl", "a");
5477 emitcode ("anl", "a,#0x01");
5482 freeAsmop (left, NULL, ic, TRUE);
5483 freeAsmop (result, NULL, ic, TRUE);
5486 /*-----------------------------------------------------------------*/
5487 /* AccRol - rotate left accumulator by known count */
5488 /*-----------------------------------------------------------------*/
5490 AccRol (int shCount)
5492 shCount &= 0x0007; // shCount : 0..7
5499 emitcode ("rl", "a");
5502 emitcode ("rl", "a");
5503 emitcode ("rl", "a");
5506 emitcode ("swap", "a");
5507 emitcode ("rr", "a");
5510 emitcode ("swap", "a");
5513 emitcode ("swap", "a");
5514 emitcode ("rl", "a");
5517 emitcode ("rr", "a");
5518 emitcode ("rr", "a");
5521 emitcode ("rr", "a");
5526 /*-----------------------------------------------------------------*/
5527 /* AccLsh - left shift accumulator by known count */
5528 /*-----------------------------------------------------------------*/
5530 AccLsh (int shCount)
5535 emitcode ("add", "a,acc");
5536 else if (shCount == 2)
5538 emitcode ("add", "a,acc");
5539 emitcode ("add", "a,acc");
5543 /* rotate left accumulator */
5545 /* and kill the lower order bits */
5546 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5551 /*-----------------------------------------------------------------*/
5552 /* AccRsh - right shift accumulator by known count */
5553 /*-----------------------------------------------------------------*/
5555 AccRsh (int shCount)
5562 emitcode ("rrc", "a");
5566 /* rotate right accumulator */
5567 AccRol (8 - shCount);
5568 /* and kill the higher order bits */
5569 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5574 /*-----------------------------------------------------------------*/
5575 /* AccSRsh - signed right shift accumulator by known count */
5576 /*-----------------------------------------------------------------*/
5578 AccSRsh (int shCount)
5585 emitcode ("mov", "c,acc.7");
5586 emitcode ("rrc", "a");
5588 else if (shCount == 2)
5590 emitcode ("mov", "c,acc.7");
5591 emitcode ("rrc", "a");
5592 emitcode ("mov", "c,acc.7");
5593 emitcode ("rrc", "a");
5597 tlbl = newiTempLabel (NULL);
5598 /* rotate right accumulator */
5599 AccRol (8 - shCount);
5600 /* and kill the higher order bits */
5601 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5602 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5603 emitcode ("orl", "a,#0x%02x",
5604 (unsigned char) ~SRMask[shCount]);
5605 emitcode ("", "%05d$:", tlbl->key + 100);
5610 /*-----------------------------------------------------------------*/
5611 /* shiftR1Left2Result - shift right one byte from left to result */
5612 /*-----------------------------------------------------------------*/
5614 shiftR1Left2Result (operand * left, int offl,
5615 operand * result, int offr,
5616 int shCount, int sign)
5618 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5619 /* shift right accumulator */
5624 aopPut (AOP (result), "a", offr);
5627 /*-----------------------------------------------------------------*/
5628 /* shiftL1Left2Result - shift left one byte from left to result */
5629 /*-----------------------------------------------------------------*/
5631 shiftL1Left2Result (operand * left, int offl,
5632 operand * result, int offr, int shCount)
5635 l = aopGet (AOP (left), offl, FALSE, FALSE);
5637 /* shift left accumulator */
5639 aopPut (AOP (result), "a", offr);
5642 /*-----------------------------------------------------------------*/
5643 /* movLeft2Result - move byte from left to result */
5644 /*-----------------------------------------------------------------*/
5646 movLeft2Result (operand * left, int offl,
5647 operand * result, int offr, int sign)
5650 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5652 l = aopGet (AOP (left), offl, FALSE, FALSE);
5654 if (*l == '@' && (IS_AOP_PREG (result)))
5656 emitcode ("mov", "a,%s", l);
5657 aopPut (AOP (result), "a", offr);
5662 aopPut (AOP (result), l, offr);
5665 /* MSB sign in acc.7 ! */
5666 if (getDataSize (left) == offl + 1)
5668 emitcode ("mov", "a,%s", l);
5669 aopPut (AOP (result), "a", offr);
5676 /*-----------------------------------------------------------------*/
5677 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5678 /*-----------------------------------------------------------------*/
5682 emitcode ("rrc", "a");
5683 emitcode ("xch", "a,%s", x);
5684 emitcode ("rrc", "a");
5685 emitcode ("xch", "a,%s", x);
5688 /*-----------------------------------------------------------------*/
5689 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5690 /*-----------------------------------------------------------------*/
5694 emitcode ("xch", "a,%s", x);
5695 emitcode ("rlc", "a");
5696 emitcode ("xch", "a,%s", x);
5697 emitcode ("rlc", "a");
5700 /*-----------------------------------------------------------------*/
5701 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5702 /*-----------------------------------------------------------------*/
5706 emitcode ("xch", "a,%s", x);
5707 emitcode ("add", "a,acc");
5708 emitcode ("xch", "a,%s", x);
5709 emitcode ("rlc", "a");
5712 /*-----------------------------------------------------------------*/
5713 /* AccAXLsh - left shift a:x by known count (0..7) */
5714 /*-----------------------------------------------------------------*/
5716 AccAXLsh (char *x, int shCount)
5731 case 5: // AAAAABBB:CCCCCDDD
5733 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5735 emitcode ("anl", "a,#0x%02x",
5736 SLMask[shCount]); // BBB00000:CCCCCDDD
5738 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5740 AccRol (shCount); // DDDCCCCC:BBB00000
5742 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5744 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5746 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5748 emitcode ("anl", "a,#0x%02x",
5749 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5751 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5753 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5756 case 6: // AAAAAABB:CCCCCCDD
5757 emitcode ("anl", "a,#0x%02x",
5758 SRMask[shCount]); // 000000BB:CCCCCCDD
5759 emitcode ("mov", "c,acc.0"); // c = B
5760 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5762 AccAXRrl1 (x); // BCCCCCCD:D000000B
5763 AccAXRrl1 (x); // BBCCCCCC:DD000000
5765 emitcode("rrc","a");
5766 emitcode("xch","a,%s", x);
5767 emitcode("rrc","a");
5768 emitcode("mov","c,acc.0"); //<< get correct bit
5769 emitcode("xch","a,%s", x);
5771 emitcode("rrc","a");
5772 emitcode("xch","a,%s", x);
5773 emitcode("rrc","a");
5774 emitcode("xch","a,%s", x);
5777 case 7: // a:x <<= 7
5779 emitcode ("anl", "a,#0x%02x",
5780 SRMask[shCount]); // 0000000B:CCCCCCCD
5782 emitcode ("mov", "c,acc.0"); // c = B
5784 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5786 AccAXRrl1 (x); // BCCCCCCC:D0000000
5794 /*-----------------------------------------------------------------*/
5795 /* AccAXRsh - right shift a:x known count (0..7) */
5796 /*-----------------------------------------------------------------*/
5798 AccAXRsh (char *x, int shCount)
5806 AccAXRrl1 (x); // 0->a:x
5811 AccAXRrl1 (x); // 0->a:x
5814 AccAXRrl1 (x); // 0->a:x
5819 case 5: // AAAAABBB:CCCCCDDD = a:x
5821 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5823 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5825 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5827 emitcode ("anl", "a,#0x%02x",
5828 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5830 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5832 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5834 emitcode ("anl", "a,#0x%02x",
5835 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5837 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5839 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5841 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5844 case 6: // AABBBBBB:CCDDDDDD
5846 emitcode ("mov", "c,acc.7");
5847 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5849 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5851 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5853 emitcode ("anl", "a,#0x%02x",
5854 SRMask[shCount]); // 000000AA:BBBBBBCC
5857 case 7: // ABBBBBBB:CDDDDDDD
5859 emitcode ("mov", "c,acc.7"); // c = A
5861 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5863 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5865 emitcode ("anl", "a,#0x%02x",
5866 SRMask[shCount]); // 0000000A:BBBBBBBC
5874 /*-----------------------------------------------------------------*/
5875 /* AccAXRshS - right shift signed a:x known count (0..7) */
5876 /*-----------------------------------------------------------------*/
5878 AccAXRshS (char *x, int shCount)
5886 emitcode ("mov", "c,acc.7");
5887 AccAXRrl1 (x); // s->a:x
5891 emitcode ("mov", "c,acc.7");
5892 AccAXRrl1 (x); // s->a:x
5894 emitcode ("mov", "c,acc.7");
5895 AccAXRrl1 (x); // s->a:x
5900 case 5: // AAAAABBB:CCCCCDDD = a:x
5902 tlbl = newiTempLabel (NULL);
5903 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5905 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5907 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5909 emitcode ("anl", "a,#0x%02x",
5910 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5912 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5914 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5916 emitcode ("anl", "a,#0x%02x",
5917 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5919 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5921 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5923 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5925 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5926 emitcode ("orl", "a,#0x%02x",
5927 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5929 emitcode ("", "%05d$:", tlbl->key + 100);
5930 break; // SSSSAAAA:BBBCCCCC
5932 case 6: // AABBBBBB:CCDDDDDD
5934 tlbl = newiTempLabel (NULL);
5935 emitcode ("mov", "c,acc.7");
5936 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5938 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5940 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5942 emitcode ("anl", "a,#0x%02x",
5943 SRMask[shCount]); // 000000AA:BBBBBBCC
5945 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5946 emitcode ("orl", "a,#0x%02x",
5947 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5949 emitcode ("", "%05d$:", tlbl->key + 100);
5951 case 7: // ABBBBBBB:CDDDDDDD
5953 tlbl = newiTempLabel (NULL);
5954 emitcode ("mov", "c,acc.7"); // c = A
5956 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5958 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5960 emitcode ("anl", "a,#0x%02x",
5961 SRMask[shCount]); // 0000000A:BBBBBBBC
5963 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5964 emitcode ("orl", "a,#0x%02x",
5965 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5967 emitcode ("", "%05d$:", tlbl->key + 100);
5974 /*-----------------------------------------------------------------*/
5975 /* shiftL2Left2Result - shift left two bytes from left to result */
5976 /*-----------------------------------------------------------------*/
5978 shiftL2Left2Result (operand * left, int offl,
5979 operand * result, int offr, int shCount)
5981 if (sameRegs (AOP (result), AOP (left)) &&
5982 ((offl + MSB16) == offr))
5984 /* don't crash result[offr] */
5985 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5986 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5990 movLeft2Result (left, offl, result, offr, 0);
5991 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5993 /* ax << shCount (x = lsb(result)) */
5994 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5995 aopPut (AOP (result), "a", offr + MSB16);
5999 /*-----------------------------------------------------------------*/
6000 /* shiftR2Left2Result - shift right two bytes from left to result */
6001 /*-----------------------------------------------------------------*/
6003 shiftR2Left2Result (operand * left, int offl,
6004 operand * result, int offr,
6005 int shCount, int sign)
6007 if (sameRegs (AOP (result), AOP (left)) &&
6008 ((offl + MSB16) == offr))
6010 /* don't crash result[offr] */
6011 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6012 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6016 movLeft2Result (left, offl, result, offr, 0);
6017 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6019 /* a:x >> shCount (x = lsb(result)) */
6021 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6023 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6024 if (getDataSize (result) > 1)
6025 aopPut (AOP (result), "a", offr + MSB16);
6028 /*-----------------------------------------------------------------*/
6029 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6030 /*-----------------------------------------------------------------*/
6032 shiftLLeftOrResult (operand * left, int offl,
6033 operand * result, int offr, int shCount)
6035 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6036 /* shift left accumulator */
6038 /* or with result */
6039 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6040 /* back to result */
6041 aopPut (AOP (result), "a", offr);
6044 /*-----------------------------------------------------------------*/
6045 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6046 /*-----------------------------------------------------------------*/
6048 shiftRLeftOrResult (operand * left, int offl,
6049 operand * result, int offr, int shCount)
6051 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6052 /* shift right accumulator */
6054 /* or with result */
6055 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6056 /* back to result */
6057 aopPut (AOP (result), "a", offr);
6060 /*-----------------------------------------------------------------*/
6061 /* genlshOne - left shift a one byte quantity by known count */
6062 /*-----------------------------------------------------------------*/
6064 genlshOne (operand * result, operand * left, int shCount)
6066 D(emitcode (";", "genlshOne"));
6068 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6071 /*-----------------------------------------------------------------*/
6072 /* genlshTwo - left shift two bytes by known amount != 0 */
6073 /*-----------------------------------------------------------------*/
6075 genlshTwo (operand * result, operand * left, int shCount)
6079 D(emitcode (";", "genlshTwo"));
6081 size = getDataSize (result);
6083 /* if shCount >= 8 */
6091 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6093 movLeft2Result (left, LSB, result, MSB16, 0);
6095 aopPut (AOP (result), zero, LSB);
6098 /* 1 <= shCount <= 7 */
6102 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6104 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6108 /*-----------------------------------------------------------------*/
6109 /* shiftLLong - shift left one long from left to result */
6110 /* offl = LSB or MSB16 */
6111 /*-----------------------------------------------------------------*/
6113 shiftLLong (operand * left, operand * result, int offr)
6116 int size = AOP_SIZE (result);
6118 if (size >= LSB + offr)
6120 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6122 emitcode ("add", "a,acc");
6123 if (sameRegs (AOP (left), AOP (result)) &&
6124 size >= MSB16 + offr && offr != LSB)
6125 emitcode ("xch", "a,%s",
6126 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6128 aopPut (AOP (result), "a", LSB + offr);
6131 if (size >= MSB16 + offr)
6133 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6135 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6138 emitcode ("rlc", "a");
6139 if (sameRegs (AOP (left), AOP (result)) &&
6140 size >= MSB24 + offr && offr != LSB)
6141 emitcode ("xch", "a,%s",
6142 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6144 aopPut (AOP (result), "a", MSB16 + offr);
6147 if (size >= MSB24 + offr)
6149 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6151 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6154 emitcode ("rlc", "a");
6155 if (sameRegs (AOP (left), AOP (result)) &&
6156 size >= MSB32 + offr && offr != LSB)
6157 emitcode ("xch", "a,%s",
6158 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6160 aopPut (AOP (result), "a", MSB24 + offr);
6163 if (size > MSB32 + offr)
6165 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6167 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6170 emitcode ("rlc", "a");
6171 aopPut (AOP (result), "a", MSB32 + offr);
6174 aopPut (AOP (result), zero, LSB);
6177 /*-----------------------------------------------------------------*/
6178 /* genlshFour - shift four byte by a known amount != 0 */
6179 /*-----------------------------------------------------------------*/
6181 genlshFour (operand * result, operand * left, int shCount)
6185 D(emitcode (";", "genlshFour"));
6187 size = AOP_SIZE (result);
6189 /* if shifting more that 3 bytes */
6194 /* lowest order of left goes to the highest
6195 order of the destination */
6196 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6198 movLeft2Result (left, LSB, result, MSB32, 0);
6199 aopPut (AOP (result), zero, LSB);
6200 aopPut (AOP (result), zero, MSB16);
6201 aopPut (AOP (result), zero, MSB24);
6205 /* more than two bytes */
6206 else if (shCount >= 16)
6208 /* lower order two bytes goes to higher order two bytes */
6210 /* if some more remaining */
6212 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6215 movLeft2Result (left, MSB16, result, MSB32, 0);
6216 movLeft2Result (left, LSB, result, MSB24, 0);
6218 aopPut (AOP (result), zero, MSB16);
6219 aopPut (AOP (result), zero, LSB);
6223 /* if more than 1 byte */
6224 else if (shCount >= 8)
6226 /* lower order three bytes goes to higher order three bytes */
6231 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6233 movLeft2Result (left, LSB, result, MSB16, 0);
6239 movLeft2Result (left, MSB24, result, MSB32, 0);
6240 movLeft2Result (left, MSB16, result, MSB24, 0);
6241 movLeft2Result (left, LSB, result, MSB16, 0);
6242 aopPut (AOP (result), zero, LSB);
6244 else if (shCount == 1)
6245 shiftLLong (left, result, MSB16);
6248 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6249 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6250 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6251 aopPut (AOP (result), zero, LSB);
6256 /* 1 <= shCount <= 7 */
6257 else if (shCount <= 2)
6259 shiftLLong (left, result, LSB);
6261 shiftLLong (result, result, LSB);
6263 /* 3 <= shCount <= 7, optimize */
6266 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6267 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6268 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6272 /*-----------------------------------------------------------------*/
6273 /* genLeftShiftLiteral - left shifting by known count */
6274 /*-----------------------------------------------------------------*/
6276 genLeftShiftLiteral (operand * left,
6281 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6284 D(emitcode (";", "genLeftShiftLiteral"));
6286 freeAsmop (right, NULL, ic, TRUE);
6288 aopOp (left, ic, FALSE);
6289 aopOp (result, ic, FALSE);
6291 size = getSize (operandType (result));
6294 emitcode ("; shift left ", "result %d, left %d", size,
6298 /* I suppose that the left size >= result size */
6303 movLeft2Result (left, size, result, size, 0);
6307 else if (shCount >= (size * 8))
6309 aopPut (AOP (result), zero, size);
6315 genlshOne (result, left, shCount);
6319 genlshTwo (result, left, shCount);
6323 genlshFour (result, left, shCount);
6326 fprintf(stderr, "*** ack! mystery literal shift!\n");
6330 freeAsmop (left, NULL, ic, TRUE);
6331 freeAsmop (result, NULL, ic, TRUE);
6334 /*-----------------------------------------------------------------*/
6335 /* genLeftShift - generates code for left shifting */
6336 /*-----------------------------------------------------------------*/
6338 genLeftShift (iCode * ic)
6340 operand *left, *right, *result;
6343 symbol *tlbl, *tlbl1;
6345 D(emitcode (";", "genLeftShift"));
6347 right = IC_RIGHT (ic);
6348 left = IC_LEFT (ic);
6349 result = IC_RESULT (ic);
6351 aopOp (right, ic, FALSE);
6353 /* if the shift count is known then do it
6354 as efficiently as possible */
6355 if (AOP_TYPE (right) == AOP_LIT)
6357 genLeftShiftLiteral (left, right, result, ic);
6361 /* shift count is unknown then we have to form
6362 a loop get the loop count in B : Note: we take
6363 only the lower order byte since shifting
6364 more that 32 bits make no sense anyway, ( the
6365 largest size of an object can be only 32 bits ) */
6367 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6368 emitcode ("inc", "b");
6369 freeAsmop (right, NULL, ic, TRUE);
6370 aopOp (left, ic, FALSE);
6371 aopOp (result, ic, FALSE);
6373 /* now move the left to the result if they are not the
6375 if (!sameRegs (AOP (left), AOP (result)) &&
6376 AOP_SIZE (result) > 1)
6379 size = AOP_SIZE (result);
6383 l = aopGet (AOP (left), offset, FALSE, TRUE);
6384 if (*l == '@' && (IS_AOP_PREG (result)))
6387 emitcode ("mov", "a,%s", l);
6388 aopPut (AOP (result), "a", offset);
6391 aopPut (AOP (result), l, offset);
6396 tlbl = newiTempLabel (NULL);
6397 size = AOP_SIZE (result);
6399 tlbl1 = newiTempLabel (NULL);
6401 /* if it is only one byte then */
6404 symbol *tlbl1 = newiTempLabel (NULL);
6406 l = aopGet (AOP (left), 0, FALSE, FALSE);
6408 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6409 emitcode ("", "%05d$:", tlbl->key + 100);
6410 emitcode ("add", "a,acc");
6411 emitcode ("", "%05d$:", tlbl1->key + 100);
6412 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6413 aopPut (AOP (result), "a", 0);
6417 reAdjustPreg (AOP (result));
6419 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6420 emitcode ("", "%05d$:", tlbl->key + 100);
6421 l = aopGet (AOP (result), offset, FALSE, FALSE);
6423 emitcode ("add", "a,acc");
6424 aopPut (AOP (result), "a", offset++);
6427 l = aopGet (AOP (result), offset, FALSE, FALSE);
6429 emitcode ("rlc", "a");
6430 aopPut (AOP (result), "a", offset++);
6432 reAdjustPreg (AOP (result));
6434 emitcode ("", "%05d$:", tlbl1->key + 100);
6435 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6437 freeAsmop (left, NULL, ic, TRUE);
6438 freeAsmop (result, NULL, ic, TRUE);
6441 /*-----------------------------------------------------------------*/
6442 /* genrshOne - right shift a one byte quantity by known count */
6443 /*-----------------------------------------------------------------*/
6445 genrshOne (operand * result, operand * left,
6446 int shCount, int sign)
6448 D(emitcode (";", "genrshOne"));
6450 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6453 /*-----------------------------------------------------------------*/
6454 /* genrshTwo - right shift two bytes by known amount != 0 */
6455 /*-----------------------------------------------------------------*/
6457 genrshTwo (operand * result, operand * left,
6458 int shCount, int sign)
6460 D(emitcode (";", "genrshTwo"));
6462 /* if shCount >= 8 */
6467 shiftR1Left2Result (left, MSB16, result, LSB,
6470 movLeft2Result (left, MSB16, result, LSB, sign);
6471 addSign (result, MSB16, sign);
6474 /* 1 <= shCount <= 7 */
6476 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6479 /*-----------------------------------------------------------------*/
6480 /* shiftRLong - shift right one long from left to result */
6481 /* offl = LSB or MSB16 */
6482 /*-----------------------------------------------------------------*/
6484 shiftRLong (operand * left, int offl,
6485 operand * result, int sign)
6487 int isSameRegs=sameRegs(AOP(left),AOP(result));
6489 if (isSameRegs && offl>1) {
6490 // we are in big trouble, but this shouldn't happen
6491 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6494 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6499 emitcode ("rlc", "a");
6500 emitcode ("subb", "a,acc");
6501 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6503 aopPut (AOP(result), zero, MSB32);
6508 emitcode ("clr", "c");
6510 emitcode ("mov", "c,acc.7");
6513 emitcode ("rrc", "a");
6515 if (isSameRegs && offl==MSB16) {
6516 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6518 aopPut (AOP (result), "a", MSB32);
6519 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6522 emitcode ("rrc", "a");
6523 if (isSameRegs && offl==1) {
6524 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6526 aopPut (AOP (result), "a", MSB24);
6527 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6529 emitcode ("rrc", "a");
6530 aopPut (AOP (result), "a", MSB16 - offl);
6534 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6535 emitcode ("rrc", "a");
6536 aopPut (AOP (result), "a", LSB);
6540 /*-----------------------------------------------------------------*/
6541 /* genrshFour - shift four byte by a known amount != 0 */
6542 /*-----------------------------------------------------------------*/
6544 genrshFour (operand * result, operand * left,
6545 int shCount, int sign)
6547 D(emitcode (";", "genrshFour"));
6549 /* if shifting more that 3 bytes */
6554 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6556 movLeft2Result (left, MSB32, result, LSB, sign);
6557 addSign (result, MSB16, sign);
6559 else if (shCount >= 16)
6563 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6566 movLeft2Result (left, MSB24, result, LSB, 0);
6567 movLeft2Result (left, MSB32, result, MSB16, sign);
6569 addSign (result, MSB24, sign);
6571 else if (shCount >= 8)
6575 shiftRLong (left, MSB16, result, sign);
6576 else if (shCount == 0)
6578 movLeft2Result (left, MSB16, result, LSB, 0);
6579 movLeft2Result (left, MSB24, result, MSB16, 0);
6580 movLeft2Result (left, MSB32, result, MSB24, sign);
6581 addSign (result, MSB32, sign);
6585 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6586 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6587 /* the last shift is signed */
6588 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6589 addSign (result, MSB32, sign);
6593 { /* 1 <= shCount <= 7 */
6596 shiftRLong (left, LSB, result, sign);
6598 shiftRLong (result, LSB, result, sign);
6602 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6603 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6604 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6609 /*-----------------------------------------------------------------*/
6610 /* genRightShiftLiteral - right shifting by known count */
6611 /*-----------------------------------------------------------------*/
6613 genRightShiftLiteral (operand * left,
6619 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6622 D(emitcode (";", "genRightShiftLiteral"));
6624 freeAsmop (right, NULL, ic, TRUE);
6626 aopOp (left, ic, FALSE);
6627 aopOp (result, ic, FALSE);
6630 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6634 size = getDataSize (left);
6635 /* test the LEFT size !!! */
6637 /* I suppose that the left size >= result size */
6640 size = getDataSize (result);
6642 movLeft2Result (left, size, result, size, 0);
6645 else if (shCount >= (size * 8))
6648 /* get sign in acc.7 */
6649 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6650 addSign (result, LSB, sign);
6657 genrshOne (result, left, shCount, sign);
6661 genrshTwo (result, left, shCount, sign);
6665 genrshFour (result, left, shCount, sign);
6671 freeAsmop (left, NULL, ic, TRUE);
6672 freeAsmop (result, NULL, ic, TRUE);
6676 /*-----------------------------------------------------------------*/
6677 /* genSignedRightShift - right shift of signed number */
6678 /*-----------------------------------------------------------------*/
6680 genSignedRightShift (iCode * ic)
6682 operand *right, *left, *result;
6685 symbol *tlbl, *tlbl1;
6687 D(emitcode (";", "genSignedRightShift"));
6689 /* we do it the hard way put the shift count in b
6690 and loop thru preserving the sign */
6692 right = IC_RIGHT (ic);
6693 left = IC_LEFT (ic);
6694 result = IC_RESULT (ic);
6696 aopOp (right, ic, FALSE);
6699 if (AOP_TYPE (right) == AOP_LIT)
6701 genRightShiftLiteral (left, right, result, ic, 1);
6704 /* shift count is unknown then we have to form
6705 a loop get the loop count in B : Note: we take
6706 only the lower order byte since shifting
6707 more that 32 bits make no sense anyway, ( the
6708 largest size of an object can be only 32 bits ) */
6710 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6711 emitcode ("inc", "b");
6712 freeAsmop (right, NULL, ic, TRUE);
6713 aopOp (left, ic, FALSE);
6714 aopOp (result, ic, FALSE);
6716 /* now move the left to the result if they are not the
6718 if (!sameRegs (AOP (left), AOP (result)) &&
6719 AOP_SIZE (result) > 1)
6722 size = AOP_SIZE (result);
6726 l = aopGet (AOP (left), offset, FALSE, TRUE);
6727 if (*l == '@' && IS_AOP_PREG (result))
6730 emitcode ("mov", "a,%s", l);
6731 aopPut (AOP (result), "a", offset);
6734 aopPut (AOP (result), l, offset);
6739 /* mov the highest order bit to OVR */
6740 tlbl = newiTempLabel (NULL);
6741 tlbl1 = newiTempLabel (NULL);
6743 size = AOP_SIZE (result);
6745 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6746 emitcode ("rlc", "a");
6747 emitcode ("mov", "ov,c");
6748 /* if it is only one byte then */
6751 l = aopGet (AOP (left), 0, FALSE, FALSE);
6753 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6754 emitcode ("", "%05d$:", tlbl->key + 100);
6755 emitcode ("mov", "c,ov");
6756 emitcode ("rrc", "a");
6757 emitcode ("", "%05d$:", tlbl1->key + 100);
6758 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6759 aopPut (AOP (result), "a", 0);
6763 reAdjustPreg (AOP (result));
6764 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6765 emitcode ("", "%05d$:", tlbl->key + 100);
6766 emitcode ("mov", "c,ov");
6769 l = aopGet (AOP (result), offset, FALSE, FALSE);
6771 emitcode ("rrc", "a");
6772 aopPut (AOP (result), "a", offset--);
6774 reAdjustPreg (AOP (result));
6775 emitcode ("", "%05d$:", tlbl1->key + 100);
6776 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6779 freeAsmop (left, NULL, ic, TRUE);
6780 freeAsmop (result, NULL, ic, TRUE);
6783 /*-----------------------------------------------------------------*/
6784 /* genRightShift - generate code for right shifting */
6785 /*-----------------------------------------------------------------*/
6787 genRightShift (iCode * ic)
6789 operand *right, *left, *result;
6793 symbol *tlbl, *tlbl1;
6795 D(emitcode (";", "genRightShift"));
6797 /* if signed then we do it the hard way preserve the
6798 sign bit moving it inwards */
6799 retype = getSpec (operandType (IC_RESULT (ic)));
6801 if (!SPEC_USIGN (retype))
6803 genSignedRightShift (ic);
6807 /* signed & unsigned types are treated the same : i.e. the
6808 signed is NOT propagated inwards : quoting from the
6809 ANSI - standard : "for E1 >> E2, is equivalent to division
6810 by 2**E2 if unsigned or if it has a non-negative value,
6811 otherwise the result is implementation defined ", MY definition
6812 is that the sign does not get propagated */
6814 right = IC_RIGHT (ic);
6815 left = IC_LEFT (ic);
6816 result = IC_RESULT (ic);
6818 aopOp (right, ic, FALSE);
6820 /* if the shift count is known then do it
6821 as efficiently as possible */
6822 if (AOP_TYPE (right) == AOP_LIT)
6824 genRightShiftLiteral (left, right, result, ic, 0);
6828 /* shift count is unknown then we have to form
6829 a loop get the loop count in B : Note: we take
6830 only the lower order byte since shifting
6831 more that 32 bits make no sense anyway, ( the
6832 largest size of an object can be only 32 bits ) */
6834 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6835 emitcode ("inc", "b");
6836 freeAsmop (right, NULL, ic, TRUE);
6837 aopOp (left, ic, FALSE);
6838 aopOp (result, ic, FALSE);
6840 /* now move the left to the result if they are not the
6842 if (!sameRegs (AOP (left), AOP (result)) &&
6843 AOP_SIZE (result) > 1)
6846 size = AOP_SIZE (result);
6850 l = aopGet (AOP (left), offset, FALSE, TRUE);
6851 if (*l == '@' && IS_AOP_PREG (result))
6854 emitcode ("mov", "a,%s", l);
6855 aopPut (AOP (result), "a", offset);
6858 aopPut (AOP (result), l, offset);
6863 tlbl = newiTempLabel (NULL);
6864 tlbl1 = newiTempLabel (NULL);
6865 size = AOP_SIZE (result);
6868 /* if it is only one byte then */
6871 l = aopGet (AOP (left), 0, FALSE, FALSE);
6873 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6874 emitcode ("", "%05d$:", tlbl->key + 100);
6876 emitcode ("rrc", "a");
6877 emitcode ("", "%05d$:", tlbl1->key + 100);
6878 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6879 aopPut (AOP (result), "a", 0);
6883 reAdjustPreg (AOP (result));
6884 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6885 emitcode ("", "%05d$:", tlbl->key + 100);
6889 l = aopGet (AOP (result), offset, FALSE, FALSE);
6891 emitcode ("rrc", "a");
6892 aopPut (AOP (result), "a", offset--);
6894 reAdjustPreg (AOP (result));
6896 emitcode ("", "%05d$:", tlbl1->key + 100);
6897 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6900 freeAsmop (left, NULL, ic, TRUE);
6901 freeAsmop (result, NULL, ic, TRUE);
6904 /*-----------------------------------------------------------------*/
6905 /* genUnpackBits - generates code for unpacking bits */
6906 /*-----------------------------------------------------------------*/
6908 genUnpackBits (operand * result, char *rname, int ptype)
6916 D(emitcode (";", "genUnpackBits"));
6918 etype = getSpec (operandType (result));
6919 rsize = getSize (operandType (result));
6920 /* read the first byte */
6926 emitcode ("mov", "a,@%s", rname);
6930 emitcode ("movx", "a,@%s", rname);
6934 emitcode ("movx", "a,@dptr");
6938 emitcode ("clr", "a");
6939 emitcode ("movc", "a,@a+dptr");
6943 emitcode ("lcall", "__gptrget");
6947 rlen = SPEC_BLEN (etype);
6949 /* if we have bitdisplacement then it fits */
6950 /* into this byte completely or if length is */
6951 /* less than a byte */
6952 if ((shCnt = SPEC_BSTR (etype)) ||
6953 (SPEC_BLEN (etype) <= 8))
6956 /* shift right acc */
6959 emitcode ("anl", "a,#0x%02x",
6960 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6961 aopPut (AOP (result), "a", offset++);
6965 /* bit field did not fit in a byte */
6966 aopPut (AOP (result), "a", offset++);
6975 emitcode ("inc", "%s", rname);
6976 emitcode ("mov", "a,@%s", rname);
6980 emitcode ("inc", "%s", rname);
6981 emitcode ("movx", "a,@%s", rname);
6985 emitcode ("inc", "dptr");
6986 emitcode ("movx", "a,@dptr");
6990 emitcode ("clr", "a");
6991 emitcode ("inc", "dptr");
6992 emitcode ("movc", "a,@a+dptr");
6996 emitcode ("inc", "dptr");
6997 emitcode ("lcall", "__gptrget");
7002 /* if we are done */
7006 aopPut (AOP (result), "a", offset++);
7012 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7014 aopPut (AOP (result), "a", offset++);
7022 aopPut (AOP (result), zero, offset++);
7028 /*-----------------------------------------------------------------*/
7029 /* genDataPointerGet - generates code when ptr offset is known */
7030 /*-----------------------------------------------------------------*/
7032 genDataPointerGet (operand * left,
7038 int size, offset = 0;
7040 D(emitcode (";", "genDataPointerGet"));
7042 aopOp (result, ic, TRUE);
7044 /* get the string representation of the name */
7045 l = aopGet (AOP (left), 0, FALSE, TRUE);
7046 size = AOP_SIZE (result);
7050 sprintf (buffer, "(%s + %d)", l + 1, offset);
7052 sprintf (buffer, "%s", l + 1);
7053 aopPut (AOP (result), buffer, offset++);
7056 freeAsmop (left, NULL, ic, TRUE);
7057 freeAsmop (result, NULL, ic, TRUE);
7060 /*-----------------------------------------------------------------*/
7061 /* genNearPointerGet - emitcode for near pointer fetch */
7062 /*-----------------------------------------------------------------*/
7064 genNearPointerGet (operand * left,
7072 sym_link *rtype, *retype;
7073 sym_link *ltype = operandType (left);
7076 D(emitcode (";", "genNearPointerGet"));
7078 rtype = operandType (result);
7079 retype = getSpec (rtype);
7081 aopOp (left, ic, FALSE);
7083 /* if left is rematerialisable and
7084 result is not bit variable type and
7085 the left is pointer to data space i.e
7086 lower 128 bytes of space */
7087 if (AOP_TYPE (left) == AOP_IMMD &&
7088 !IS_BITVAR (retype) &&
7089 DCL_TYPE (ltype) == POINTER)
7091 genDataPointerGet (left, result, ic);
7095 /* if the value is already in a pointer register
7096 then don't need anything more */
7097 if (!AOP_INPREG (AOP (left)))
7099 /* otherwise get a free pointer register */
7101 preg = getFreePtr (ic, &aop, FALSE);
7102 emitcode ("mov", "%s,%s",
7104 aopGet (AOP (left), 0, FALSE, TRUE));
7108 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7110 //aopOp (result, ic, FALSE);
7111 aopOp (result, ic, result?TRUE:FALSE);
7113 /* if bitfield then unpack the bits */
7114 if (IS_BITVAR (retype))
7115 genUnpackBits (result, rname, POINTER);
7118 /* we have can just get the values */
7119 int size = AOP_SIZE (result);
7124 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7127 emitcode ("mov", "a,@%s", rname);
7128 aopPut (AOP (result), "a", offset);
7132 sprintf (buffer, "@%s", rname);
7133 aopPut (AOP (result), buffer, offset);
7137 emitcode ("inc", "%s", rname);
7141 /* now some housekeeping stuff */
7142 if (aop) /* we had to allocate for this iCode */
7144 if (pi) { /* post increment present */
7145 aopPut(AOP ( left ),rname,0);
7147 freeAsmop (NULL, aop, ic, TRUE);
7151 /* we did not allocate which means left
7152 already in a pointer register, then
7153 if size > 0 && this could be used again
7154 we have to point it back to where it
7156 if ((AOP_SIZE (result) > 1 &&
7157 !OP_SYMBOL (left)->remat &&
7158 (OP_SYMBOL (left)->liveTo > ic->seq ||
7162 int size = AOP_SIZE (result) - 1;
7164 emitcode ("dec", "%s", rname);
7169 freeAsmop (left, NULL, ic, TRUE);
7170 freeAsmop (result, NULL, ic, TRUE);
7171 if (pi) pi->generated = 1;
7174 /*-----------------------------------------------------------------*/
7175 /* genPagedPointerGet - emitcode for paged pointer fetch */
7176 /*-----------------------------------------------------------------*/
7178 genPagedPointerGet (operand * left,
7186 sym_link *rtype, *retype;
7188 D(emitcode (";", "genPagedPointerGet"));
7190 rtype = operandType (result);
7191 retype = getSpec (rtype);
7193 aopOp (left, ic, FALSE);
7195 /* if the value is already in a pointer register
7196 then don't need anything more */
7197 if (!AOP_INPREG (AOP (left)))
7199 /* otherwise get a free pointer register */
7201 preg = getFreePtr (ic, &aop, FALSE);
7202 emitcode ("mov", "%s,%s",
7204 aopGet (AOP (left), 0, FALSE, TRUE));
7208 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7210 aopOp (result, ic, FALSE);
7212 /* if bitfield then unpack the bits */
7213 if (IS_BITVAR (retype))
7214 genUnpackBits (result, rname, PPOINTER);
7217 /* we have can just get the values */
7218 int size = AOP_SIZE (result);
7224 emitcode ("movx", "a,@%s", rname);
7225 aopPut (AOP (result), "a", offset);
7230 emitcode ("inc", "%s", rname);
7234 /* now some housekeeping stuff */
7235 if (aop) /* we had to allocate for this iCode */
7237 if (pi) aopPut ( AOP (left), rname, 0);
7238 freeAsmop (NULL, aop, ic, TRUE);
7242 /* we did not allocate which means left
7243 already in a pointer register, then
7244 if size > 0 && this could be used again
7245 we have to point it back to where it
7247 if ((AOP_SIZE (result) > 1 &&
7248 !OP_SYMBOL (left)->remat &&
7249 (OP_SYMBOL (left)->liveTo > ic->seq ||
7253 int size = AOP_SIZE (result) - 1;
7255 emitcode ("dec", "%s", rname);
7260 freeAsmop (left, NULL, ic, TRUE);
7261 freeAsmop (result, NULL, ic, TRUE);
7262 if (pi) pi->generated = 1;
7266 /*-----------------------------------------------------------------*/
7267 /* genFarPointerGet - gget value from far space */
7268 /*-----------------------------------------------------------------*/
7270 genFarPointerGet (operand * left,
7271 operand * result, iCode * ic, iCode * pi)
7274 sym_link *retype = getSpec (operandType (result));
7276 D(emitcode (";", "genFarPointerGet"));
7278 aopOp (left, ic, FALSE);
7280 /* if the operand is already in dptr
7281 then we do nothing else we move the value to dptr */
7282 if (AOP_TYPE (left) != AOP_STR)
7284 /* if this is remateriazable */
7285 if (AOP_TYPE (left) == AOP_IMMD)
7286 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7288 { /* we need to get it byte by byte */
7289 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7290 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7293 /* so dptr know contains the address */
7294 aopOp (result, ic, FALSE);
7296 /* if bit then unpack */
7297 if (IS_BITVAR (retype))
7298 genUnpackBits (result, "dptr", FPOINTER);
7301 size = AOP_SIZE (result);
7306 emitcode ("movx", "a,@dptr");
7307 aopPut (AOP (result), "a", offset++);
7309 emitcode ("inc", "dptr");
7313 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7314 aopPut ( AOP (left), "dpl", 0);
7315 aopPut ( AOP (left), "dph", 1);
7318 freeAsmop (left, NULL, ic, TRUE);
7319 freeAsmop (result, NULL, ic, TRUE);
7322 /*-----------------------------------------------------------------*/
7323 /* genCodePointerGet - gget value from code space */
7324 /*-----------------------------------------------------------------*/
7326 genCodePointerGet (operand * left,
7327 operand * result, iCode * ic, iCode *pi)
7330 sym_link *retype = getSpec (operandType (result));
7332 D(emitcode (";", "genCodePointerGet"));
7334 aopOp (left, ic, FALSE);
7336 /* if the operand is already in dptr
7337 then we do nothing else we move the value to dptr */
7338 if (AOP_TYPE (left) != AOP_STR)
7340 /* if this is remateriazable */
7341 if (AOP_TYPE (left) == AOP_IMMD)
7342 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7344 { /* we need to get it byte by byte */
7345 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7346 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7349 /* so dptr know contains the address */
7350 aopOp (result, ic, FALSE);
7352 /* if bit then unpack */
7353 if (IS_BITVAR (retype))
7354 genUnpackBits (result, "dptr", CPOINTER);
7357 size = AOP_SIZE (result);
7362 emitcode ("clr", "a");
7363 emitcode ("movc", "a,@a+dptr");
7364 aopPut (AOP (result), "a", offset++);
7366 emitcode ("inc", "dptr");
7370 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7371 aopPut ( AOP (left), "dpl", 0);
7372 aopPut ( AOP (left), "dph", 1);
7375 freeAsmop (left, NULL, ic, TRUE);
7376 freeAsmop (result, NULL, ic, TRUE);
7379 /*-----------------------------------------------------------------*/
7380 /* genGenPointerGet - gget value from generic pointer space */
7381 /*-----------------------------------------------------------------*/
7383 genGenPointerGet (operand * left,
7384 operand * result, iCode * ic, iCode *pi)
7387 sym_link *retype = getSpec (operandType (result));
7389 D(emitcode (";", "genGenPointerGet"));
7391 aopOp (left, ic, FALSE);
7393 /* if the operand is already in dptr
7394 then we do nothing else we move the value to dptr */
7395 if (AOP_TYPE (left) != AOP_STR)
7397 /* if this is remateriazable */
7398 if (AOP_TYPE (left) == AOP_IMMD)
7400 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7401 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7402 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7404 emitcode ("mov", "b,#%d", pointerCode (retype));
7407 { /* we need to get it byte by byte */
7408 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7409 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7410 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7413 /* so dptr know contains the address */
7414 aopOp (result, ic, FALSE);
7416 /* if bit then unpack */
7417 if (IS_BITVAR (retype))
7418 genUnpackBits (result, "dptr", GPOINTER);
7421 size = AOP_SIZE (result);
7426 emitcode ("lcall", "__gptrget");
7427 aopPut (AOP (result), "a", offset++);
7429 emitcode ("inc", "dptr");
7433 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7434 aopPut ( AOP (left), "dpl", 0);
7435 aopPut ( AOP (left), "dph", 1);
7436 aopPut ( AOP (left), "b", 2);
7439 freeAsmop (left, NULL, ic, TRUE);
7440 freeAsmop (result, NULL, ic, TRUE);
7443 /*-----------------------------------------------------------------*/
7444 /* genPointerGet - generate code for pointer get */
7445 /*-----------------------------------------------------------------*/
7447 genPointerGet (iCode * ic, iCode *pi)
7449 operand *left, *result;
7450 sym_link *type, *etype;
7453 D(emitcode (";", "genPointerGet"));
7455 left = IC_LEFT (ic);
7456 result = IC_RESULT (ic);
7458 /* depending on the type of pointer we need to
7459 move it to the correct pointer register */
7460 type = operandType (left);
7461 etype = getSpec (type);
7462 /* if left is of type of pointer then it is simple */
7463 if (IS_PTR (type) && !IS_FUNC (type->next))
7464 p_type = DCL_TYPE (type);
7467 /* we have to go by the storage class */
7468 p_type = PTR_TYPE (SPEC_OCLS (etype));
7471 /* special case when cast remat */
7472 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7473 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7474 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7475 type = type = operandType (left);
7476 p_type = DCL_TYPE (type);
7478 /* now that we have the pointer type we assign
7479 the pointer values */
7485 genNearPointerGet (left, result, ic, pi);
7489 genPagedPointerGet (left, result, ic, pi);
7493 genFarPointerGet (left, result, ic, pi);
7497 genCodePointerGet (left, result, ic, pi);
7501 genGenPointerGet (left, result, ic, pi);
7507 /*-----------------------------------------------------------------*/
7508 /* genPackBits - generates code for packed bit storage */
7509 /*-----------------------------------------------------------------*/
7511 genPackBits (sym_link * etype,
7513 char *rname, int p_type)
7521 D(emitcode (";", "genPackBits"));
7523 blen = SPEC_BLEN (etype);
7524 bstr = SPEC_BSTR (etype);
7526 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7529 /* if the bit lenth is less than or */
7530 /* it exactly fits a byte then */
7531 if (SPEC_BLEN (etype) <= 8)
7533 shCount = SPEC_BSTR (etype);
7535 /* shift left acc */
7538 if (SPEC_BLEN (etype) < 8)
7539 { /* if smaller than a byte */
7545 emitcode ("mov", "b,a");
7546 emitcode ("mov", "a,@%s", rname);
7550 emitcode ("mov", "b,a");
7551 emitcode ("movx", "a,@dptr");
7555 emitcode ("push", "b");
7556 emitcode ("push", "acc");
7557 emitcode ("lcall", "__gptrget");
7558 emitcode ("pop", "b");
7562 emitcode ("anl", "a,#0x%02x", (unsigned char)
7563 ((unsigned char) (0xFF << (blen + bstr)) |
7564 (unsigned char) (0xFF >> (8 - bstr))));
7565 emitcode ("orl", "a,b");
7566 if (p_type == GPOINTER)
7567 emitcode ("pop", "b");
7574 emitcode ("mov", "@%s,a", rname);
7578 emitcode ("movx", "@dptr,a");
7582 emitcode ("lcall", "__gptrput");
7587 if (SPEC_BLEN (etype) <= 8)
7590 emitcode ("inc", "%s", rname);
7591 rLen = SPEC_BLEN (etype);
7593 /* now generate for lengths greater than one byte */
7597 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7609 emitcode ("mov", "@%s,a", rname);
7612 emitcode ("mov", "@%s,%s", rname, l);
7617 emitcode ("movx", "@dptr,a");
7622 emitcode ("lcall", "__gptrput");
7625 emitcode ("inc", "%s", rname);
7630 /* last last was not complete */
7633 /* save the byte & read byte */
7637 emitcode ("mov", "b,a");
7638 emitcode ("mov", "a,@%s", rname);
7642 emitcode ("mov", "b,a");
7643 emitcode ("movx", "a,@dptr");
7647 emitcode ("push", "b");
7648 emitcode ("push", "acc");
7649 emitcode ("lcall", "__gptrget");
7650 emitcode ("pop", "b");
7654 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7655 emitcode ("orl", "a,b");
7658 if (p_type == GPOINTER)
7659 emitcode ("pop", "b");
7665 emitcode ("mov", "@%s,a", rname);
7669 emitcode ("movx", "@dptr,a");
7673 emitcode ("lcall", "__gptrput");
7677 /*-----------------------------------------------------------------*/
7678 /* genDataPointerSet - remat pointer to data space */
7679 /*-----------------------------------------------------------------*/
7681 genDataPointerSet (operand * right,
7685 int size, offset = 0;
7686 char *l, buffer[256];
7688 D(emitcode (";", "genDataPointerSet"));
7690 aopOp (right, ic, FALSE);
7692 l = aopGet (AOP (result), 0, FALSE, TRUE);
7693 size = AOP_SIZE (right);
7697 sprintf (buffer, "(%s + %d)", l + 1, offset);
7699 sprintf (buffer, "%s", l + 1);
7700 emitcode ("mov", "%s,%s", buffer,
7701 aopGet (AOP (right), offset++, FALSE, FALSE));
7704 freeAsmop (right, NULL, ic, TRUE);
7705 freeAsmop (result, NULL, ic, TRUE);
7708 /*-----------------------------------------------------------------*/
7709 /* genNearPointerSet - emitcode for near pointer put */
7710 /*-----------------------------------------------------------------*/
7712 genNearPointerSet (operand * right,
7720 sym_link *retype, *letype;
7721 sym_link *ptype = operandType (result);
7723 D(emitcode (";", "genNearPointerSet"));
7725 retype = getSpec (operandType (right));
7726 letype = getSpec (ptype);
7727 aopOp (result, ic, FALSE);
7729 /* if the result is rematerializable &
7730 in data space & not a bit variable */
7731 if (AOP_TYPE (result) == AOP_IMMD &&
7732 DCL_TYPE (ptype) == POINTER &&
7733 !IS_BITVAR (retype) &&
7734 !IS_BITVAR (letype))
7736 genDataPointerSet (right, result, ic);
7740 /* if the value is already in a pointer register
7741 then don't need anything more */
7742 if (!AOP_INPREG (AOP (result)))
7745 //AOP_TYPE (result) == AOP_STK
7749 // Aha, it is a pointer, just in disguise.
7750 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7753 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7754 __FILE__, __LINE__);
7759 rname++; // skip the '@'.
7764 /* otherwise get a free pointer register */
7766 preg = getFreePtr (ic, &aop, FALSE);
7767 emitcode ("mov", "%s,%s",
7769 aopGet (AOP (result), 0, FALSE, TRUE));
7775 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7778 aopOp (right, ic, FALSE);
7780 /* if bitfield then unpack the bits */
7781 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7782 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7785 /* we have can just get the values */
7786 int size = AOP_SIZE (right);
7791 l = aopGet (AOP (right), offset, FALSE, TRUE);
7795 emitcode ("mov", "@%s,a", rname);
7798 emitcode ("mov", "@%s,%s", rname, l);
7800 emitcode ("inc", "%s", rname);
7805 /* now some housekeeping stuff */
7806 if (aop) /* we had to allocate for this iCode */
7808 if (pi) aopPut (AOP (result),rname,0);
7809 freeAsmop (NULL, aop, ic, TRUE);
7813 /* we did not allocate which means left
7814 already in a pointer register, then
7815 if size > 0 && this could be used again
7816 we have to point it back to where it
7818 if ((AOP_SIZE (right) > 1 &&
7819 !OP_SYMBOL (result)->remat &&
7820 (OP_SYMBOL (result)->liveTo > ic->seq ||
7824 int size = AOP_SIZE (right) - 1;
7826 emitcode ("dec", "%s", rname);
7831 if (pi) pi->generated = 1;
7832 freeAsmop (result, NULL, ic, TRUE);
7833 freeAsmop (right, NULL, ic, TRUE);
7836 /*-----------------------------------------------------------------*/
7837 /* genPagedPointerSet - emitcode for Paged pointer put */
7838 /*-----------------------------------------------------------------*/
7840 genPagedPointerSet (operand * right,
7848 sym_link *retype, *letype;
7850 D(emitcode (";", "genPagedPointerSet"));
7852 retype = getSpec (operandType (right));
7853 letype = getSpec (operandType (result));
7855 aopOp (result, ic, FALSE);
7857 /* if the value is already in a pointer register
7858 then don't need anything more */
7859 if (!AOP_INPREG (AOP (result)))
7861 /* otherwise get a free pointer register */
7863 preg = getFreePtr (ic, &aop, FALSE);
7864 emitcode ("mov", "%s,%s",
7866 aopGet (AOP (result), 0, FALSE, TRUE));
7870 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7872 aopOp (right, ic, FALSE);
7874 /* if bitfield then unpack the bits */
7875 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7876 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7879 /* we have can just get the values */
7880 int size = AOP_SIZE (right);
7885 l = aopGet (AOP (right), offset, FALSE, TRUE);
7888 emitcode ("movx", "@%s,a", rname);
7891 emitcode ("inc", "%s", rname);
7897 /* now some housekeeping stuff */
7898 if (aop) /* we had to allocate for this iCode */
7900 if (pi) aopPut (AOP (result),rname,0);
7901 freeAsmop (NULL, aop, ic, TRUE);
7905 /* we did not allocate which means left
7906 already in a pointer register, then
7907 if size > 0 && this could be used again
7908 we have to point it back to where it
7910 if (AOP_SIZE (right) > 1 &&
7911 !OP_SYMBOL (result)->remat &&
7912 (OP_SYMBOL (result)->liveTo > ic->seq ||
7915 int size = AOP_SIZE (right) - 1;
7917 emitcode ("dec", "%s", rname);
7922 if (pi) pi->generated = 1;
7923 freeAsmop (result, NULL, ic, TRUE);
7924 freeAsmop (right, NULL, ic, TRUE);
7929 /*-----------------------------------------------------------------*/
7930 /* genFarPointerSet - set value from far space */
7931 /*-----------------------------------------------------------------*/
7933 genFarPointerSet (operand * right,
7934 operand * result, iCode * ic, iCode * pi)
7937 sym_link *retype = getSpec (operandType (right));
7938 sym_link *letype = getSpec (operandType (result));
7940 D(emitcode (";", "genFarPointerSet"));
7942 aopOp (result, ic, FALSE);
7944 /* if the operand is already in dptr
7945 then we do nothing else we move the value to dptr */
7946 if (AOP_TYPE (result) != AOP_STR)
7948 /* if this is remateriazable */
7949 if (AOP_TYPE (result) == AOP_IMMD)
7950 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7952 { /* we need to get it byte by byte */
7953 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7954 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7957 /* so dptr know contains the address */
7958 aopOp (right, ic, FALSE);
7960 /* if bit then unpack */
7961 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7962 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7965 size = AOP_SIZE (right);
7970 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7972 emitcode ("movx", "@dptr,a");
7974 emitcode ("inc", "dptr");
7977 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7978 aopPut (AOP(result),"dpl",0);
7979 aopPut (AOP(result),"dph",1);
7982 freeAsmop (result, NULL, ic, TRUE);
7983 freeAsmop (right, NULL, ic, TRUE);
7986 /*-----------------------------------------------------------------*/
7987 /* genGenPointerSet - set value from generic pointer space */
7988 /*-----------------------------------------------------------------*/
7990 genGenPointerSet (operand * right,
7991 operand * result, iCode * ic, iCode * pi)
7994 sym_link *retype = getSpec (operandType (right));
7995 sym_link *letype = getSpec (operandType (result));
7997 D(emitcode (";", "genGenPointerSet"));
7999 aopOp (result, ic, FALSE);
8001 /* if the operand is already in dptr
8002 then we do nothing else we move the value to dptr */
8003 if (AOP_TYPE (result) != AOP_STR)
8005 /* if this is remateriazable */
8006 if (AOP_TYPE (result) == AOP_IMMD)
8008 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8009 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8010 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8012 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8015 { /* we need to get it byte by byte */
8016 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8017 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8018 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8021 /* so dptr know contains the address */
8022 aopOp (right, ic, FALSE);
8024 /* if bit then unpack */
8025 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8026 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8029 size = AOP_SIZE (right);
8034 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8036 emitcode ("lcall", "__gptrput");
8038 emitcode ("inc", "dptr");
8042 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8043 aopPut (AOP(result),"dpl",0);
8044 aopPut (AOP(result),"dph",1);
8047 freeAsmop (result, NULL, ic, TRUE);
8048 freeAsmop (right, NULL, ic, TRUE);
8051 /*-----------------------------------------------------------------*/
8052 /* genPointerSet - stores the value into a pointer location */
8053 /*-----------------------------------------------------------------*/
8055 genPointerSet (iCode * ic, iCode *pi)
8057 operand *right, *result;
8058 sym_link *type, *etype;
8061 D(emitcode (";", "genPointerSet"));
8063 right = IC_RIGHT (ic);
8064 result = IC_RESULT (ic);
8066 /* depending on the type of pointer we need to
8067 move it to the correct pointer register */
8068 type = operandType (result);
8069 etype = getSpec (type);
8070 /* if left is of type of pointer then it is simple */
8071 if (IS_PTR (type) && !IS_FUNC (type->next))
8073 p_type = DCL_TYPE (type);
8077 /* we have to go by the storage class */
8078 p_type = PTR_TYPE (SPEC_OCLS (etype));
8081 /* special case when cast remat */
8082 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8083 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8084 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8085 type = type = operandType (result);
8086 p_type = DCL_TYPE (type);
8088 /* now that we have the pointer type we assign
8089 the pointer values */
8095 genNearPointerSet (right, result, ic, pi);
8099 genPagedPointerSet (right, result, ic, pi);
8103 genFarPointerSet (right, result, ic, pi);
8107 genGenPointerSet (right, result, ic, pi);
8113 /*-----------------------------------------------------------------*/
8114 /* genIfx - generate code for Ifx statement */
8115 /*-----------------------------------------------------------------*/
8117 genIfx (iCode * ic, iCode * popIc)
8119 operand *cond = IC_COND (ic);
8122 D(emitcode (";", "genIfx"));
8124 aopOp (cond, ic, FALSE);
8126 /* get the value into acc */
8127 if (AOP_TYPE (cond) != AOP_CRY)
8131 /* the result is now in the accumulator */
8132 freeAsmop (cond, NULL, ic, TRUE);
8134 /* if there was something to be popped then do it */
8138 /* if the condition is a bit variable */
8139 if (isbit && IS_ITEMP (cond) &&
8141 genIfxJump (ic, SPIL_LOC (cond)->rname);
8142 else if (isbit && !IS_ITEMP (cond))
8143 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8145 genIfxJump (ic, "a");
8150 /*-----------------------------------------------------------------*/
8151 /* genAddrOf - generates code for address of */
8152 /*-----------------------------------------------------------------*/
8154 genAddrOf (iCode * ic)
8156 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8159 D(emitcode (";", "genAddrOf"));
8161 aopOp (IC_RESULT (ic), ic, FALSE);
8163 /* if the operand is on the stack then we
8164 need to get the stack offset of this
8168 /* if it has an offset then we need to compute
8172 emitcode ("mov", "a,_bp");
8173 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8174 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8178 /* we can just move _bp */
8179 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8181 /* fill the result with zero */
8182 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8187 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8193 /* object not on stack then we need the name */
8194 size = AOP_SIZE (IC_RESULT (ic));
8199 char s[SDCC_NAME_MAX];
8201 sprintf (s, "#(%s >> %d)",
8205 sprintf (s, "#%s", sym->rname);
8206 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8214 /*-----------------------------------------------------------------*/
8215 /* genFarFarAssign - assignment when both are in far space */
8216 /*-----------------------------------------------------------------*/
8218 genFarFarAssign (operand * result, operand * right, iCode * ic)
8220 int size = AOP_SIZE (right);
8224 D(emitcode (";", "genFarFarAssign"));
8226 /* first push the right side on to the stack */
8229 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8231 emitcode ("push", "acc");
8234 freeAsmop (right, NULL, ic, FALSE);
8235 /* now assign DPTR to result */
8236 aopOp (result, ic, FALSE);
8237 size = AOP_SIZE (result);
8240 emitcode ("pop", "acc");
8241 aopPut (AOP (result), "a", --offset);
8243 freeAsmop (result, NULL, ic, FALSE);
8247 /*-----------------------------------------------------------------*/
8248 /* genAssign - generate code for assignment */
8249 /*-----------------------------------------------------------------*/
8251 genAssign (iCode * ic)
8253 operand *result, *right;
8255 unsigned long lit = 0L;
8257 D(emitcode(";","genAssign"));
8259 result = IC_RESULT (ic);
8260 right = IC_RIGHT (ic);
8262 /* if they are the same */
8263 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8266 aopOp (right, ic, FALSE);
8268 /* special case both in far space */
8269 if (AOP_TYPE (right) == AOP_DPTR &&
8270 IS_TRUE_SYMOP (result) &&
8271 isOperandInFarSpace (result))
8274 genFarFarAssign (result, right, ic);
8278 aopOp (result, ic, TRUE);
8280 /* if they are the same registers */
8281 if (sameRegs (AOP (right), AOP (result)))
8284 /* if the result is a bit */
8285 if (AOP_TYPE (result) == AOP_CRY)
8288 /* if the right size is a literal then
8289 we know what the value is */
8290 if (AOP_TYPE (right) == AOP_LIT)
8292 if (((int) operandLitValue (right)))
8293 aopPut (AOP (result), one, 0);
8295 aopPut (AOP (result), zero, 0);
8299 /* the right is also a bit variable */
8300 if (AOP_TYPE (right) == AOP_CRY)
8302 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8303 aopPut (AOP (result), "c", 0);
8309 aopPut (AOP (result), "a", 0);
8313 /* bit variables done */
8315 size = AOP_SIZE (result);
8317 if (AOP_TYPE (right) == AOP_LIT)
8318 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8320 (AOP_TYPE (result) != AOP_REG) &&
8321 (AOP_TYPE (right) == AOP_LIT) &&
8322 !IS_FLOAT (operandType (right)) &&
8325 emitcode ("clr", "a");
8328 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8329 aopPut (AOP (result), "a", size);
8331 aopPut (AOP (result),
8332 aopGet (AOP (right), size, FALSE, FALSE),
8340 aopPut (AOP (result),
8341 aopGet (AOP (right), offset, FALSE, FALSE),
8348 freeAsmop (right, NULL, ic, TRUE);
8349 freeAsmop (result, NULL, ic, TRUE);
8352 /*-----------------------------------------------------------------*/
8353 /* genJumpTab - genrates code for jump table */
8354 /*-----------------------------------------------------------------*/
8356 genJumpTab (iCode * ic)
8361 D(emitcode (";", "genJumpTab"));
8363 aopOp (IC_JTCOND (ic), ic, FALSE);
8364 /* get the condition into accumulator */
8365 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8367 /* multiply by three */
8368 emitcode ("add", "a,acc");
8369 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8370 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8372 jtab = newiTempLabel (NULL);
8373 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8374 emitcode ("jmp", "@a+dptr");
8375 emitcode ("", "%05d$:", jtab->key + 100);
8376 /* now generate the jump labels */
8377 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8378 jtab = setNextItem (IC_JTLABELS (ic)))
8379 emitcode ("ljmp", "%05d$", jtab->key + 100);
8383 /*-----------------------------------------------------------------*/
8384 /* genCast - gen code for casting */
8385 /*-----------------------------------------------------------------*/
8387 genCast (iCode * ic)
8389 operand *result = IC_RESULT (ic);
8390 sym_link *ctype = operandType (IC_LEFT (ic));
8391 sym_link *rtype = operandType (IC_RIGHT (ic));
8392 operand *right = IC_RIGHT (ic);
8395 D(emitcode(";", "genCast"));
8397 /* if they are equivalent then do nothing */
8398 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8401 aopOp (right, ic, FALSE);
8402 aopOp (result, ic, FALSE);
8404 /* if the result is a bit */
8405 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8406 if (IS_BITVAR(OP_SYMBOL(result)->type))
8408 /* if the right size is a literal then
8409 we know what the value is */
8410 if (AOP_TYPE (right) == AOP_LIT)
8412 if (((int) operandLitValue (right)))
8413 aopPut (AOP (result), one, 0);
8415 aopPut (AOP (result), zero, 0);
8420 /* the right is also a bit variable */
8421 if (AOP_TYPE (right) == AOP_CRY)
8423 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8424 aopPut (AOP (result), "c", 0);
8430 aopPut (AOP (result), "a", 0);
8434 /* if they are the same size : or less */
8435 if (AOP_SIZE (result) <= AOP_SIZE (right))
8438 /* if they are in the same place */
8439 if (sameRegs (AOP (right), AOP (result)))
8442 /* if they in different places then copy */
8443 size = AOP_SIZE (result);
8447 aopPut (AOP (result),
8448 aopGet (AOP (right), offset, FALSE, FALSE),
8456 /* if the result is of type pointer */
8461 sym_link *type = operandType (right);
8462 sym_link *etype = getSpec (type);
8464 /* pointer to generic pointer */
8465 if (IS_GENPTR (ctype))
8470 p_type = DCL_TYPE (type);
8473 if (SPEC_SCLS(etype)==S_REGISTER) {
8474 // let's assume it is a generic pointer
8477 /* we have to go by the storage class */
8478 p_type = PTR_TYPE (SPEC_OCLS (etype));
8482 /* the first two bytes are known */
8483 size = GPTRSIZE - 1;
8487 aopPut (AOP (result),
8488 aopGet (AOP (right), offset, FALSE, FALSE),
8492 /* the last byte depending on type */
8508 case PPOINTER: // what the fck is this?
8513 /* this should never happen */
8514 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8515 "got unknown pointer type");
8518 aopPut (AOP (result), l, GPTRSIZE - 1);
8522 /* just copy the pointers */
8523 size = AOP_SIZE (result);
8527 aopPut (AOP (result),
8528 aopGet (AOP (right), offset, FALSE, FALSE),
8535 /* so we now know that the size of destination is greater
8536 than the size of the source */
8537 /* we move to result for the size of source */
8538 size = AOP_SIZE (right);
8542 aopPut (AOP (result),
8543 aopGet (AOP (right), offset, FALSE, FALSE),
8548 /* now depending on the sign of the source && destination */
8549 size = AOP_SIZE (result) - AOP_SIZE (right);
8550 /* if unsigned or not an integral type */
8551 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8554 aopPut (AOP (result), zero, offset++);
8558 /* we need to extend the sign :{ */
8559 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8562 emitcode ("rlc", "a");
8563 emitcode ("subb", "a,acc");
8565 aopPut (AOP (result), "a", offset++);
8568 /* we are done hurray !!!! */
8571 freeAsmop (right, NULL, ic, TRUE);
8572 freeAsmop (result, NULL, ic, TRUE);
8576 /*-----------------------------------------------------------------*/
8577 /* genDjnz - generate decrement & jump if not zero instrucion */
8578 /*-----------------------------------------------------------------*/
8580 genDjnz (iCode * ic, iCode * ifx)
8586 D(emitcode (";", "genDjnz"));
8588 /* if the if condition has a false label
8589 then we cannot save */
8593 /* if the minus is not of the form
8595 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8596 !IS_OP_LITERAL (IC_RIGHT (ic)))
8599 if (operandLitValue (IC_RIGHT (ic)) != 1)
8602 /* if the size of this greater than one then no
8604 if (getSize (operandType (IC_RESULT (ic))) > 1)
8607 /* otherwise we can save BIG */
8608 lbl = newiTempLabel (NULL);
8609 lbl1 = newiTempLabel (NULL);
8611 aopOp (IC_RESULT (ic), ic, FALSE);
8613 if (AOP_NEEDSACC(IC_RESULT(ic)))
8615 /* If the result is accessed indirectly via
8616 * the accumulator, we must explicitly write
8617 * it back after the decrement.
8619 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8621 if (strcmp(rByte, "a"))
8623 /* Something is hopelessly wrong */
8624 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8625 __FILE__, __LINE__);
8626 /* We can just give up; the generated code will be inefficient,
8629 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8632 emitcode ("dec", "%s", rByte);
8633 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8634 emitcode ("jnz", "%05d$", lbl->key + 100);
8636 else if (IS_AOP_PREG (IC_RESULT (ic)))
8638 emitcode ("dec", "%s",
8639 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8640 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8641 emitcode ("jnz", "%05d$", lbl->key + 100);
8645 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8648 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8649 emitcode ("", "%05d$:", lbl->key + 100);
8650 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8651 emitcode ("", "%05d$:", lbl1->key + 100);
8653 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8658 /*-----------------------------------------------------------------*/
8659 /* genReceive - generate code for a receive iCode */
8660 /*-----------------------------------------------------------------*/
8662 genReceive (iCode * ic)
8664 D(emitcode (";", "genReceive"));
8666 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8667 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8668 IS_TRUE_SYMOP (IC_RESULT (ic))))
8671 int size = getSize (operandType (IC_RESULT (ic)));
8672 int offset = fReturnSizeMCS51 - size;
8675 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8676 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8679 aopOp (IC_RESULT (ic), ic, FALSE);
8680 size = AOP_SIZE (IC_RESULT (ic));
8684 emitcode ("pop", "acc");
8685 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8692 aopOp (IC_RESULT (ic), ic, FALSE);
8694 assignResultValue (IC_RESULT (ic));
8697 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8700 /*-----------------------------------------------------------------*/
8701 /* gen51AggregateAssign - copy complete array's or structures */
8702 /*-----------------------------------------------------------------*/
8703 void gen51AggregateAssign(iCode *ic) {
8704 operand *left=IC_LEFT(ic);
8705 operand *right=IC_RIGHT(ic);
8706 char *fromName=OP_SYMBOL(right)->rname;
8707 char *toName=OP_SYMBOL(left)->rname;
8708 int fromSize=getSize(OP_SYMBOL(right)->type);
8709 int toSize=getSize(OP_SYMBOL(left)->type);
8712 D(emitcode (";", "gen51AggregateAssign"));
8714 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8715 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8716 // well, this code isn't used yet from anywhere else as for initialising
8717 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8721 if (fromSize!=toSize) {
8722 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8723 ic->filename, ic->lineno);
8728 // use the generic memcpy() for now
8729 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8730 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8731 emitcode ("mov", "a,#%s", fromName);
8732 emitcode ("movx", "@dptr,a");
8733 emitcode ("inc", "dptr");
8734 emitcode ("mov", "a,#(%s>>8)", fromName);
8735 emitcode ("movx", "@dptr,a");
8736 emitcode ("inc", "dptr");
8737 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8738 emitcode ("movx", "@dptr,a");
8739 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8740 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8741 emitcode ("movx", "@dptr,a");
8742 emitcode ("inc", "dptr");
8743 emitcode ("mov", "a,#(%d>>8)", count);
8744 emitcode ("movx", "@dptr,a");
8745 emitcode ("mov", "dptr,#%s", toName);
8746 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8747 emitcode ("lcall", "_memcpy");
8749 // more efficient, but will require the native_memcpy_cs2xs
8750 emitcode ("mov", "r0,#%s", fromName);
8751 emitcode ("mov", "r1,#(%s>>8)", fromName);
8752 emitcode ("mov", "r2,#%s", toName);
8753 emitcode ("mov", "r3,#(%s>>8)", toName);
8754 emitcode ("mov", "r4,#%d", count);
8755 emitcode ("mov", "r5,#(%d>>8)", count);
8756 emitcode ("lcall", "_native_memcpy_cs2xs");
8760 /*-----------------------------------------------------------------*/
8761 /* gen51Code - generate code for 8051 based controllers */
8762 /*-----------------------------------------------------------------*/
8764 gen51Code (iCode * lic)
8769 lineHead = lineCurr = NULL;
8771 /* print the allocation information */
8773 printAllocInfo (currFunc, codeOutFile);
8774 /* if debug information required */
8775 /* if (options.debug && currFunc) { */
8776 if (options.debug && currFunc)
8778 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8780 if (IS_STATIC (currFunc->etype))
8781 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8783 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8786 /* stack pointer name */
8787 if (options.useXstack)
8793 for (ic = lic; ic; ic = ic->next)
8796 if (cln != ic->lineno)
8801 emitcode ("", "C$%s$%d$%d$%d ==.",
8802 FileBaseName (ic->filename), ic->lineno,
8803 ic->level, ic->block);
8806 emitcode (";", "%s %d", ic->filename, ic->lineno);
8809 /* if the result is marked as
8810 spilt and rematerializable or code for
8811 this has already been generated then
8813 if (resultRemat (ic) || ic->generated)
8816 /* depending on the operation */
8836 /* IPOP happens only when trying to restore a
8837 spilt live range, if there is an ifx statement
8838 following this pop then the if statement might
8839 be using some of the registers being popped which
8840 would destory the contents of the register so
8841 we need to check for this condition and handle it */
8843 ic->next->op == IFX &&
8844 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8845 genIfx (ic->next, ic);
8863 genEndFunction (ic);
8883 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8900 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8904 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8911 /* note these two are xlated by algebraic equivalence
8912 during parsing SDCC.y */
8913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8914 "got '>=' or '<=' shouldn't have come here");
8918 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8930 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8934 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8938 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8965 case GET_VALUE_AT_ADDRESS:
8966 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8970 if (POINTER_SET (ic))
8971 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8997 addSet (&_G.sendSet, ic);
9001 gen51AggregateAssign(ic);
9010 /* now we are ready to call the
9011 peep hole optimizer */
9012 if (!options.nopeep)
9013 peepHole (&lineHead);
9015 /* now do the actual printing */
9016 printLine (lineHead, codeOutFile);