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 D(emitcode (";", "genPlusIncr"));
2740 /* will try to generate an increment */
2741 /* if the right side is not a literal
2743 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2746 /* if the literal value of the right hand side
2747 is greater than 4 then it is not worth it */
2748 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
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 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2888 symbol *lbl = newiTempLabel (NULL);
2889 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2890 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2891 emitcode ("cpl", "c");
2892 emitcode ("", "%05d$:", (lbl->key + 100));
2893 outBitC (IC_RESULT (ic));
2897 emitcode ("clr", "a");
2898 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2899 emitcode ("rlc", "a");
2900 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2901 emitcode ("addc", "a,#0x00");
2902 outAcc (IC_RESULT (ic));
2907 /* This is the original version of this code.
2909 * This is being kept around for reference,
2910 * because I am not entirely sure I got it right...
2913 adjustArithmeticResult (iCode * ic)
2915 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2916 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2917 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2918 aopPut (AOP (IC_RESULT (ic)),
2919 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2922 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2923 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2924 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2925 aopPut (AOP (IC_RESULT (ic)),
2926 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2929 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2930 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2931 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2932 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2933 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2936 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2937 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2941 /* This is the pure and virtuous version of this code.
2942 * I'm pretty certain it's right, but not enough to toss the old
2946 adjustArithmeticResult (iCode * ic)
2948 if (opIsGptr (IC_RESULT (ic)) &&
2949 opIsGptr (IC_LEFT (ic)) &&
2950 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2952 aopPut (AOP (IC_RESULT (ic)),
2953 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2957 if (opIsGptr (IC_RESULT (ic)) &&
2958 opIsGptr (IC_RIGHT (ic)) &&
2959 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2961 aopPut (AOP (IC_RESULT (ic)),
2962 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2966 if (opIsGptr (IC_RESULT (ic)) &&
2967 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2968 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2969 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2970 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2973 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2974 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2979 /*-----------------------------------------------------------------*/
2980 /* genPlus - generates code for addition */
2981 /*-----------------------------------------------------------------*/
2983 genPlus (iCode * ic)
2985 int size, offset = 0;
2987 /* special cases :- */
2989 D(emitcode (";", "genPlus"));
2991 aopOp (IC_LEFT (ic), ic, FALSE);
2992 aopOp (IC_RIGHT (ic), ic, FALSE);
2993 aopOp (IC_RESULT (ic), ic, TRUE);
2995 /* if literal, literal on the right or
2996 if left requires ACC or right is already
2998 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2999 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3000 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3002 operand *t = IC_RIGHT (ic);
3003 IC_RIGHT (ic) = IC_LEFT (ic);
3007 /* if both left & right are in bit
3009 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3010 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3016 /* if left in bit space & right literal */
3017 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3018 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3020 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3021 /* if result in bit space */
3022 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3024 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3025 emitcode ("cpl", "c");
3026 outBitC (IC_RESULT (ic));
3030 size = getDataSize (IC_RESULT (ic));
3033 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3034 emitcode ("addc", "a,#00");
3035 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3041 /* if I can do an increment instead
3042 of add then GOOD for ME */
3043 if (genPlusIncr (ic) == TRUE)
3046 size = getDataSize (IC_RESULT (ic));
3050 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3052 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3054 emitcode ("add", "a,%s",
3055 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3057 emitcode ("addc", "a,%s",
3058 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3062 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3064 emitcode ("add", "a,%s",
3065 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3067 emitcode ("addc", "a,%s",
3068 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3070 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3073 adjustArithmeticResult (ic);
3076 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3077 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3078 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3081 /*-----------------------------------------------------------------*/
3082 /* genMinusDec :- does subtraction with deccrement if possible */
3083 /*-----------------------------------------------------------------*/
3085 genMinusDec (iCode * ic)
3087 unsigned int icount;
3088 unsigned int size = getDataSize (IC_RESULT (ic));
3090 D(emitcode (";", "genMinusDec"));
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 /* if decrement 16 bits in register */
3104 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3112 /* If the next instruction is a goto and the goto target
3113 * is <= 10 instructions previous to this, we can generate
3114 * jumps straight to that target.
3116 if (ic->next && ic->next->op == GOTO
3117 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3118 && labelRange <= 10)
3120 emitcode (";", "tail decrement optimized");
3121 tlbl = IC_LABEL (ic->next);
3126 tlbl = newiTempLabel (NULL);
3130 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3131 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3132 IS_AOP_PREG (IC_RESULT (ic)))
3133 emitcode ("cjne", "%s,#0xff,%05d$"
3134 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3138 emitcode ("mov", "a,#0xff");
3139 emitcode ("cjne", "a,%s,%05d$"
3140 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3143 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3146 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3147 IS_AOP_PREG (IC_RESULT (ic)))
3148 emitcode ("cjne", "%s,#0xff,%05d$"
3149 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3153 emitcode ("cjne", "a,%s,%05d$"
3154 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3157 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3161 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3162 IS_AOP_PREG (IC_RESULT (ic)))
3163 emitcode ("cjne", "%s,#0xff,%05d$"
3164 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3168 emitcode ("cjne", "a,%s,%05d$"
3169 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3172 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3176 emitcode ("", "%05d$:", tlbl->key + 100);
3181 /* if the sizes are greater than 1 then we cannot */
3182 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3183 AOP_SIZE (IC_LEFT (ic)) > 1)
3186 /* we can if the aops of the left & result match or
3187 if they are in registers and the registers are the
3189 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3193 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3201 /*-----------------------------------------------------------------*/
3202 /* addSign - complete with sign */
3203 /*-----------------------------------------------------------------*/
3205 addSign (operand * result, int offset, int sign)
3207 int size = (getDataSize (result) - offset);
3212 emitcode ("rlc", "a");
3213 emitcode ("subb", "a,acc");
3215 aopPut (AOP (result), "a", offset++);
3219 aopPut (AOP (result), zero, offset++);
3223 /*-----------------------------------------------------------------*/
3224 /* genMinusBits - generates code for subtraction of two bits */
3225 /*-----------------------------------------------------------------*/
3227 genMinusBits (iCode * ic)
3229 symbol *lbl = newiTempLabel (NULL);
3230 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3232 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3233 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3234 emitcode ("cpl", "c");
3235 emitcode ("", "%05d$:", (lbl->key + 100));
3236 outBitC (IC_RESULT (ic));
3240 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3241 emitcode ("subb", "a,acc");
3242 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3243 emitcode ("inc", "a");
3244 emitcode ("", "%05d$:", (lbl->key + 100));
3245 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3246 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3250 /*-----------------------------------------------------------------*/
3251 /* genMinus - generates code for subtraction */
3252 /*-----------------------------------------------------------------*/
3254 genMinus (iCode * ic)
3256 int size, offset = 0;
3257 unsigned long lit = 0L;
3259 aopOp (IC_LEFT (ic), ic, FALSE);
3260 aopOp (IC_RIGHT (ic), ic, FALSE);
3261 aopOp (IC_RESULT (ic), ic, TRUE);
3263 /* special cases :- */
3264 /* if both left & right are in bit space */
3265 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3266 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3272 /* if I can do an decrement instead
3273 of subtract then GOOD for ME */
3274 if (genMinusDec (ic) == TRUE)
3277 size = getDataSize (IC_RESULT (ic));
3279 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3285 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3289 /* if literal, add a,#-lit, else normal subb */
3292 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3293 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3294 emitcode ("subb", "a,%s",
3295 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3298 /* first add without previous c */
3300 if (!size && lit==-1) {
3301 emitcode ("dec", "a");
3303 emitcode ("add", "a,#0x%02x",
3304 (unsigned int) (lit & 0x0FFL));
3307 emitcode ("addc", "a,#0x%02x",
3308 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3311 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3314 adjustArithmeticResult (ic);
3317 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3318 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3319 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3323 /*-----------------------------------------------------------------*/
3324 /* genMultbits :- multiplication of bits */
3325 /*-----------------------------------------------------------------*/
3327 genMultbits (operand * left,
3331 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3332 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3337 /*-----------------------------------------------------------------*/
3338 /* genMultOneByte : 8*8=8/16 bit multiplication */
3339 /*-----------------------------------------------------------------*/
3341 genMultOneByte (operand * left,
3345 sym_link *opetype = operandType (result);
3347 int size=AOP_SIZE(result);
3349 if (size<1 || size>2) {
3350 // this should never happen
3351 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3352 AOP_SIZE(result), __FILE__, lineno);
3356 /* (if two literals: the value is computed before) */
3357 /* if one literal, literal on the right */
3358 if (AOP_TYPE (left) == AOP_LIT)
3363 //emitcode (";", "swapped left and right");
3366 if (SPEC_USIGN(opetype)
3367 // ignore the sign of left and right, what else can we do?
3368 || (SPEC_USIGN(operandType(left)) &&
3369 SPEC_USIGN(operandType(right)))) {
3370 // just an unsigned 8*8=8/16 multiply
3371 //emitcode (";","unsigned");
3372 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3373 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3374 emitcode ("mul", "ab");
3375 aopPut (AOP (result), "a", 0);
3377 aopPut (AOP (result), "b", 1);
3382 // we have to do a signed multiply
3384 //emitcode (";", "signed");
3385 emitcode ("clr", "F0"); // reset sign flag
3386 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3388 lbl=newiTempLabel(NULL);
3389 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3390 // left side is negative, 8-bit two's complement, this fails for -128
3391 emitcode ("setb", "F0"); // set sign flag
3392 emitcode ("cpl", "a");
3393 emitcode ("inc", "a");
3395 emitcode ("", "%05d$:", lbl->key+100);
3398 if (AOP_TYPE(right)==AOP_LIT) {
3399 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3400 /* AND literal negative */
3402 emitcode ("cpl", "F0"); // complement sign flag
3403 emitcode ("mov", "b,#0x%02x", -val);
3405 emitcode ("mov", "b,#0x%02x", val);
3408 lbl=newiTempLabel(NULL);
3409 emitcode ("mov", "b,a");
3410 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3411 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3412 // right side is negative, 8-bit two's complement
3413 emitcode ("cpl", "F0"); // complement sign flag
3414 emitcode ("cpl", "a");
3415 emitcode ("inc", "a");
3416 emitcode ("", "%05d$:", lbl->key+100);
3418 emitcode ("mul", "ab");
3420 lbl=newiTempLabel(NULL);
3421 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3422 // only ONE op was negative, we have to do a 8/16-bit two's complement
3423 emitcode ("cpl", "a"); // lsb
3425 emitcode ("inc", "a");
3427 emitcode ("add", "a,#1");
3428 emitcode ("xch", "a,b");
3429 emitcode ("cpl", "a"); // msb
3430 emitcode ("addc", "a,#0");
3431 emitcode ("xch", "a,b");
3434 emitcode ("", "%05d$:", lbl->key+100);
3435 aopPut (AOP (result), "a", 0);
3437 aopPut (AOP (result), "b", 1);
3441 /*-----------------------------------------------------------------*/
3442 /* genMult - generates code for multiplication */
3443 /*-----------------------------------------------------------------*/
3445 genMult (iCode * ic)
3447 operand *left = IC_LEFT (ic);
3448 operand *right = IC_RIGHT (ic);
3449 operand *result = IC_RESULT (ic);
3451 /* assign the amsops */
3452 aopOp (left, ic, FALSE);
3453 aopOp (right, ic, FALSE);
3454 aopOp (result, ic, TRUE);
3456 /* special cases first */
3458 if (AOP_TYPE (left) == AOP_CRY &&
3459 AOP_TYPE (right) == AOP_CRY)
3461 genMultbits (left, right, result);
3465 /* if both are of size == 1 */
3466 #if 0 // one of them can be a sloc shared with the result
3467 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3469 if (getSize(operandType(left)) == 1 &&
3470 getSize(operandType(right)) == 1)
3473 genMultOneByte (left, right, result);
3477 /* should have been converted to function call */
3478 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3479 getSize(OP_SYMBOL(right)->type));
3483 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3484 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3485 freeAsmop (result, NULL, ic, TRUE);
3488 /*-----------------------------------------------------------------*/
3489 /* genDivbits :- division of bits */
3490 /*-----------------------------------------------------------------*/
3492 genDivbits (operand * left,
3499 /* the result must be bit */
3500 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3501 l = aopGet (AOP (left), 0, FALSE, FALSE);
3505 emitcode ("div", "ab");
3506 emitcode ("rrc", "a");
3507 aopPut (AOP (result), "c", 0);
3510 /*-----------------------------------------------------------------*/
3511 /* genDivOneByte : 8 bit division */
3512 /*-----------------------------------------------------------------*/
3514 genDivOneByte (operand * left,
3518 sym_link *opetype = operandType (result);
3523 size = AOP_SIZE (result) - 1;
3525 /* signed or unsigned */
3526 if (SPEC_USIGN (opetype))
3528 /* unsigned is easy */
3529 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3530 l = aopGet (AOP (left), 0, FALSE, FALSE);
3532 emitcode ("div", "ab");
3533 aopPut (AOP (result), "a", 0);
3535 aopPut (AOP (result), zero, offset++);
3539 /* signed is a little bit more difficult */
3541 /* save the signs of the operands */
3542 l = aopGet (AOP (left), 0, FALSE, FALSE);
3544 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3545 emitcode ("push", "acc"); /* save it on the stack */
3547 /* now sign adjust for both left & right */
3548 l = aopGet (AOP (right), 0, FALSE, FALSE);
3550 lbl = newiTempLabel (NULL);
3551 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3552 emitcode ("cpl", "a");
3553 emitcode ("inc", "a");
3554 emitcode ("", "%05d$:", (lbl->key + 100));
3555 emitcode ("mov", "b,a");
3557 /* sign adjust left side */
3558 l = aopGet (AOP (left), 0, FALSE, FALSE);
3561 lbl = newiTempLabel (NULL);
3562 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3563 emitcode ("cpl", "a");
3564 emitcode ("inc", "a");
3565 emitcode ("", "%05d$:", (lbl->key + 100));
3567 /* now the division */
3568 emitcode ("div", "ab");
3569 /* we are interested in the lower order
3571 emitcode ("mov", "b,a");
3572 lbl = newiTempLabel (NULL);
3573 emitcode ("pop", "acc");
3574 /* if there was an over flow we don't
3575 adjust the sign of the result */
3576 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3577 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3579 emitcode ("clr", "a");
3580 emitcode ("subb", "a,b");
3581 emitcode ("mov", "b,a");
3582 emitcode ("", "%05d$:", (lbl->key + 100));
3584 /* now we are done */
3585 aopPut (AOP (result), "b", 0);
3588 emitcode ("mov", "c,b.7");
3589 emitcode ("subb", "a,acc");
3592 aopPut (AOP (result), "a", offset++);
3596 /*-----------------------------------------------------------------*/
3597 /* genDiv - generates code for division */
3598 /*-----------------------------------------------------------------*/
3602 operand *left = IC_LEFT (ic);
3603 operand *right = IC_RIGHT (ic);
3604 operand *result = IC_RESULT (ic);
3606 /* assign the amsops */
3607 aopOp (left, ic, FALSE);
3608 aopOp (right, ic, FALSE);
3609 aopOp (result, ic, TRUE);
3611 /* special cases first */
3613 if (AOP_TYPE (left) == AOP_CRY &&
3614 AOP_TYPE (right) == AOP_CRY)
3616 genDivbits (left, right, result);
3620 /* if both are of size == 1 */
3621 if (AOP_SIZE (left) == 1 &&
3622 AOP_SIZE (right) == 1)
3624 genDivOneByte (left, right, result);
3628 /* should have been converted to function call */
3631 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3632 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3633 freeAsmop (result, NULL, ic, TRUE);
3636 /*-----------------------------------------------------------------*/
3637 /* genModbits :- modulus of bits */
3638 /*-----------------------------------------------------------------*/
3640 genModbits (operand * left,
3647 /* the result must be bit */
3648 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3649 l = aopGet (AOP (left), 0, FALSE, FALSE);
3653 emitcode ("div", "ab");
3654 emitcode ("mov", "a,b");
3655 emitcode ("rrc", "a");
3656 aopPut (AOP (result), "c", 0);
3659 /*-----------------------------------------------------------------*/
3660 /* genModOneByte : 8 bit modulus */
3661 /*-----------------------------------------------------------------*/
3663 genModOneByte (operand * left,
3667 sym_link *opetype = operandType (result);
3671 /* signed or unsigned */
3672 if (SPEC_USIGN (opetype))
3674 /* unsigned is easy */
3675 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3676 l = aopGet (AOP (left), 0, FALSE, FALSE);
3678 emitcode ("div", "ab");
3679 aopPut (AOP (result), "b", 0);
3683 /* signed is a little bit more difficult */
3685 /* save the signs of the operands */
3686 l = aopGet (AOP (left), 0, FALSE, FALSE);
3689 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3690 emitcode ("push", "acc"); /* save it on the stack */
3692 /* now sign adjust for both left & right */
3693 l = aopGet (AOP (right), 0, FALSE, FALSE);
3696 lbl = newiTempLabel (NULL);
3697 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3698 emitcode ("cpl", "a");
3699 emitcode ("inc", "a");
3700 emitcode ("", "%05d$:", (lbl->key + 100));
3701 emitcode ("mov", "b,a");
3703 /* sign adjust left side */
3704 l = aopGet (AOP (left), 0, FALSE, FALSE);
3707 lbl = newiTempLabel (NULL);
3708 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3709 emitcode ("cpl", "a");
3710 emitcode ("inc", "a");
3711 emitcode ("", "%05d$:", (lbl->key + 100));
3713 /* now the multiplication */
3714 emitcode ("div", "ab");
3715 /* we are interested in the lower order
3717 lbl = newiTempLabel (NULL);
3718 emitcode ("pop", "acc");
3719 /* if there was an over flow we don't
3720 adjust the sign of the result */
3721 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3722 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3724 emitcode ("clr", "a");
3725 emitcode ("subb", "a,b");
3726 emitcode ("mov", "b,a");
3727 emitcode ("", "%05d$:", (lbl->key + 100));
3729 /* now we are done */
3730 aopPut (AOP (result), "b", 0);
3734 /*-----------------------------------------------------------------*/
3735 /* genMod - generates code for division */
3736 /*-----------------------------------------------------------------*/
3740 operand *left = IC_LEFT (ic);
3741 operand *right = IC_RIGHT (ic);
3742 operand *result = IC_RESULT (ic);
3744 /* assign the amsops */
3745 aopOp (left, ic, FALSE);
3746 aopOp (right, ic, FALSE);
3747 aopOp (result, ic, TRUE);
3749 /* special cases first */
3751 if (AOP_TYPE (left) == AOP_CRY &&
3752 AOP_TYPE (right) == AOP_CRY)
3754 genModbits (left, right, result);
3758 /* if both are of size == 1 */
3759 if (AOP_SIZE (left) == 1 &&
3760 AOP_SIZE (right) == 1)
3762 genModOneByte (left, right, result);
3766 /* should have been converted to function call */
3770 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3772 freeAsmop (result, NULL, ic, TRUE);
3775 /*-----------------------------------------------------------------*/
3776 /* genIfxJump :- will create a jump depending on the ifx */
3777 /*-----------------------------------------------------------------*/
3779 genIfxJump (iCode * ic, char *jval)
3782 symbol *tlbl = newiTempLabel (NULL);
3785 /* if true label then we jump if condition
3789 jlbl = IC_TRUE (ic);
3790 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3791 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3795 /* false label is present */
3796 jlbl = IC_FALSE (ic);
3797 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3798 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3800 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3801 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3803 emitcode (inst, "%05d$", tlbl->key + 100);
3804 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3805 emitcode ("", "%05d$:", tlbl->key + 100);
3807 /* mark the icode as generated */
3811 /*-----------------------------------------------------------------*/
3812 /* genCmp :- greater or less than comparison */
3813 /*-----------------------------------------------------------------*/
3815 genCmp (operand * left, operand * right,
3816 operand * result, iCode * ifx, int sign, iCode *ic)
3818 int size, offset = 0;
3819 unsigned long lit = 0L;
3821 /* if left & right are bit variables */
3822 if (AOP_TYPE (left) == AOP_CRY &&
3823 AOP_TYPE (right) == AOP_CRY)
3825 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3826 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3830 /* subtract right from left if at the
3831 end the carry flag is set then we know that
3832 left is greater than right */
3833 size = max (AOP_SIZE (left), AOP_SIZE (right));
3835 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3836 if ((size == 1) && !sign &&
3837 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3839 symbol *lbl = newiTempLabel (NULL);
3840 emitcode ("cjne", "%s,%s,%05d$",
3841 aopGet (AOP (left), offset, FALSE, FALSE),
3842 aopGet (AOP (right), offset, FALSE, FALSE),
3844 emitcode ("", "%05d$:", lbl->key + 100);
3848 if (AOP_TYPE (right) == AOP_LIT)
3850 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3851 /* optimize if(x < 0) or if(x >= 0) */
3860 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3861 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3863 genIfxJump (ifx, "acc.7");
3867 emitcode ("rlc", "a");
3875 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3876 if (sign && size == 0)
3878 emitcode ("xrl", "a,#0x80");
3879 if (AOP_TYPE (right) == AOP_LIT)
3881 unsigned long lit = (unsigned long)
3882 floatFromVal (AOP (right)->aopu.aop_lit);
3883 emitcode ("subb", "a,#0x%02x",
3884 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3888 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3889 emitcode ("xrl", "b,#0x80");
3890 emitcode ("subb", "a,b");
3894 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3900 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3901 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3902 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3908 /* if the result is used in the next
3909 ifx conditional branch then generate
3910 code a little differently */
3912 genIfxJump (ifx, "c");
3915 /* leave the result in acc */
3919 /*-----------------------------------------------------------------*/
3920 /* genCmpGt :- greater than comparison */
3921 /*-----------------------------------------------------------------*/
3923 genCmpGt (iCode * ic, iCode * ifx)
3925 operand *left, *right, *result;
3926 sym_link *letype, *retype;
3929 left = IC_LEFT (ic);
3930 right = IC_RIGHT (ic);
3931 result = IC_RESULT (ic);
3933 letype = getSpec (operandType (left));
3934 retype = getSpec (operandType (right));
3935 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3936 /* assign the amsops */
3937 aopOp (left, ic, FALSE);
3938 aopOp (right, ic, FALSE);
3939 aopOp (result, ic, TRUE);
3941 genCmp (right, left, result, ifx, sign,ic);
3943 freeAsmop (result, NULL, ic, TRUE);
3946 /*-----------------------------------------------------------------*/
3947 /* genCmpLt - less than comparisons */
3948 /*-----------------------------------------------------------------*/
3950 genCmpLt (iCode * ic, iCode * ifx)
3952 operand *left, *right, *result;
3953 sym_link *letype, *retype;
3956 left = IC_LEFT (ic);
3957 right = IC_RIGHT (ic);
3958 result = IC_RESULT (ic);
3960 letype = getSpec (operandType (left));
3961 retype = getSpec (operandType (right));
3962 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3964 /* assign the amsops */
3965 aopOp (left, ic, FALSE);
3966 aopOp (right, ic, FALSE);
3967 aopOp (result, ic, TRUE);
3969 genCmp (left, right, result, ifx, sign,ic);
3971 freeAsmop (result, NULL, ic, TRUE);
3974 /*-----------------------------------------------------------------*/
3975 /* gencjneshort - compare and jump if not equal */
3976 /*-----------------------------------------------------------------*/
3978 gencjneshort (operand * left, operand * right, symbol * lbl)
3980 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3982 unsigned long lit = 0L;
3984 /* if the left side is a literal or
3985 if the right is in a pointer register and left
3987 if ((AOP_TYPE (left) == AOP_LIT) ||
3988 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3994 if (AOP_TYPE (right) == AOP_LIT)
3995 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3997 /* if the right side is a literal then anything goes */
3998 if (AOP_TYPE (right) == AOP_LIT &&
3999 AOP_TYPE (left) != AOP_DIR)
4003 emitcode ("cjne", "%s,%s,%05d$",
4004 aopGet (AOP (left), offset, FALSE, FALSE),
4005 aopGet (AOP (right), offset, FALSE, FALSE),
4011 /* if the right side is in a register or in direct space or
4012 if the left is a pointer register & right is not */
4013 else if (AOP_TYPE (right) == AOP_REG ||
4014 AOP_TYPE (right) == AOP_DIR ||
4015 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4016 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4020 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4021 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4022 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4023 emitcode ("jnz", "%05d$", lbl->key + 100);
4025 emitcode ("cjne", "a,%s,%05d$",
4026 aopGet (AOP (right), offset, FALSE, TRUE),
4033 /* right is a pointer reg need both a & b */
4036 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4037 if (strcmp (l, "b"))
4038 emitcode ("mov", "b,%s", l);
4039 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4040 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4046 /*-----------------------------------------------------------------*/
4047 /* gencjne - compare and jump if not equal */
4048 /*-----------------------------------------------------------------*/
4050 gencjne (operand * left, operand * right, symbol * lbl)
4052 symbol *tlbl = newiTempLabel (NULL);
4054 gencjneshort (left, right, lbl);
4056 emitcode ("mov", "a,%s", one);
4057 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4058 emitcode ("", "%05d$:", lbl->key + 100);
4059 emitcode ("clr", "a");
4060 emitcode ("", "%05d$:", tlbl->key + 100);
4063 /*-----------------------------------------------------------------*/
4064 /* genCmpEq - generates code for equal to */
4065 /*-----------------------------------------------------------------*/
4067 genCmpEq (iCode * ic, iCode * ifx)
4069 operand *left, *right, *result;
4071 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4072 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4073 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4075 /* if literal, literal on the right or
4076 if the right is in a pointer register and left
4078 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4079 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4081 operand *t = IC_RIGHT (ic);
4082 IC_RIGHT (ic) = IC_LEFT (ic);
4086 if (ifx && !AOP_SIZE (result))
4089 /* if they are both bit variables */
4090 if (AOP_TYPE (left) == AOP_CRY &&
4091 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4093 if (AOP_TYPE (right) == AOP_LIT)
4095 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4098 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4099 emitcode ("cpl", "c");
4103 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4107 emitcode ("clr", "c");
4109 /* AOP_TYPE(right) == AOP_CRY */
4113 symbol *lbl = newiTempLabel (NULL);
4114 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4115 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4116 emitcode ("cpl", "c");
4117 emitcode ("", "%05d$:", (lbl->key + 100));
4119 /* if true label then we jump if condition
4121 tlbl = newiTempLabel (NULL);
4124 emitcode ("jnc", "%05d$", tlbl->key + 100);
4125 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4129 emitcode ("jc", "%05d$", tlbl->key + 100);
4130 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4132 emitcode ("", "%05d$:", tlbl->key + 100);
4136 tlbl = newiTempLabel (NULL);
4137 gencjneshort (left, right, tlbl);
4140 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4141 emitcode ("", "%05d$:", tlbl->key + 100);
4145 symbol *lbl = newiTempLabel (NULL);
4146 emitcode ("sjmp", "%05d$", lbl->key + 100);
4147 emitcode ("", "%05d$:", tlbl->key + 100);
4148 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4149 emitcode ("", "%05d$:", lbl->key + 100);
4152 /* mark the icode as generated */
4157 /* if they are both bit variables */
4158 if (AOP_TYPE (left) == AOP_CRY &&
4159 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4161 if (AOP_TYPE (right) == AOP_LIT)
4163 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4166 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4167 emitcode ("cpl", "c");
4171 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4175 emitcode ("clr", "c");
4177 /* AOP_TYPE(right) == AOP_CRY */
4181 symbol *lbl = newiTempLabel (NULL);
4182 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4183 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4184 emitcode ("cpl", "c");
4185 emitcode ("", "%05d$:", (lbl->key + 100));
4188 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4195 genIfxJump (ifx, "c");
4198 /* if the result is used in an arithmetic operation
4199 then put the result in place */
4204 gencjne (left, right, newiTempLabel (NULL));
4205 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4207 aopPut (AOP (result), "a", 0);
4212 genIfxJump (ifx, "a");
4215 /* if the result is used in an arithmetic operation
4216 then put the result in place */
4217 if (AOP_TYPE (result) != AOP_CRY)
4219 /* leave the result in acc */
4223 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4224 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4225 freeAsmop (result, NULL, ic, TRUE);
4228 /*-----------------------------------------------------------------*/
4229 /* ifxForOp - returns the icode containing the ifx for operand */
4230 /*-----------------------------------------------------------------*/
4232 ifxForOp (operand * op, iCode * ic)
4234 /* if true symbol then needs to be assigned */
4235 if (IS_TRUE_SYMOP (op))
4238 /* if this has register type condition and
4239 the next instruction is ifx with the same operand
4240 and live to of the operand is upto the ifx only then */
4242 ic->next->op == IFX &&
4243 IC_COND (ic->next)->key == op->key &&
4244 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4250 /*-----------------------------------------------------------------*/
4251 /* hasInc - operand is incremented before any other use */
4252 /*-----------------------------------------------------------------*/
4254 hasInc (operand *op, iCode *ic)
4256 sym_link *type = operandType(op);
4257 sym_link *retype = getSpec (type);
4258 iCode *lic = ic->next;
4261 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4262 if (!IS_SYMOP(op)) return NULL;
4264 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4265 isize = getSize(type->next);
4267 /* if operand of the form op = op + <sizeof *op> */
4268 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4269 isOperandEqual(IC_RESULT(lic),op) &&
4270 isOperandLiteral(IC_RIGHT(lic)) &&
4271 operandLitValue(IC_RIGHT(lic)) == isize) {
4274 /* if the operand used or deffed */
4275 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4283 /*-----------------------------------------------------------------*/
4284 /* genAndOp - for && operation */
4285 /*-----------------------------------------------------------------*/
4287 genAndOp (iCode * ic)
4289 operand *left, *right, *result;
4292 /* note here that && operations that are in an
4293 if statement are taken away by backPatchLabels
4294 only those used in arthmetic operations remain */
4295 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4296 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4297 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4299 /* if both are bit variables */
4300 if (AOP_TYPE (left) == AOP_CRY &&
4301 AOP_TYPE (right) == AOP_CRY)
4303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4304 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4309 tlbl = newiTempLabel (NULL);
4311 emitcode ("jz", "%05d$", tlbl->key + 100);
4313 emitcode ("", "%05d$:", tlbl->key + 100);
4317 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4318 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4319 freeAsmop (result, NULL, ic, TRUE);
4323 /*-----------------------------------------------------------------*/
4324 /* genOrOp - for || operation */
4325 /*-----------------------------------------------------------------*/
4327 genOrOp (iCode * ic)
4329 operand *left, *right, *result;
4332 /* note here that || operations that are in an
4333 if statement are taken away by backPatchLabels
4334 only those used in arthmetic operations remain */
4335 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4336 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4337 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4339 /* if both are bit variables */
4340 if (AOP_TYPE (left) == AOP_CRY &&
4341 AOP_TYPE (right) == AOP_CRY)
4343 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4344 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4349 tlbl = newiTempLabel (NULL);
4351 emitcode ("jnz", "%05d$", tlbl->key + 100);
4353 emitcode ("", "%05d$:", tlbl->key + 100);
4357 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4358 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4359 freeAsmop (result, NULL, ic, TRUE);
4362 /*-----------------------------------------------------------------*/
4363 /* isLiteralBit - test if lit == 2^n */
4364 /*-----------------------------------------------------------------*/
4366 isLiteralBit (unsigned long lit)
4368 unsigned long pw[32] =
4369 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4370 0x100L, 0x200L, 0x400L, 0x800L,
4371 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4372 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4373 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4374 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4375 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4378 for (idx = 0; idx < 32; idx++)
4384 /*-----------------------------------------------------------------*/
4385 /* continueIfTrue - */
4386 /*-----------------------------------------------------------------*/
4388 continueIfTrue (iCode * ic)
4391 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4395 /*-----------------------------------------------------------------*/
4397 /*-----------------------------------------------------------------*/
4399 jumpIfTrue (iCode * ic)
4402 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4406 /*-----------------------------------------------------------------*/
4407 /* jmpTrueOrFalse - */
4408 /*-----------------------------------------------------------------*/
4410 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4412 // ugly but optimized by peephole
4415 symbol *nlbl = newiTempLabel (NULL);
4416 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4417 emitcode ("", "%05d$:", tlbl->key + 100);
4418 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4419 emitcode ("", "%05d$:", nlbl->key + 100);
4423 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4424 emitcode ("", "%05d$:", tlbl->key + 100);
4429 /*-----------------------------------------------------------------*/
4430 /* genAnd - code for and */
4431 /*-----------------------------------------------------------------*/
4433 genAnd (iCode * ic, iCode * ifx)
4435 operand *left, *right, *result;
4436 int size, offset = 0;
4437 unsigned long lit = 0L;
4441 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4442 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4443 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4446 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4448 AOP_TYPE (left), AOP_TYPE (right));
4449 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4451 AOP_SIZE (left), AOP_SIZE (right));
4454 /* if left is a literal & right is not then exchange them */
4455 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4456 AOP_NEEDSACC (left))
4458 operand *tmp = right;
4463 /* if result = right then exchange them */
4464 if (sameRegs (AOP (result), AOP (right)))
4466 operand *tmp = right;
4471 /* if right is bit then exchange them */
4472 if (AOP_TYPE (right) == AOP_CRY &&
4473 AOP_TYPE (left) != AOP_CRY)
4475 operand *tmp = right;
4479 if (AOP_TYPE (right) == AOP_LIT)
4480 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4482 size = AOP_SIZE (result);
4485 // result = bit & yy;
4486 if (AOP_TYPE (left) == AOP_CRY)
4488 // c = bit & literal;
4489 if (AOP_TYPE (right) == AOP_LIT)
4493 if (size && sameRegs (AOP (result), AOP (left)))
4496 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4501 if (size && (AOP_TYPE (result) == AOP_CRY))
4503 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4506 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4511 emitcode ("clr", "c");
4516 if (AOP_TYPE (right) == AOP_CRY)
4519 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4520 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4525 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4527 emitcode ("rrc", "a");
4528 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4536 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4537 genIfxJump (ifx, "c");
4541 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4542 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4543 if ((AOP_TYPE (right) == AOP_LIT) &&
4544 (AOP_TYPE (result) == AOP_CRY) &&
4545 (AOP_TYPE (left) != AOP_CRY))
4547 int posbit = isLiteralBit (lit);
4552 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4555 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4561 sprintf (buffer, "acc.%d", posbit & 0x07);
4562 genIfxJump (ifx, buffer);
4569 symbol *tlbl = newiTempLabel (NULL);
4570 int sizel = AOP_SIZE (left);
4572 emitcode ("setb", "c");
4575 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4577 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4579 if ((posbit = isLiteralBit (bytelit)) != 0)
4580 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4583 if (bytelit != 0x0FFL)
4584 emitcode ("anl", "a,%s",
4585 aopGet (AOP (right), offset, FALSE, TRUE));
4586 emitcode ("jnz", "%05d$", tlbl->key + 100);
4591 // bit = left & literal
4594 emitcode ("clr", "c");
4595 emitcode ("", "%05d$:", tlbl->key + 100);
4597 // if(left & literal)
4601 jmpTrueOrFalse (ifx, tlbl);
4609 /* if left is same as result */
4610 if (sameRegs (AOP (result), AOP (left)))
4612 for (; size--; offset++)
4614 if (AOP_TYPE (right) == AOP_LIT)
4616 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4618 else if (bytelit == 0)
4619 aopPut (AOP (result), zero, offset);
4620 else if (IS_AOP_PREG (result))
4622 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4623 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4624 aopPut (AOP (result), "a", offset);
4627 emitcode ("anl", "%s,%s",
4628 aopGet (AOP (left), offset, FALSE, TRUE),
4629 aopGet (AOP (right), offset, FALSE, FALSE));
4633 if (AOP_TYPE (left) == AOP_ACC)
4634 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4637 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4638 if (IS_AOP_PREG (result))
4640 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4641 aopPut (AOP (result), "a", offset);
4645 emitcode ("anl", "%s,a",
4646 aopGet (AOP (left), offset, FALSE, TRUE));
4653 // left & result in different registers
4654 if (AOP_TYPE (result) == AOP_CRY)
4657 // if(size), result in bit
4658 // if(!size && ifx), conditional oper: if(left & right)
4659 symbol *tlbl = newiTempLabel (NULL);
4660 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4662 emitcode ("setb", "c");
4665 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4666 emitcode ("anl", "a,%s",
4667 aopGet (AOP (right), offset, FALSE, FALSE));
4669 if (AOP_TYPE(left)==AOP_ACC) {
4670 emitcode("mov", "b,a");
4671 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4672 emitcode("anl", "a,b");
4674 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4675 emitcode ("anl", "a,%s",
4676 aopGet (AOP (left), offset, FALSE, FALSE));
4679 emitcode ("jnz", "%05d$", tlbl->key + 100);
4685 emitcode ("", "%05d$:", tlbl->key + 100);
4689 jmpTrueOrFalse (ifx, tlbl);
4693 for (; (size--); offset++)
4696 // result = left & right
4697 if (AOP_TYPE (right) == AOP_LIT)
4699 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4701 aopPut (AOP (result),
4702 aopGet (AOP (left), offset, FALSE, FALSE),
4706 else if (bytelit == 0)
4708 aopPut (AOP (result), zero, offset);
4712 // faster than result <- left, anl result,right
4713 // and better if result is SFR
4714 if (AOP_TYPE (left) == AOP_ACC)
4715 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4718 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4719 emitcode ("anl", "a,%s",
4720 aopGet (AOP (left), offset, FALSE, FALSE));
4722 aopPut (AOP (result), "a", offset);
4728 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4729 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4730 freeAsmop (result, NULL, ic, TRUE);
4733 /*-----------------------------------------------------------------*/
4734 /* genOr - code for or */
4735 /*-----------------------------------------------------------------*/
4737 genOr (iCode * ic, iCode * ifx)
4739 operand *left, *right, *result;
4740 int size, offset = 0;
4741 unsigned long lit = 0L;
4743 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4744 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4745 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4748 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4750 AOP_TYPE (left), AOP_TYPE (right));
4751 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4753 AOP_SIZE (left), AOP_SIZE (right));
4756 /* if left is a literal & right is not then exchange them */
4757 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4758 AOP_NEEDSACC (left))
4760 operand *tmp = right;
4765 /* if result = right then exchange them */
4766 if (sameRegs (AOP (result), AOP (right)))
4768 operand *tmp = right;
4773 /* if right is bit then exchange them */
4774 if (AOP_TYPE (right) == AOP_CRY &&
4775 AOP_TYPE (left) != AOP_CRY)
4777 operand *tmp = right;
4781 if (AOP_TYPE (right) == AOP_LIT)
4782 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4784 size = AOP_SIZE (result);
4788 if (AOP_TYPE (left) == AOP_CRY)
4790 if (AOP_TYPE (right) == AOP_LIT)
4792 // c = bit & literal;
4795 // lit != 0 => result = 1
4796 if (AOP_TYPE (result) == AOP_CRY)
4799 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4801 continueIfTrue (ifx);
4804 emitcode ("setb", "c");
4808 // lit == 0 => result = left
4809 if (size && sameRegs (AOP (result), AOP (left)))
4811 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4816 if (AOP_TYPE (right) == AOP_CRY)
4819 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4820 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4825 symbol *tlbl = newiTempLabel (NULL);
4826 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4827 emitcode ("setb", "c");
4828 emitcode ("jb", "%s,%05d$",
4829 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4831 emitcode ("jnz", "%05d$", tlbl->key + 100);
4832 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4834 jmpTrueOrFalse (ifx, tlbl);
4840 emitcode ("", "%05d$:", tlbl->key + 100);
4849 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4850 genIfxJump (ifx, "c");
4854 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4855 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4856 if ((AOP_TYPE (right) == AOP_LIT) &&
4857 (AOP_TYPE (result) == AOP_CRY) &&
4858 (AOP_TYPE (left) != AOP_CRY))
4864 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4866 continueIfTrue (ifx);
4871 // lit = 0, result = boolean(left)
4873 emitcode ("setb", "c");
4877 symbol *tlbl = newiTempLabel (NULL);
4878 emitcode ("jnz", "%05d$", tlbl->key + 100);
4880 emitcode ("", "%05d$:", tlbl->key + 100);
4884 genIfxJump (ifx, "a");
4892 /* if left is same as result */
4893 if (sameRegs (AOP (result), AOP (left)))
4895 for (; size--; offset++)
4897 if (AOP_TYPE (right) == AOP_LIT)
4899 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4901 else if (IS_AOP_PREG (left))
4903 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4904 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4905 aopPut (AOP (result), "a", offset);
4908 emitcode ("orl", "%s,%s",
4909 aopGet (AOP (left), offset, FALSE, TRUE),
4910 aopGet (AOP (right), offset, FALSE, FALSE));
4914 if (AOP_TYPE (left) == AOP_ACC)
4915 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4918 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4919 if (IS_AOP_PREG (left))
4921 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4922 aopPut (AOP (result), "a", offset);
4925 emitcode ("orl", "%s,a",
4926 aopGet (AOP (left), offset, FALSE, TRUE));
4933 // left & result in different registers
4934 if (AOP_TYPE (result) == AOP_CRY)
4937 // if(size), result in bit
4938 // if(!size && ifx), conditional oper: if(left | right)
4939 symbol *tlbl = newiTempLabel (NULL);
4940 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4942 emitcode ("setb", "c");
4945 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4946 emitcode ("orl", "a,%s",
4947 aopGet (AOP (right), offset, FALSE, FALSE));
4949 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4950 emitcode ("orl", "a,%s",
4951 aopGet (AOP (left), offset, FALSE, FALSE));
4953 emitcode ("jnz", "%05d$", tlbl->key + 100);
4959 emitcode ("", "%05d$:", tlbl->key + 100);
4963 jmpTrueOrFalse (ifx, tlbl);
4966 for (; (size--); offset++)
4969 // result = left & right
4970 if (AOP_TYPE (right) == AOP_LIT)
4972 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4974 aopPut (AOP (result),
4975 aopGet (AOP (left), offset, FALSE, FALSE),
4980 // faster than result <- left, anl result,right
4981 // and better if result is SFR
4982 if (AOP_TYPE (left) == AOP_ACC)
4983 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4986 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4987 emitcode ("orl", "a,%s",
4988 aopGet (AOP (left), offset, FALSE, FALSE));
4990 aopPut (AOP (result), "a", offset);
4995 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4996 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4997 freeAsmop (result, NULL, ic, TRUE);
5000 /*-----------------------------------------------------------------*/
5001 /* genXor - code for xclusive or */
5002 /*-----------------------------------------------------------------*/
5004 genXor (iCode * ic, iCode * ifx)
5006 operand *left, *right, *result;
5007 int size, offset = 0;
5008 unsigned long lit = 0L;
5010 D(emitcode (";", "genXor"));
5012 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5013 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5014 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5017 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5019 AOP_TYPE (left), AOP_TYPE (right));
5020 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5022 AOP_SIZE (left), AOP_SIZE (right));
5025 /* if left is a literal & right is not ||
5026 if left needs acc & right does not */
5027 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5028 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5030 operand *tmp = right;
5035 /* if result = right then exchange them */
5036 if (sameRegs (AOP (result), AOP (right)))
5038 operand *tmp = right;
5043 /* if right is bit then exchange them */
5044 if (AOP_TYPE (right) == AOP_CRY &&
5045 AOP_TYPE (left) != AOP_CRY)
5047 operand *tmp = right;
5051 if (AOP_TYPE (right) == AOP_LIT)
5052 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5054 size = AOP_SIZE (result);
5058 if (AOP_TYPE (left) == AOP_CRY)
5060 if (AOP_TYPE (right) == AOP_LIT)
5062 // c = bit & literal;
5065 // lit>>1 != 0 => result = 1
5066 if (AOP_TYPE (result) == AOP_CRY)
5069 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5071 continueIfTrue (ifx);
5074 emitcode ("setb", "c");
5081 // lit == 0, result = left
5082 if (size && sameRegs (AOP (result), AOP (left)))
5084 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5088 // lit == 1, result = not(left)
5089 if (size && sameRegs (AOP (result), AOP (left)))
5091 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5096 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5097 emitcode ("cpl", "c");
5106 symbol *tlbl = newiTempLabel (NULL);
5107 if (AOP_TYPE (right) == AOP_CRY)
5110 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5114 int sizer = AOP_SIZE (right);
5116 // if val>>1 != 0, result = 1
5117 emitcode ("setb", "c");
5120 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5122 // test the msb of the lsb
5123 emitcode ("anl", "a,#0xfe");
5124 emitcode ("jnz", "%05d$", tlbl->key + 100);
5128 emitcode ("rrc", "a");
5130 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5131 emitcode ("cpl", "c");
5132 emitcode ("", "%05d$:", (tlbl->key + 100));
5139 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5140 genIfxJump (ifx, "c");
5144 if (sameRegs (AOP (result), AOP (left)))
5146 /* if left is same as result */
5147 for (; size--; offset++)
5149 if (AOP_TYPE (right) == AOP_LIT)
5151 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5153 else if (IS_AOP_PREG (left))
5155 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5156 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5157 aopPut (AOP (result), "a", offset);
5160 emitcode ("xrl", "%s,%s",
5161 aopGet (AOP (left), offset, FALSE, TRUE),
5162 aopGet (AOP (right), offset, FALSE, FALSE));
5166 if (AOP_TYPE (left) == AOP_ACC)
5167 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5170 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5171 if (IS_AOP_PREG (left))
5173 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5174 aopPut (AOP (result), "a", offset);
5177 emitcode ("xrl", "%s,a",
5178 aopGet (AOP (left), offset, FALSE, TRUE));
5185 // left & result in different registers
5186 if (AOP_TYPE (result) == AOP_CRY)
5189 // if(size), result in bit
5190 // if(!size && ifx), conditional oper: if(left ^ right)
5191 symbol *tlbl = newiTempLabel (NULL);
5192 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5194 emitcode ("setb", "c");
5197 if ((AOP_TYPE (right) == AOP_LIT) &&
5198 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5200 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5204 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5205 emitcode ("xrl", "a,%s",
5206 aopGet (AOP (right), offset, FALSE, FALSE));
5208 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5209 emitcode ("xrl", "a,%s",
5210 aopGet (AOP (left), offset, FALSE, FALSE));
5213 emitcode ("jnz", "%05d$", tlbl->key + 100);
5219 emitcode ("", "%05d$:", tlbl->key + 100);
5223 jmpTrueOrFalse (ifx, tlbl);
5226 for (; (size--); offset++)
5229 // result = left & right
5230 if (AOP_TYPE (right) == AOP_LIT)
5232 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5234 aopPut (AOP (result),
5235 aopGet (AOP (left), offset, FALSE, FALSE),
5240 // faster than result <- left, anl result,right
5241 // and better if result is SFR
5242 if (AOP_TYPE (left) == AOP_ACC)
5243 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5246 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5247 emitcode ("xrl", "a,%s",
5248 aopGet (AOP (left), offset, FALSE, TRUE));
5250 aopPut (AOP (result), "a", offset);
5255 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5256 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5257 freeAsmop (result, NULL, ic, TRUE);
5260 /*-----------------------------------------------------------------*/
5261 /* genInline - write the inline code out */
5262 /*-----------------------------------------------------------------*/
5264 genInline (iCode * ic)
5266 char *buffer, *bp, *bp1;
5268 D(emitcode (";", "genInline"));
5270 _G.inLine += (!options.asmpeep);
5272 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5273 strcpy (buffer, IC_INLINE (ic));
5275 /* emit each line as a code */
5300 /* emitcode("",buffer); */
5301 _G.inLine -= (!options.asmpeep);
5304 /*-----------------------------------------------------------------*/
5305 /* genRRC - rotate right with carry */
5306 /*-----------------------------------------------------------------*/
5310 operand *left, *result;
5311 int size, offset = 0;
5314 D(emitcode (";", "genRRC"));
5316 /* rotate right with carry */
5317 left = IC_LEFT (ic);
5318 result = IC_RESULT (ic);
5319 aopOp (left, ic, FALSE);
5320 aopOp (result, ic, FALSE);
5322 /* move it to the result */
5323 size = AOP_SIZE (result);
5325 if (size == 1) { /* special case for 1 byte */
5326 l = aopGet (AOP (left), offset, FALSE, FALSE);
5328 emitcode ("rr", "a");
5334 l = aopGet (AOP (left), offset, FALSE, FALSE);
5336 emitcode ("rrc", "a");
5337 if (AOP_SIZE (result) > 1)
5338 aopPut (AOP (result), "a", offset--);
5340 /* now we need to put the carry into the
5341 highest order byte of the result */
5342 if (AOP_SIZE (result) > 1)
5344 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5347 emitcode ("mov", "acc.7,c");
5349 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5350 freeAsmop (left, NULL, ic, TRUE);
5351 freeAsmop (result, NULL, ic, TRUE);
5354 /*-----------------------------------------------------------------*/
5355 /* genRLC - generate code for rotate left with carry */
5356 /*-----------------------------------------------------------------*/
5360 operand *left, *result;
5361 int size, offset = 0;
5364 D(emitcode (";", "genRLC"));
5366 /* rotate right with carry */
5367 left = IC_LEFT (ic);
5368 result = IC_RESULT (ic);
5369 aopOp (left, ic, FALSE);
5370 aopOp (result, ic, FALSE);
5372 /* move it to the result */
5373 size = AOP_SIZE (result);
5377 l = aopGet (AOP (left), offset, FALSE, FALSE);
5379 if (size == 0) { /* special case for 1 byte */
5383 emitcode ("add", "a,acc");
5384 if (AOP_SIZE (result) > 1)
5385 aopPut (AOP (result), "a", offset++);
5388 l = aopGet (AOP (left), offset, FALSE, FALSE);
5390 emitcode ("rlc", "a");
5391 if (AOP_SIZE (result) > 1)
5392 aopPut (AOP (result), "a", offset++);
5395 /* now we need to put the carry into the
5396 highest order byte of the result */
5397 if (AOP_SIZE (result) > 1)
5399 l = aopGet (AOP (result), 0, FALSE, FALSE);
5402 emitcode ("mov", "acc.0,c");
5404 aopPut (AOP (result), "a", 0);
5405 freeAsmop (left, NULL, ic, TRUE);
5406 freeAsmop (result, NULL, ic, TRUE);
5409 /*-----------------------------------------------------------------*/
5410 /* genGetHbit - generates code get highest order bit */
5411 /*-----------------------------------------------------------------*/
5413 genGetHbit (iCode * ic)
5415 operand *left, *result;
5417 D(emitcode (";", "genGetHbit"));
5419 left = IC_LEFT (ic);
5420 result = IC_RESULT (ic);
5421 aopOp (left, ic, FALSE);
5422 aopOp (result, ic, FALSE);
5424 /* get the highest order byte into a */
5425 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5426 if (AOP_TYPE (result) == AOP_CRY)
5428 emitcode ("rlc", "a");
5433 emitcode ("rl", "a");
5434 emitcode ("anl", "a,#0x01");
5439 freeAsmop (left, NULL, ic, TRUE);
5440 freeAsmop (result, NULL, ic, TRUE);
5443 /*-----------------------------------------------------------------*/
5444 /* AccRol - rotate left accumulator by known count */
5445 /*-----------------------------------------------------------------*/
5447 AccRol (int shCount)
5449 shCount &= 0x0007; // shCount : 0..7
5456 emitcode ("rl", "a");
5459 emitcode ("rl", "a");
5460 emitcode ("rl", "a");
5463 emitcode ("swap", "a");
5464 emitcode ("rr", "a");
5467 emitcode ("swap", "a");
5470 emitcode ("swap", "a");
5471 emitcode ("rl", "a");
5474 emitcode ("rr", "a");
5475 emitcode ("rr", "a");
5478 emitcode ("rr", "a");
5483 /*-----------------------------------------------------------------*/
5484 /* AccLsh - left shift accumulator by known count */
5485 /*-----------------------------------------------------------------*/
5487 AccLsh (int shCount)
5492 emitcode ("add", "a,acc");
5493 else if (shCount == 2)
5495 emitcode ("add", "a,acc");
5496 emitcode ("add", "a,acc");
5500 /* rotate left accumulator */
5502 /* and kill the lower order bits */
5503 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5508 /*-----------------------------------------------------------------*/
5509 /* AccRsh - right shift accumulator by known count */
5510 /*-----------------------------------------------------------------*/
5512 AccRsh (int shCount)
5519 emitcode ("rrc", "a");
5523 /* rotate right accumulator */
5524 AccRol (8 - shCount);
5525 /* and kill the higher order bits */
5526 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5531 /*-----------------------------------------------------------------*/
5532 /* AccSRsh - signed right shift accumulator by known count */
5533 /*-----------------------------------------------------------------*/
5535 AccSRsh (int shCount)
5542 emitcode ("mov", "c,acc.7");
5543 emitcode ("rrc", "a");
5545 else if (shCount == 2)
5547 emitcode ("mov", "c,acc.7");
5548 emitcode ("rrc", "a");
5549 emitcode ("mov", "c,acc.7");
5550 emitcode ("rrc", "a");
5554 tlbl = newiTempLabel (NULL);
5555 /* rotate right accumulator */
5556 AccRol (8 - shCount);
5557 /* and kill the higher order bits */
5558 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5559 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5560 emitcode ("orl", "a,#0x%02x",
5561 (unsigned char) ~SRMask[shCount]);
5562 emitcode ("", "%05d$:", tlbl->key + 100);
5567 /*-----------------------------------------------------------------*/
5568 /* shiftR1Left2Result - shift right one byte from left to result */
5569 /*-----------------------------------------------------------------*/
5571 shiftR1Left2Result (operand * left, int offl,
5572 operand * result, int offr,
5573 int shCount, int sign)
5575 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5576 /* shift right accumulator */
5581 aopPut (AOP (result), "a", offr);
5584 /*-----------------------------------------------------------------*/
5585 /* shiftL1Left2Result - shift left one byte from left to result */
5586 /*-----------------------------------------------------------------*/
5588 shiftL1Left2Result (operand * left, int offl,
5589 operand * result, int offr, int shCount)
5592 l = aopGet (AOP (left), offl, FALSE, FALSE);
5594 /* shift left accumulator */
5596 aopPut (AOP (result), "a", offr);
5599 /*-----------------------------------------------------------------*/
5600 /* movLeft2Result - move byte from left to result */
5601 /*-----------------------------------------------------------------*/
5603 movLeft2Result (operand * left, int offl,
5604 operand * result, int offr, int sign)
5607 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5609 l = aopGet (AOP (left), offl, FALSE, FALSE);
5611 if (*l == '@' && (IS_AOP_PREG (result)))
5613 emitcode ("mov", "a,%s", l);
5614 aopPut (AOP (result), "a", offr);
5619 aopPut (AOP (result), l, offr);
5622 /* MSB sign in acc.7 ! */
5623 if (getDataSize (left) == offl + 1)
5625 emitcode ("mov", "a,%s", l);
5626 aopPut (AOP (result), "a", offr);
5633 /*-----------------------------------------------------------------*/
5634 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5635 /*-----------------------------------------------------------------*/
5639 emitcode ("rrc", "a");
5640 emitcode ("xch", "a,%s", x);
5641 emitcode ("rrc", "a");
5642 emitcode ("xch", "a,%s", x);
5645 /*-----------------------------------------------------------------*/
5646 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5647 /*-----------------------------------------------------------------*/
5651 emitcode ("xch", "a,%s", x);
5652 emitcode ("rlc", "a");
5653 emitcode ("xch", "a,%s", x);
5654 emitcode ("rlc", "a");
5657 /*-----------------------------------------------------------------*/
5658 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5659 /*-----------------------------------------------------------------*/
5663 emitcode ("xch", "a,%s", x);
5664 emitcode ("add", "a,acc");
5665 emitcode ("xch", "a,%s", x);
5666 emitcode ("rlc", "a");
5669 /*-----------------------------------------------------------------*/
5670 /* AccAXLsh - left shift a:x by known count (0..7) */
5671 /*-----------------------------------------------------------------*/
5673 AccAXLsh (char *x, int shCount)
5688 case 5: // AAAAABBB:CCCCCDDD
5690 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5692 emitcode ("anl", "a,#0x%02x",
5693 SLMask[shCount]); // BBB00000:CCCCCDDD
5695 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5697 AccRol (shCount); // DDDCCCCC:BBB00000
5699 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5701 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5703 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5705 emitcode ("anl", "a,#0x%02x",
5706 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5708 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5710 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5713 case 6: // AAAAAABB:CCCCCCDD
5714 emitcode ("anl", "a,#0x%02x",
5715 SRMask[shCount]); // 000000BB:CCCCCCDD
5716 emitcode ("mov", "c,acc.0"); // c = B
5717 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5719 AccAXRrl1 (x); // BCCCCCCD:D000000B
5720 AccAXRrl1 (x); // BBCCCCCC:DD000000
5722 emitcode("rrc","a");
5723 emitcode("xch","a,%s", x);
5724 emitcode("rrc","a");
5725 emitcode("mov","c,acc.0"); //<< get correct bit
5726 emitcode("xch","a,%s", x);
5728 emitcode("rrc","a");
5729 emitcode("xch","a,%s", x);
5730 emitcode("rrc","a");
5731 emitcode("xch","a,%s", x);
5734 case 7: // a:x <<= 7
5736 emitcode ("anl", "a,#0x%02x",
5737 SRMask[shCount]); // 0000000B:CCCCCCCD
5739 emitcode ("mov", "c,acc.0"); // c = B
5741 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5743 AccAXRrl1 (x); // BCCCCCCC:D0000000
5751 /*-----------------------------------------------------------------*/
5752 /* AccAXRsh - right shift a:x known count (0..7) */
5753 /*-----------------------------------------------------------------*/
5755 AccAXRsh (char *x, int shCount)
5763 AccAXRrl1 (x); // 0->a:x
5768 AccAXRrl1 (x); // 0->a:x
5771 AccAXRrl1 (x); // 0->a:x
5776 case 5: // AAAAABBB:CCCCCDDD = a:x
5778 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5780 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5782 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5784 emitcode ("anl", "a,#0x%02x",
5785 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5787 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5789 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5791 emitcode ("anl", "a,#0x%02x",
5792 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5794 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5796 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5798 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5801 case 6: // AABBBBBB:CCDDDDDD
5803 emitcode ("mov", "c,acc.7");
5804 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5806 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5808 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5810 emitcode ("anl", "a,#0x%02x",
5811 SRMask[shCount]); // 000000AA:BBBBBBCC
5814 case 7: // ABBBBBBB:CDDDDDDD
5816 emitcode ("mov", "c,acc.7"); // c = A
5818 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5820 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5822 emitcode ("anl", "a,#0x%02x",
5823 SRMask[shCount]); // 0000000A:BBBBBBBC
5831 /*-----------------------------------------------------------------*/
5832 /* AccAXRshS - right shift signed a:x known count (0..7) */
5833 /*-----------------------------------------------------------------*/
5835 AccAXRshS (char *x, int shCount)
5843 emitcode ("mov", "c,acc.7");
5844 AccAXRrl1 (x); // s->a:x
5848 emitcode ("mov", "c,acc.7");
5849 AccAXRrl1 (x); // s->a:x
5851 emitcode ("mov", "c,acc.7");
5852 AccAXRrl1 (x); // s->a:x
5857 case 5: // AAAAABBB:CCCCCDDD = a:x
5859 tlbl = newiTempLabel (NULL);
5860 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5862 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5864 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5866 emitcode ("anl", "a,#0x%02x",
5867 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5869 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5871 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5873 emitcode ("anl", "a,#0x%02x",
5874 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5876 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5878 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5880 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5882 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5883 emitcode ("orl", "a,#0x%02x",
5884 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5886 emitcode ("", "%05d$:", tlbl->key + 100);
5887 break; // SSSSAAAA:BBBCCCCC
5889 case 6: // AABBBBBB:CCDDDDDD
5891 tlbl = newiTempLabel (NULL);
5892 emitcode ("mov", "c,acc.7");
5893 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5895 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5897 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5899 emitcode ("anl", "a,#0x%02x",
5900 SRMask[shCount]); // 000000AA:BBBBBBCC
5902 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5903 emitcode ("orl", "a,#0x%02x",
5904 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5906 emitcode ("", "%05d$:", tlbl->key + 100);
5908 case 7: // ABBBBBBB:CDDDDDDD
5910 tlbl = newiTempLabel (NULL);
5911 emitcode ("mov", "c,acc.7"); // c = A
5913 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5915 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5917 emitcode ("anl", "a,#0x%02x",
5918 SRMask[shCount]); // 0000000A:BBBBBBBC
5920 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5921 emitcode ("orl", "a,#0x%02x",
5922 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5924 emitcode ("", "%05d$:", tlbl->key + 100);
5931 /*-----------------------------------------------------------------*/
5932 /* shiftL2Left2Result - shift left two bytes from left to result */
5933 /*-----------------------------------------------------------------*/
5935 shiftL2Left2Result (operand * left, int offl,
5936 operand * result, int offr, int shCount)
5938 if (sameRegs (AOP (result), AOP (left)) &&
5939 ((offl + MSB16) == offr))
5941 /* don't crash result[offr] */
5942 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5943 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5947 movLeft2Result (left, offl, result, offr, 0);
5948 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5950 /* ax << shCount (x = lsb(result)) */
5951 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5952 aopPut (AOP (result), "a", offr + MSB16);
5956 /*-----------------------------------------------------------------*/
5957 /* shiftR2Left2Result - shift right two bytes from left to result */
5958 /*-----------------------------------------------------------------*/
5960 shiftR2Left2Result (operand * left, int offl,
5961 operand * result, int offr,
5962 int shCount, int sign)
5964 if (sameRegs (AOP (result), AOP (left)) &&
5965 ((offl + MSB16) == offr))
5967 /* don't crash result[offr] */
5968 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5969 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5973 movLeft2Result (left, offl, result, offr, 0);
5974 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5976 /* a:x >> shCount (x = lsb(result)) */
5978 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5980 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5981 if (getDataSize (result) > 1)
5982 aopPut (AOP (result), "a", offr + MSB16);
5985 /*-----------------------------------------------------------------*/
5986 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5987 /*-----------------------------------------------------------------*/
5989 shiftLLeftOrResult (operand * left, int offl,
5990 operand * result, int offr, int shCount)
5992 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5993 /* shift left accumulator */
5995 /* or with result */
5996 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5997 /* back to result */
5998 aopPut (AOP (result), "a", offr);
6001 /*-----------------------------------------------------------------*/
6002 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6003 /*-----------------------------------------------------------------*/
6005 shiftRLeftOrResult (operand * left, int offl,
6006 operand * result, int offr, int shCount)
6008 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6009 /* shift right accumulator */
6011 /* or with result */
6012 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6013 /* back to result */
6014 aopPut (AOP (result), "a", offr);
6017 /*-----------------------------------------------------------------*/
6018 /* genlshOne - left shift a one byte quantity by known count */
6019 /*-----------------------------------------------------------------*/
6021 genlshOne (operand * result, operand * left, int shCount)
6023 D(emitcode (";", "genlshOne"));
6025 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6028 /*-----------------------------------------------------------------*/
6029 /* genlshTwo - left shift two bytes by known amount != 0 */
6030 /*-----------------------------------------------------------------*/
6032 genlshTwo (operand * result, operand * left, int shCount)
6036 D(emitcode (";", "genlshTwo"));
6038 size = getDataSize (result);
6040 /* if shCount >= 8 */
6048 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6050 movLeft2Result (left, LSB, result, MSB16, 0);
6052 aopPut (AOP (result), zero, LSB);
6055 /* 1 <= shCount <= 7 */
6059 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6061 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6065 /*-----------------------------------------------------------------*/
6066 /* shiftLLong - shift left one long from left to result */
6067 /* offl = LSB or MSB16 */
6068 /*-----------------------------------------------------------------*/
6070 shiftLLong (operand * left, operand * result, int offr)
6073 int size = AOP_SIZE (result);
6075 if (size >= LSB + offr)
6077 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6079 emitcode ("add", "a,acc");
6080 if (sameRegs (AOP (left), AOP (result)) &&
6081 size >= MSB16 + offr && offr != LSB)
6082 emitcode ("xch", "a,%s",
6083 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6085 aopPut (AOP (result), "a", LSB + offr);
6088 if (size >= MSB16 + offr)
6090 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6092 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6095 emitcode ("rlc", "a");
6096 if (sameRegs (AOP (left), AOP (result)) &&
6097 size >= MSB24 + offr && offr != LSB)
6098 emitcode ("xch", "a,%s",
6099 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6101 aopPut (AOP (result), "a", MSB16 + offr);
6104 if (size >= MSB24 + offr)
6106 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6108 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6111 emitcode ("rlc", "a");
6112 if (sameRegs (AOP (left), AOP (result)) &&
6113 size >= MSB32 + offr && offr != LSB)
6114 emitcode ("xch", "a,%s",
6115 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6117 aopPut (AOP (result), "a", MSB24 + offr);
6120 if (size > MSB32 + offr)
6122 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6124 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6127 emitcode ("rlc", "a");
6128 aopPut (AOP (result), "a", MSB32 + offr);
6131 aopPut (AOP (result), zero, LSB);
6134 /*-----------------------------------------------------------------*/
6135 /* genlshFour - shift four byte by a known amount != 0 */
6136 /*-----------------------------------------------------------------*/
6138 genlshFour (operand * result, operand * left, int shCount)
6142 D(emitcode (";", "genlshFour"));
6144 size = AOP_SIZE (result);
6146 /* if shifting more that 3 bytes */
6151 /* lowest order of left goes to the highest
6152 order of the destination */
6153 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6155 movLeft2Result (left, LSB, result, MSB32, 0);
6156 aopPut (AOP (result), zero, LSB);
6157 aopPut (AOP (result), zero, MSB16);
6158 aopPut (AOP (result), zero, MSB24);
6162 /* more than two bytes */
6163 else if (shCount >= 16)
6165 /* lower order two bytes goes to higher order two bytes */
6167 /* if some more remaining */
6169 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6172 movLeft2Result (left, MSB16, result, MSB32, 0);
6173 movLeft2Result (left, LSB, result, MSB24, 0);
6175 aopPut (AOP (result), zero, MSB16);
6176 aopPut (AOP (result), zero, LSB);
6180 /* if more than 1 byte */
6181 else if (shCount >= 8)
6183 /* lower order three bytes goes to higher order three bytes */
6188 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6190 movLeft2Result (left, LSB, result, MSB16, 0);
6196 movLeft2Result (left, MSB24, result, MSB32, 0);
6197 movLeft2Result (left, MSB16, result, MSB24, 0);
6198 movLeft2Result (left, LSB, result, MSB16, 0);
6199 aopPut (AOP (result), zero, LSB);
6201 else if (shCount == 1)
6202 shiftLLong (left, result, MSB16);
6205 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6206 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6207 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6208 aopPut (AOP (result), zero, LSB);
6213 /* 1 <= shCount <= 7 */
6214 else if (shCount <= 2)
6216 shiftLLong (left, result, LSB);
6218 shiftLLong (result, result, LSB);
6220 /* 3 <= shCount <= 7, optimize */
6223 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6224 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6225 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6229 /*-----------------------------------------------------------------*/
6230 /* genLeftShiftLiteral - left shifting by known count */
6231 /*-----------------------------------------------------------------*/
6233 genLeftShiftLiteral (operand * left,
6238 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6241 D(emitcode (";", "genLeftShiftLiteral"));
6243 freeAsmop (right, NULL, ic, TRUE);
6245 aopOp (left, ic, FALSE);
6246 aopOp (result, ic, FALSE);
6248 size = getSize (operandType (result));
6251 emitcode ("; shift left ", "result %d, left %d", size,
6255 /* I suppose that the left size >= result size */
6260 movLeft2Result (left, size, result, size, 0);
6264 else if (shCount >= (size * 8))
6266 aopPut (AOP (result), zero, size);
6272 genlshOne (result, left, shCount);
6276 genlshTwo (result, left, shCount);
6280 genlshFour (result, left, shCount);
6283 fprintf(stderr, "*** ack! mystery literal shift!\n");
6287 freeAsmop (left, NULL, ic, TRUE);
6288 freeAsmop (result, NULL, ic, TRUE);
6291 /*-----------------------------------------------------------------*/
6292 /* genLeftShift - generates code for left shifting */
6293 /*-----------------------------------------------------------------*/
6295 genLeftShift (iCode * ic)
6297 operand *left, *right, *result;
6300 symbol *tlbl, *tlbl1;
6302 D(emitcode (";", "genLeftShift"));
6304 right = IC_RIGHT (ic);
6305 left = IC_LEFT (ic);
6306 result = IC_RESULT (ic);
6308 aopOp (right, ic, FALSE);
6310 /* if the shift count is known then do it
6311 as efficiently as possible */
6312 if (AOP_TYPE (right) == AOP_LIT)
6314 genLeftShiftLiteral (left, right, result, ic);
6318 /* shift count is unknown then we have to form
6319 a loop get the loop count in B : Note: we take
6320 only the lower order byte since shifting
6321 more that 32 bits make no sense anyway, ( the
6322 largest size of an object can be only 32 bits ) */
6324 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6325 emitcode ("inc", "b");
6326 freeAsmop (right, NULL, ic, TRUE);
6327 aopOp (left, ic, FALSE);
6328 aopOp (result, ic, FALSE);
6330 /* now move the left to the result if they are not the
6332 if (!sameRegs (AOP (left), AOP (result)) &&
6333 AOP_SIZE (result) > 1)
6336 size = AOP_SIZE (result);
6340 l = aopGet (AOP (left), offset, FALSE, TRUE);
6341 if (*l == '@' && (IS_AOP_PREG (result)))
6344 emitcode ("mov", "a,%s", l);
6345 aopPut (AOP (result), "a", offset);
6348 aopPut (AOP (result), l, offset);
6353 tlbl = newiTempLabel (NULL);
6354 size = AOP_SIZE (result);
6356 tlbl1 = newiTempLabel (NULL);
6358 /* if it is only one byte then */
6361 symbol *tlbl1 = newiTempLabel (NULL);
6363 l = aopGet (AOP (left), 0, FALSE, FALSE);
6365 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6366 emitcode ("", "%05d$:", tlbl->key + 100);
6367 emitcode ("add", "a,acc");
6368 emitcode ("", "%05d$:", tlbl1->key + 100);
6369 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6370 aopPut (AOP (result), "a", 0);
6374 reAdjustPreg (AOP (result));
6376 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6377 emitcode ("", "%05d$:", tlbl->key + 100);
6378 l = aopGet (AOP (result), offset, FALSE, FALSE);
6380 emitcode ("add", "a,acc");
6381 aopPut (AOP (result), "a", offset++);
6384 l = aopGet (AOP (result), offset, FALSE, FALSE);
6386 emitcode ("rlc", "a");
6387 aopPut (AOP (result), "a", offset++);
6389 reAdjustPreg (AOP (result));
6391 emitcode ("", "%05d$:", tlbl1->key + 100);
6392 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6394 freeAsmop (left, NULL, ic, TRUE);
6395 freeAsmop (result, NULL, ic, TRUE);
6398 /*-----------------------------------------------------------------*/
6399 /* genrshOne - right shift a one byte quantity by known count */
6400 /*-----------------------------------------------------------------*/
6402 genrshOne (operand * result, operand * left,
6403 int shCount, int sign)
6405 D(emitcode (";", "genrshOne"));
6407 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6410 /*-----------------------------------------------------------------*/
6411 /* genrshTwo - right shift two bytes by known amount != 0 */
6412 /*-----------------------------------------------------------------*/
6414 genrshTwo (operand * result, operand * left,
6415 int shCount, int sign)
6417 D(emitcode (";", "genrshTwo"));
6419 /* if shCount >= 8 */
6424 shiftR1Left2Result (left, MSB16, result, LSB,
6427 movLeft2Result (left, MSB16, result, LSB, sign);
6428 addSign (result, MSB16, sign);
6431 /* 1 <= shCount <= 7 */
6433 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6436 /*-----------------------------------------------------------------*/
6437 /* shiftRLong - shift right one long from left to result */
6438 /* offl = LSB or MSB16 */
6439 /*-----------------------------------------------------------------*/
6441 shiftRLong (operand * left, int offl,
6442 operand * result, int sign)
6444 int isSameRegs=sameRegs(AOP(left),AOP(result));
6446 if (isSameRegs && offl>1) {
6447 // we are in big trouble, but this shouldn't happen
6448 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6451 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6456 emitcode ("rlc", "a");
6457 emitcode ("subb", "a,acc");
6458 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6460 aopPut (AOP(result), zero, MSB32);
6465 emitcode ("clr", "c");
6467 emitcode ("mov", "c,acc.7");
6470 emitcode ("rrc", "a");
6472 if (isSameRegs && offl==MSB16) {
6473 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6475 aopPut (AOP (result), "a", MSB32);
6476 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6479 emitcode ("rrc", "a");
6480 if (isSameRegs && offl==1) {
6481 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6483 aopPut (AOP (result), "a", MSB24);
6484 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6486 emitcode ("rrc", "a");
6487 aopPut (AOP (result), "a", MSB16 - offl);
6491 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6492 emitcode ("rrc", "a");
6493 aopPut (AOP (result), "a", LSB);
6497 /*-----------------------------------------------------------------*/
6498 /* genrshFour - shift four byte by a known amount != 0 */
6499 /*-----------------------------------------------------------------*/
6501 genrshFour (operand * result, operand * left,
6502 int shCount, int sign)
6504 D(emitcode (";", "genrshFour"));
6506 /* if shifting more that 3 bytes */
6511 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6513 movLeft2Result (left, MSB32, result, LSB, sign);
6514 addSign (result, MSB16, sign);
6516 else if (shCount >= 16)
6520 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6523 movLeft2Result (left, MSB24, result, LSB, 0);
6524 movLeft2Result (left, MSB32, result, MSB16, sign);
6526 addSign (result, MSB24, sign);
6528 else if (shCount >= 8)
6532 shiftRLong (left, MSB16, result, sign);
6533 else if (shCount == 0)
6535 movLeft2Result (left, MSB16, result, LSB, 0);
6536 movLeft2Result (left, MSB24, result, MSB16, 0);
6537 movLeft2Result (left, MSB32, result, MSB24, sign);
6538 addSign (result, MSB32, sign);
6542 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6543 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6544 /* the last shift is signed */
6545 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6546 addSign (result, MSB32, sign);
6550 { /* 1 <= shCount <= 7 */
6553 shiftRLong (left, LSB, result, sign);
6555 shiftRLong (result, LSB, result, sign);
6559 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6560 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6561 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6566 /*-----------------------------------------------------------------*/
6567 /* genRightShiftLiteral - right shifting by known count */
6568 /*-----------------------------------------------------------------*/
6570 genRightShiftLiteral (operand * left,
6576 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6579 D(emitcode (";", "genRightShiftLiteral"));
6581 freeAsmop (right, NULL, ic, TRUE);
6583 aopOp (left, ic, FALSE);
6584 aopOp (result, ic, FALSE);
6587 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6591 size = getDataSize (left);
6592 /* test the LEFT size !!! */
6594 /* I suppose that the left size >= result size */
6597 size = getDataSize (result);
6599 movLeft2Result (left, size, result, size, 0);
6602 else if (shCount >= (size * 8))
6605 /* get sign in acc.7 */
6606 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6607 addSign (result, LSB, sign);
6614 genrshOne (result, left, shCount, sign);
6618 genrshTwo (result, left, shCount, sign);
6622 genrshFour (result, left, shCount, sign);
6628 freeAsmop (left, NULL, ic, TRUE);
6629 freeAsmop (result, NULL, ic, TRUE);
6633 /*-----------------------------------------------------------------*/
6634 /* genSignedRightShift - right shift of signed number */
6635 /*-----------------------------------------------------------------*/
6637 genSignedRightShift (iCode * ic)
6639 operand *right, *left, *result;
6642 symbol *tlbl, *tlbl1;
6644 D(emitcode (";", "genSignedRightShift"));
6646 /* we do it the hard way put the shift count in b
6647 and loop thru preserving the sign */
6649 right = IC_RIGHT (ic);
6650 left = IC_LEFT (ic);
6651 result = IC_RESULT (ic);
6653 aopOp (right, ic, FALSE);
6656 if (AOP_TYPE (right) == AOP_LIT)
6658 genRightShiftLiteral (left, right, result, ic, 1);
6661 /* shift count is unknown then we have to form
6662 a loop get the loop count in B : Note: we take
6663 only the lower order byte since shifting
6664 more that 32 bits make no sense anyway, ( the
6665 largest size of an object can be only 32 bits ) */
6667 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6668 emitcode ("inc", "b");
6669 freeAsmop (right, NULL, ic, TRUE);
6670 aopOp (left, ic, FALSE);
6671 aopOp (result, ic, FALSE);
6673 /* now move the left to the result if they are not the
6675 if (!sameRegs (AOP (left), AOP (result)) &&
6676 AOP_SIZE (result) > 1)
6679 size = AOP_SIZE (result);
6683 l = aopGet (AOP (left), offset, FALSE, TRUE);
6684 if (*l == '@' && IS_AOP_PREG (result))
6687 emitcode ("mov", "a,%s", l);
6688 aopPut (AOP (result), "a", offset);
6691 aopPut (AOP (result), l, offset);
6696 /* mov the highest order bit to OVR */
6697 tlbl = newiTempLabel (NULL);
6698 tlbl1 = newiTempLabel (NULL);
6700 size = AOP_SIZE (result);
6702 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6703 emitcode ("rlc", "a");
6704 emitcode ("mov", "ov,c");
6705 /* if it is only one byte then */
6708 l = aopGet (AOP (left), 0, FALSE, FALSE);
6710 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6711 emitcode ("", "%05d$:", tlbl->key + 100);
6712 emitcode ("mov", "c,ov");
6713 emitcode ("rrc", "a");
6714 emitcode ("", "%05d$:", tlbl1->key + 100);
6715 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6716 aopPut (AOP (result), "a", 0);
6720 reAdjustPreg (AOP (result));
6721 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6722 emitcode ("", "%05d$:", tlbl->key + 100);
6723 emitcode ("mov", "c,ov");
6726 l = aopGet (AOP (result), offset, FALSE, FALSE);
6728 emitcode ("rrc", "a");
6729 aopPut (AOP (result), "a", offset--);
6731 reAdjustPreg (AOP (result));
6732 emitcode ("", "%05d$:", tlbl1->key + 100);
6733 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6736 freeAsmop (left, NULL, ic, TRUE);
6737 freeAsmop (result, NULL, ic, TRUE);
6740 /*-----------------------------------------------------------------*/
6741 /* genRightShift - generate code for right shifting */
6742 /*-----------------------------------------------------------------*/
6744 genRightShift (iCode * ic)
6746 operand *right, *left, *result;
6750 symbol *tlbl, *tlbl1;
6752 D(emitcode (";", "genRightShift"));
6754 /* if signed then we do it the hard way preserve the
6755 sign bit moving it inwards */
6756 retype = getSpec (operandType (IC_RESULT (ic)));
6758 if (!SPEC_USIGN (retype))
6760 genSignedRightShift (ic);
6764 /* signed & unsigned types are treated the same : i.e. the
6765 signed is NOT propagated inwards : quoting from the
6766 ANSI - standard : "for E1 >> E2, is equivalent to division
6767 by 2**E2 if unsigned or if it has a non-negative value,
6768 otherwise the result is implementation defined ", MY definition
6769 is that the sign does not get propagated */
6771 right = IC_RIGHT (ic);
6772 left = IC_LEFT (ic);
6773 result = IC_RESULT (ic);
6775 aopOp (right, ic, FALSE);
6777 /* if the shift count is known then do it
6778 as efficiently as possible */
6779 if (AOP_TYPE (right) == AOP_LIT)
6781 genRightShiftLiteral (left, right, result, ic, 0);
6785 /* shift count is unknown then we have to form
6786 a loop get the loop count in B : Note: we take
6787 only the lower order byte since shifting
6788 more that 32 bits make no sense anyway, ( the
6789 largest size of an object can be only 32 bits ) */
6791 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6792 emitcode ("inc", "b");
6793 freeAsmop (right, NULL, ic, TRUE);
6794 aopOp (left, ic, FALSE);
6795 aopOp (result, ic, FALSE);
6797 /* now move the left to the result if they are not the
6799 if (!sameRegs (AOP (left), AOP (result)) &&
6800 AOP_SIZE (result) > 1)
6803 size = AOP_SIZE (result);
6807 l = aopGet (AOP (left), offset, FALSE, TRUE);
6808 if (*l == '@' && IS_AOP_PREG (result))
6811 emitcode ("mov", "a,%s", l);
6812 aopPut (AOP (result), "a", offset);
6815 aopPut (AOP (result), l, offset);
6820 tlbl = newiTempLabel (NULL);
6821 tlbl1 = newiTempLabel (NULL);
6822 size = AOP_SIZE (result);
6825 /* if it is only one byte then */
6828 l = aopGet (AOP (left), 0, FALSE, FALSE);
6830 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6831 emitcode ("", "%05d$:", tlbl->key + 100);
6833 emitcode ("rrc", "a");
6834 emitcode ("", "%05d$:", tlbl1->key + 100);
6835 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6836 aopPut (AOP (result), "a", 0);
6840 reAdjustPreg (AOP (result));
6841 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6842 emitcode ("", "%05d$:", tlbl->key + 100);
6846 l = aopGet (AOP (result), offset, FALSE, FALSE);
6848 emitcode ("rrc", "a");
6849 aopPut (AOP (result), "a", offset--);
6851 reAdjustPreg (AOP (result));
6853 emitcode ("", "%05d$:", tlbl1->key + 100);
6854 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6857 freeAsmop (left, NULL, ic, TRUE);
6858 freeAsmop (result, NULL, ic, TRUE);
6861 /*-----------------------------------------------------------------*/
6862 /* genUnpackBits - generates code for unpacking bits */
6863 /*-----------------------------------------------------------------*/
6865 genUnpackBits (operand * result, char *rname, int ptype)
6873 D(emitcode (";", "genUnpackBits"));
6875 etype = getSpec (operandType (result));
6876 rsize = getSize (operandType (result));
6877 /* read the first byte */
6883 emitcode ("mov", "a,@%s", rname);
6887 emitcode ("movx", "a,@%s", rname);
6891 emitcode ("movx", "a,@dptr");
6895 emitcode ("clr", "a");
6896 emitcode ("movc", "a,@a+dptr");
6900 emitcode ("lcall", "__gptrget");
6904 rlen = SPEC_BLEN (etype);
6906 /* if we have bitdisplacement then it fits */
6907 /* into this byte completely or if length is */
6908 /* less than a byte */
6909 if ((shCnt = SPEC_BSTR (etype)) ||
6910 (SPEC_BLEN (etype) <= 8))
6913 /* shift right acc */
6916 emitcode ("anl", "a,#0x%02x",
6917 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6918 aopPut (AOP (result), "a", offset++);
6922 /* bit field did not fit in a byte */
6923 aopPut (AOP (result), "a", offset++);
6932 emitcode ("inc", "%s", rname);
6933 emitcode ("mov", "a,@%s", rname);
6937 emitcode ("inc", "%s", rname);
6938 emitcode ("movx", "a,@%s", rname);
6942 emitcode ("inc", "dptr");
6943 emitcode ("movx", "a,@dptr");
6947 emitcode ("clr", "a");
6948 emitcode ("inc", "dptr");
6949 emitcode ("movc", "a,@a+dptr");
6953 emitcode ("inc", "dptr");
6954 emitcode ("lcall", "__gptrget");
6959 /* if we are done */
6963 aopPut (AOP (result), "a", offset++);
6969 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6971 aopPut (AOP (result), "a", offset++);
6979 aopPut (AOP (result), zero, offset++);
6985 /*-----------------------------------------------------------------*/
6986 /* genDataPointerGet - generates code when ptr offset is known */
6987 /*-----------------------------------------------------------------*/
6989 genDataPointerGet (operand * left,
6995 int size, offset = 0;
6997 D(emitcode (";", "genDataPointerGet"));
6999 aopOp (result, ic, TRUE);
7001 /* get the string representation of the name */
7002 l = aopGet (AOP (left), 0, FALSE, TRUE);
7003 size = AOP_SIZE (result);
7007 sprintf (buffer, "(%s + %d)", l + 1, offset);
7009 sprintf (buffer, "%s", l + 1);
7010 aopPut (AOP (result), buffer, offset++);
7013 freeAsmop (left, NULL, ic, TRUE);
7014 freeAsmop (result, NULL, ic, TRUE);
7017 /*-----------------------------------------------------------------*/
7018 /* genNearPointerGet - emitcode for near pointer fetch */
7019 /*-----------------------------------------------------------------*/
7021 genNearPointerGet (operand * left,
7029 sym_link *rtype, *retype;
7030 sym_link *ltype = operandType (left);
7033 D(emitcode (";", "genNearPointerGet"));
7035 rtype = operandType (result);
7036 retype = getSpec (rtype);
7038 aopOp (left, ic, FALSE);
7040 /* if left is rematerialisable and
7041 result is not bit variable type and
7042 the left is pointer to data space i.e
7043 lower 128 bytes of space */
7044 if (AOP_TYPE (left) == AOP_IMMD &&
7045 !IS_BITVAR (retype) &&
7046 DCL_TYPE (ltype) == POINTER)
7048 genDataPointerGet (left, result, ic);
7052 /* if the value is already in a pointer register
7053 then don't need anything more */
7054 if (!AOP_INPREG (AOP (left)))
7056 /* otherwise get a free pointer register */
7058 preg = getFreePtr (ic, &aop, FALSE);
7059 emitcode ("mov", "%s,%s",
7061 aopGet (AOP (left), 0, FALSE, TRUE));
7065 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7067 //aopOp (result, ic, FALSE);
7068 aopOp (result, ic, result?TRUE:FALSE);
7070 /* if bitfield then unpack the bits */
7071 if (IS_BITVAR (retype))
7072 genUnpackBits (result, rname, POINTER);
7075 /* we have can just get the values */
7076 int size = AOP_SIZE (result);
7081 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7084 emitcode ("mov", "a,@%s", rname);
7085 aopPut (AOP (result), "a", offset);
7089 sprintf (buffer, "@%s", rname);
7090 aopPut (AOP (result), buffer, offset);
7094 emitcode ("inc", "%s", rname);
7098 /* now some housekeeping stuff */
7099 if (aop) /* we had to allocate for this iCode */
7101 if (pi) { /* post increment present */
7102 aopPut(AOP ( left ),rname,0);
7104 freeAsmop (NULL, aop, ic, TRUE);
7108 /* we did not allocate which means left
7109 already in a pointer register, then
7110 if size > 0 && this could be used again
7111 we have to point it back to where it
7113 if ((AOP_SIZE (result) > 1 &&
7114 !OP_SYMBOL (left)->remat &&
7115 (OP_SYMBOL (left)->liveTo > ic->seq ||
7119 int size = AOP_SIZE (result) - 1;
7121 emitcode ("dec", "%s", rname);
7126 freeAsmop (left, NULL, ic, TRUE);
7127 freeAsmop (result, NULL, ic, TRUE);
7128 if (pi) pi->generated = 1;
7131 /*-----------------------------------------------------------------*/
7132 /* genPagedPointerGet - emitcode for paged pointer fetch */
7133 /*-----------------------------------------------------------------*/
7135 genPagedPointerGet (operand * left,
7143 sym_link *rtype, *retype;
7145 D(emitcode (";", "genPagedPointerGet"));
7147 rtype = operandType (result);
7148 retype = getSpec (rtype);
7150 aopOp (left, ic, FALSE);
7152 /* if the value is already in a pointer register
7153 then don't need anything more */
7154 if (!AOP_INPREG (AOP (left)))
7156 /* otherwise get a free pointer register */
7158 preg = getFreePtr (ic, &aop, FALSE);
7159 emitcode ("mov", "%s,%s",
7161 aopGet (AOP (left), 0, FALSE, TRUE));
7165 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7167 aopOp (result, ic, FALSE);
7169 /* if bitfield then unpack the bits */
7170 if (IS_BITVAR (retype))
7171 genUnpackBits (result, rname, PPOINTER);
7174 /* we have can just get the values */
7175 int size = AOP_SIZE (result);
7181 emitcode ("movx", "a,@%s", rname);
7182 aopPut (AOP (result), "a", offset);
7187 emitcode ("inc", "%s", rname);
7191 /* now some housekeeping stuff */
7192 if (aop) /* we had to allocate for this iCode */
7194 if (pi) aopPut ( AOP (left), rname, 0);
7195 freeAsmop (NULL, aop, ic, TRUE);
7199 /* we did not allocate which means left
7200 already in a pointer register, then
7201 if size > 0 && this could be used again
7202 we have to point it back to where it
7204 if ((AOP_SIZE (result) > 1 &&
7205 !OP_SYMBOL (left)->remat &&
7206 (OP_SYMBOL (left)->liveTo > ic->seq ||
7210 int size = AOP_SIZE (result) - 1;
7212 emitcode ("dec", "%s", rname);
7217 freeAsmop (left, NULL, ic, TRUE);
7218 freeAsmop (result, NULL, ic, TRUE);
7219 if (pi) pi->generated = 1;
7223 /*-----------------------------------------------------------------*/
7224 /* genFarPointerGet - gget value from far space */
7225 /*-----------------------------------------------------------------*/
7227 genFarPointerGet (operand * left,
7228 operand * result, iCode * ic, iCode * pi)
7231 sym_link *retype = getSpec (operandType (result));
7233 D(emitcode (";", "genFarPointerGet"));
7235 aopOp (left, ic, FALSE);
7237 /* if the operand is already in dptr
7238 then we do nothing else we move the value to dptr */
7239 if (AOP_TYPE (left) != AOP_STR)
7241 /* if this is remateriazable */
7242 if (AOP_TYPE (left) == AOP_IMMD)
7243 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7245 { /* we need to get it byte by byte */
7246 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7247 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7250 /* so dptr know contains the address */
7251 aopOp (result, ic, FALSE);
7253 /* if bit then unpack */
7254 if (IS_BITVAR (retype))
7255 genUnpackBits (result, "dptr", FPOINTER);
7258 size = AOP_SIZE (result);
7263 emitcode ("movx", "a,@dptr");
7264 aopPut (AOP (result), "a", offset++);
7266 emitcode ("inc", "dptr");
7270 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7271 aopPut ( AOP (left), "dpl", 0);
7272 aopPut ( AOP (left), "dph", 1);
7275 freeAsmop (left, NULL, ic, TRUE);
7276 freeAsmop (result, NULL, ic, TRUE);
7279 /*-----------------------------------------------------------------*/
7280 /* genCodePointerGet - gget value from code space */
7281 /*-----------------------------------------------------------------*/
7283 genCodePointerGet (operand * left,
7284 operand * result, iCode * ic, iCode *pi)
7287 sym_link *retype = getSpec (operandType (result));
7289 D(emitcode (";", "genCodePointerGet"));
7291 aopOp (left, ic, FALSE);
7293 /* if the operand is already in dptr
7294 then we do nothing else we move the value to dptr */
7295 if (AOP_TYPE (left) != AOP_STR)
7297 /* if this is remateriazable */
7298 if (AOP_TYPE (left) == AOP_IMMD)
7299 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7301 { /* we need to get it byte by byte */
7302 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7303 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7306 /* so dptr know contains the address */
7307 aopOp (result, ic, FALSE);
7309 /* if bit then unpack */
7310 if (IS_BITVAR (retype))
7311 genUnpackBits (result, "dptr", CPOINTER);
7314 size = AOP_SIZE (result);
7319 emitcode ("clr", "a");
7320 emitcode ("movc", "a,@a+dptr");
7321 aopPut (AOP (result), "a", offset++);
7323 emitcode ("inc", "dptr");
7327 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7328 aopPut ( AOP (left), "dpl", 0);
7329 aopPut ( AOP (left), "dph", 1);
7332 freeAsmop (left, NULL, ic, TRUE);
7333 freeAsmop (result, NULL, ic, TRUE);
7336 /*-----------------------------------------------------------------*/
7337 /* genGenPointerGet - gget value from generic pointer space */
7338 /*-----------------------------------------------------------------*/
7340 genGenPointerGet (operand * left,
7341 operand * result, iCode * ic, iCode *pi)
7344 sym_link *retype = getSpec (operandType (result));
7346 D(emitcode (";", "genGenPointerGet"));
7348 aopOp (left, ic, FALSE);
7350 /* if the operand is already in dptr
7351 then we do nothing else we move the value to dptr */
7352 if (AOP_TYPE (left) != AOP_STR)
7354 /* if this is remateriazable */
7355 if (AOP_TYPE (left) == AOP_IMMD)
7357 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7358 emitcode ("mov", "b,#%d", pointerCode (retype));
7361 { /* we need to get it byte by byte */
7362 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7363 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7364 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7367 /* so dptr know contains the address */
7368 aopOp (result, ic, FALSE);
7370 /* if bit then unpack */
7371 if (IS_BITVAR (retype))
7372 genUnpackBits (result, "dptr", GPOINTER);
7375 size = AOP_SIZE (result);
7380 emitcode ("lcall", "__gptrget");
7381 aopPut (AOP (result), "a", offset++);
7383 emitcode ("inc", "dptr");
7387 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7388 aopPut ( AOP (left), "dpl", 0);
7389 aopPut ( AOP (left), "dph", 1);
7392 freeAsmop (left, NULL, ic, TRUE);
7393 freeAsmop (result, NULL, ic, TRUE);
7396 /*-----------------------------------------------------------------*/
7397 /* genPointerGet - generate code for pointer get */
7398 /*-----------------------------------------------------------------*/
7400 genPointerGet (iCode * ic, iCode *pi)
7402 operand *left, *result;
7403 sym_link *type, *etype;
7406 D(emitcode (";", "genPointerGet"));
7408 left = IC_LEFT (ic);
7409 result = IC_RESULT (ic);
7411 /* depending on the type of pointer we need to
7412 move it to the correct pointer register */
7413 type = operandType (left);
7414 etype = getSpec (type);
7415 /* if left is of type of pointer then it is simple */
7416 if (IS_PTR (type) && !IS_FUNC (type->next))
7417 p_type = DCL_TYPE (type);
7420 /* we have to go by the storage class */
7421 p_type = PTR_TYPE (SPEC_OCLS (etype));
7424 /* now that we have the pointer type we assign
7425 the pointer values */
7431 genNearPointerGet (left, result, ic, pi);
7435 genPagedPointerGet (left, result, ic, pi);
7439 genFarPointerGet (left, result, ic, pi);
7443 genCodePointerGet (left, result, ic, pi);
7447 genGenPointerGet (left, result, ic, pi);
7453 /*-----------------------------------------------------------------*/
7454 /* genPackBits - generates code for packed bit storage */
7455 /*-----------------------------------------------------------------*/
7457 genPackBits (sym_link * etype,
7459 char *rname, int p_type)
7467 D(emitcode (";", "genPackBits"));
7469 blen = SPEC_BLEN (etype);
7470 bstr = SPEC_BSTR (etype);
7472 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7475 /* if the bit lenth is less than or */
7476 /* it exactly fits a byte then */
7477 if (SPEC_BLEN (etype) <= 8)
7479 shCount = SPEC_BSTR (etype);
7481 /* shift left acc */
7484 if (SPEC_BLEN (etype) < 8)
7485 { /* if smaller than a byte */
7491 emitcode ("mov", "b,a");
7492 emitcode ("mov", "a,@%s", rname);
7496 emitcode ("mov", "b,a");
7497 emitcode ("movx", "a,@dptr");
7501 emitcode ("push", "b");
7502 emitcode ("push", "acc");
7503 emitcode ("lcall", "__gptrget");
7504 emitcode ("pop", "b");
7508 emitcode ("anl", "a,#0x%02x", (unsigned char)
7509 ((unsigned char) (0xFF << (blen + bstr)) |
7510 (unsigned char) (0xFF >> (8 - bstr))));
7511 emitcode ("orl", "a,b");
7512 if (p_type == GPOINTER)
7513 emitcode ("pop", "b");
7520 emitcode ("mov", "@%s,a", rname);
7524 emitcode ("movx", "@dptr,a");
7528 emitcode ("lcall", "__gptrput");
7533 if (SPEC_BLEN (etype) <= 8)
7536 emitcode ("inc", "%s", rname);
7537 rLen = SPEC_BLEN (etype);
7539 /* now generate for lengths greater than one byte */
7543 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7555 emitcode ("mov", "@%s,a", rname);
7558 emitcode ("mov", "@%s,%s", rname, l);
7563 emitcode ("movx", "@dptr,a");
7568 emitcode ("lcall", "__gptrput");
7571 emitcode ("inc", "%s", rname);
7576 /* last last was not complete */
7579 /* save the byte & read byte */
7583 emitcode ("mov", "b,a");
7584 emitcode ("mov", "a,@%s", rname);
7588 emitcode ("mov", "b,a");
7589 emitcode ("movx", "a,@dptr");
7593 emitcode ("push", "b");
7594 emitcode ("push", "acc");
7595 emitcode ("lcall", "__gptrget");
7596 emitcode ("pop", "b");
7600 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7601 emitcode ("orl", "a,b");
7604 if (p_type == GPOINTER)
7605 emitcode ("pop", "b");
7611 emitcode ("mov", "@%s,a", rname);
7615 emitcode ("movx", "@dptr,a");
7619 emitcode ("lcall", "__gptrput");
7623 /*-----------------------------------------------------------------*/
7624 /* genDataPointerSet - remat pointer to data space */
7625 /*-----------------------------------------------------------------*/
7627 genDataPointerSet (operand * right,
7631 int size, offset = 0;
7632 char *l, buffer[256];
7634 D(emitcode (";", "genDataPointerSet"));
7636 aopOp (right, ic, FALSE);
7638 l = aopGet (AOP (result), 0, FALSE, TRUE);
7639 size = AOP_SIZE (right);
7643 sprintf (buffer, "(%s + %d)", l + 1, offset);
7645 sprintf (buffer, "%s", l + 1);
7646 emitcode ("mov", "%s,%s", buffer,
7647 aopGet (AOP (right), offset++, FALSE, FALSE));
7650 freeAsmop (right, NULL, ic, TRUE);
7651 freeAsmop (result, NULL, ic, TRUE);
7654 /*-----------------------------------------------------------------*/
7655 /* genNearPointerSet - emitcode for near pointer put */
7656 /*-----------------------------------------------------------------*/
7658 genNearPointerSet (operand * right,
7666 sym_link *retype, *letype;
7667 sym_link *ptype = operandType (result);
7669 D(emitcode (";", "genNearPointerSet"));
7671 retype = getSpec (operandType (right));
7672 letype = getSpec (ptype);
7673 aopOp (result, ic, FALSE);
7675 /* if the result is rematerializable &
7676 in data space & not a bit variable */
7677 if (AOP_TYPE (result) == AOP_IMMD &&
7678 DCL_TYPE (ptype) == POINTER &&
7679 !IS_BITVAR (retype) &&
7680 !IS_BITVAR (letype))
7682 genDataPointerSet (right, result, ic);
7686 /* if the value is already in a pointer register
7687 then don't need anything more */
7688 if (!AOP_INPREG (AOP (result)))
7691 //AOP_TYPE (result) == AOP_STK
7695 // Aha, it is a pointer, just in disguise.
7696 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7699 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7700 __FILE__, __LINE__);
7705 rname++; // skip the '@'.
7710 /* otherwise get a free pointer register */
7712 preg = getFreePtr (ic, &aop, FALSE);
7713 emitcode ("mov", "%s,%s",
7715 aopGet (AOP (result), 0, FALSE, TRUE));
7721 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7724 aopOp (right, ic, FALSE);
7726 /* if bitfield then unpack the bits */
7727 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7728 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7731 /* we have can just get the values */
7732 int size = AOP_SIZE (right);
7737 l = aopGet (AOP (right), offset, FALSE, TRUE);
7741 emitcode ("mov", "@%s,a", rname);
7744 emitcode ("mov", "@%s,%s", rname, l);
7746 emitcode ("inc", "%s", rname);
7751 /* now some housekeeping stuff */
7752 if (aop) /* we had to allocate for this iCode */
7754 if (pi) aopPut (AOP (result),rname,0);
7755 freeAsmop (NULL, aop, ic, TRUE);
7759 /* we did not allocate which means left
7760 already in a pointer register, then
7761 if size > 0 && this could be used again
7762 we have to point it back to where it
7764 if ((AOP_SIZE (right) > 1 &&
7765 !OP_SYMBOL (result)->remat &&
7766 (OP_SYMBOL (result)->liveTo > ic->seq ||
7770 int size = AOP_SIZE (right) - 1;
7772 emitcode ("dec", "%s", rname);
7777 if (pi) pi->generated = 1;
7778 freeAsmop (result, NULL, ic, TRUE);
7779 freeAsmop (right, NULL, ic, TRUE);
7782 /*-----------------------------------------------------------------*/
7783 /* genPagedPointerSet - emitcode for Paged pointer put */
7784 /*-----------------------------------------------------------------*/
7786 genPagedPointerSet (operand * right,
7794 sym_link *retype, *letype;
7796 D(emitcode (";", "genPagedPointerSet"));
7798 retype = getSpec (operandType (right));
7799 letype = getSpec (operandType (result));
7801 aopOp (result, ic, FALSE);
7803 /* if the value is already in a pointer register
7804 then don't need anything more */
7805 if (!AOP_INPREG (AOP (result)))
7807 /* otherwise get a free pointer register */
7809 preg = getFreePtr (ic, &aop, FALSE);
7810 emitcode ("mov", "%s,%s",
7812 aopGet (AOP (result), 0, FALSE, TRUE));
7816 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7818 aopOp (right, ic, FALSE);
7820 /* if bitfield then unpack the bits */
7821 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7822 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7825 /* we have can just get the values */
7826 int size = AOP_SIZE (right);
7831 l = aopGet (AOP (right), offset, FALSE, TRUE);
7834 emitcode ("movx", "@%s,a", rname);
7837 emitcode ("inc", "%s", rname);
7843 /* now some housekeeping stuff */
7844 if (aop) /* we had to allocate for this iCode */
7846 if (pi) aopPut (AOP (result),rname,0);
7847 freeAsmop (NULL, aop, ic, TRUE);
7851 /* we did not allocate which means left
7852 already in a pointer register, then
7853 if size > 0 && this could be used again
7854 we have to point it back to where it
7856 if (AOP_SIZE (right) > 1 &&
7857 !OP_SYMBOL (result)->remat &&
7858 (OP_SYMBOL (result)->liveTo > ic->seq ||
7861 int size = AOP_SIZE (right) - 1;
7863 emitcode ("dec", "%s", rname);
7868 if (pi) pi->generated = 1;
7869 freeAsmop (result, NULL, ic, TRUE);
7870 freeAsmop (right, NULL, ic, TRUE);
7875 /*-----------------------------------------------------------------*/
7876 /* genFarPointerSet - set value from far space */
7877 /*-----------------------------------------------------------------*/
7879 genFarPointerSet (operand * right,
7880 operand * result, iCode * ic, iCode * pi)
7883 sym_link *retype = getSpec (operandType (right));
7884 sym_link *letype = getSpec (operandType (result));
7886 D(emitcode (";", "genFarPointerSet"));
7888 aopOp (result, ic, FALSE);
7890 /* if the operand is already in dptr
7891 then we do nothing else we move the value to dptr */
7892 if (AOP_TYPE (result) != AOP_STR)
7894 /* if this is remateriazable */
7895 if (AOP_TYPE (result) == AOP_IMMD)
7896 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7898 { /* we need to get it byte by byte */
7899 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7900 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7903 /* so dptr know contains the address */
7904 aopOp (right, ic, FALSE);
7906 /* if bit then unpack */
7907 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7908 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7911 size = AOP_SIZE (right);
7916 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7918 emitcode ("movx", "@dptr,a");
7920 emitcode ("inc", "dptr");
7923 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7924 aopPut (AOP(result),"dpl",0);
7925 aopPut (AOP(result),"dph",1);
7928 freeAsmop (result, NULL, ic, TRUE);
7929 freeAsmop (right, NULL, ic, TRUE);
7932 /*-----------------------------------------------------------------*/
7933 /* genGenPointerSet - set value from generic pointer space */
7934 /*-----------------------------------------------------------------*/
7936 genGenPointerSet (operand * right,
7937 operand * result, iCode * ic, iCode * pi)
7940 sym_link *retype = getSpec (operandType (right));
7941 sym_link *letype = getSpec (operandType (result));
7943 D(emitcode (";", "genGenPointerSet"));
7945 aopOp (result, ic, FALSE);
7947 /* if the operand is already in dptr
7948 then we do nothing else we move the value to dptr */
7949 if (AOP_TYPE (result) != AOP_STR)
7951 /* if this is remateriazable */
7952 if (AOP_TYPE (result) == AOP_IMMD)
7954 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7955 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7958 { /* we need to get it byte by byte */
7959 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7960 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7961 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7964 /* so dptr know contains the address */
7965 aopOp (right, ic, FALSE);
7967 /* if bit then unpack */
7968 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7969 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7972 size = AOP_SIZE (right);
7977 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7979 emitcode ("lcall", "__gptrput");
7981 emitcode ("inc", "dptr");
7985 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7986 aopPut (AOP(result),"dpl",0);
7987 aopPut (AOP(result),"dph",1);
7990 freeAsmop (result, NULL, ic, TRUE);
7991 freeAsmop (right, NULL, ic, TRUE);
7994 /*-----------------------------------------------------------------*/
7995 /* genPointerSet - stores the value into a pointer location */
7996 /*-----------------------------------------------------------------*/
7998 genPointerSet (iCode * ic, iCode *pi)
8000 operand *right, *result;
8001 sym_link *type, *etype;
8004 D(emitcode (";", "genPointerSet"));
8006 right = IC_RIGHT (ic);
8007 result = IC_RESULT (ic);
8009 /* depending on the type of pointer we need to
8010 move it to the correct pointer register */
8011 type = operandType (result);
8012 etype = getSpec (type);
8013 /* if left is of type of pointer then it is simple */
8014 if (IS_PTR (type) && !IS_FUNC (type->next))
8016 p_type = DCL_TYPE (type);
8020 /* we have to go by the storage class */
8021 p_type = PTR_TYPE (SPEC_OCLS (etype));
8024 /* now that we have the pointer type we assign
8025 the pointer values */
8031 genNearPointerSet (right, result, ic, pi);
8035 genPagedPointerSet (right, result, ic, pi);
8039 genFarPointerSet (right, result, ic, pi);
8043 genGenPointerSet (right, result, ic, pi);
8049 /*-----------------------------------------------------------------*/
8050 /* genIfx - generate code for Ifx statement */
8051 /*-----------------------------------------------------------------*/
8053 genIfx (iCode * ic, iCode * popIc)
8055 operand *cond = IC_COND (ic);
8058 D(emitcode (";", "genIfx"));
8060 aopOp (cond, ic, FALSE);
8062 /* get the value into acc */
8063 if (AOP_TYPE (cond) != AOP_CRY)
8067 /* the result is now in the accumulator */
8068 freeAsmop (cond, NULL, ic, TRUE);
8070 /* if there was something to be popped then do it */
8074 /* if the condition is a bit variable */
8075 if (isbit && IS_ITEMP (cond) &&
8077 genIfxJump (ic, SPIL_LOC (cond)->rname);
8078 else if (isbit && !IS_ITEMP (cond))
8079 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8081 genIfxJump (ic, "a");
8086 /*-----------------------------------------------------------------*/
8087 /* genAddrOf - generates code for address of */
8088 /*-----------------------------------------------------------------*/
8090 genAddrOf (iCode * ic)
8092 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8095 D(emitcode (";", "genAddrOf"));
8097 aopOp (IC_RESULT (ic), ic, FALSE);
8099 /* if the operand is on the stack then we
8100 need to get the stack offset of this
8104 /* if it has an offset then we need to compute
8108 emitcode ("mov", "a,_bp");
8109 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8110 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8114 /* we can just move _bp */
8115 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8117 /* fill the result with zero */
8118 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8123 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8129 /* object not on stack then we need the name */
8130 size = AOP_SIZE (IC_RESULT (ic));
8135 char s[SDCC_NAME_MAX];
8137 sprintf (s, "#(%s >> %d)",
8141 sprintf (s, "#%s", sym->rname);
8142 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8146 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8150 /*-----------------------------------------------------------------*/
8151 /* genFarFarAssign - assignment when both are in far space */
8152 /*-----------------------------------------------------------------*/
8154 genFarFarAssign (operand * result, operand * right, iCode * ic)
8156 int size = AOP_SIZE (right);
8160 D(emitcode (";", "genFarFarAssign"));
8162 /* first push the right side on to the stack */
8165 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8167 emitcode ("push", "acc");
8170 freeAsmop (right, NULL, ic, FALSE);
8171 /* now assign DPTR to result */
8172 aopOp (result, ic, FALSE);
8173 size = AOP_SIZE (result);
8176 emitcode ("pop", "acc");
8177 aopPut (AOP (result), "a", --offset);
8179 freeAsmop (result, NULL, ic, FALSE);
8183 /*-----------------------------------------------------------------*/
8184 /* genAssign - generate code for assignment */
8185 /*-----------------------------------------------------------------*/
8187 genAssign (iCode * ic)
8189 operand *result, *right;
8191 unsigned long lit = 0L;
8193 D(emitcode(";","genAssign"));
8195 result = IC_RESULT (ic);
8196 right = IC_RIGHT (ic);
8198 /* if they are the same */
8199 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8202 aopOp (right, ic, FALSE);
8204 /* special case both in far space */
8205 if (AOP_TYPE (right) == AOP_DPTR &&
8206 IS_TRUE_SYMOP (result) &&
8207 isOperandInFarSpace (result))
8210 genFarFarAssign (result, right, ic);
8214 aopOp (result, ic, TRUE);
8216 /* if they are the same registers */
8217 if (sameRegs (AOP (right), AOP (result)))
8220 /* if the result is a bit */
8221 if (AOP_TYPE (result) == AOP_CRY)
8224 /* if the right size is a literal then
8225 we know what the value is */
8226 if (AOP_TYPE (right) == AOP_LIT)
8228 if (((int) operandLitValue (right)))
8229 aopPut (AOP (result), one, 0);
8231 aopPut (AOP (result), zero, 0);
8235 /* the right is also a bit variable */
8236 if (AOP_TYPE (right) == AOP_CRY)
8238 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8239 aopPut (AOP (result), "c", 0);
8245 aopPut (AOP (result), "a", 0);
8249 /* bit variables done */
8251 size = AOP_SIZE (result);
8253 if (AOP_TYPE (right) == AOP_LIT)
8254 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8256 (AOP_TYPE (result) != AOP_REG) &&
8257 (AOP_TYPE (right) == AOP_LIT) &&
8258 !IS_FLOAT (operandType (right)) &&
8261 emitcode ("clr", "a");
8264 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8265 aopPut (AOP (result), "a", size);
8267 aopPut (AOP (result),
8268 aopGet (AOP (right), size, FALSE, FALSE),
8276 aopPut (AOP (result),
8277 aopGet (AOP (right), offset, FALSE, FALSE),
8284 freeAsmop (right, NULL, ic, TRUE);
8285 freeAsmop (result, NULL, ic, TRUE);
8288 /*-----------------------------------------------------------------*/
8289 /* genJumpTab - genrates code for jump table */
8290 /*-----------------------------------------------------------------*/
8292 genJumpTab (iCode * ic)
8297 D(emitcode (";", "genJumpTab"));
8299 aopOp (IC_JTCOND (ic), ic, FALSE);
8300 /* get the condition into accumulator */
8301 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8303 /* multiply by three */
8304 emitcode ("add", "a,acc");
8305 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8306 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8308 jtab = newiTempLabel (NULL);
8309 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8310 emitcode ("jmp", "@a+dptr");
8311 emitcode ("", "%05d$:", jtab->key + 100);
8312 /* now generate the jump labels */
8313 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8314 jtab = setNextItem (IC_JTLABELS (ic)))
8315 emitcode ("ljmp", "%05d$", jtab->key + 100);
8319 /*-----------------------------------------------------------------*/
8320 /* genCast - gen code for casting */
8321 /*-----------------------------------------------------------------*/
8323 genCast (iCode * ic)
8325 operand *result = IC_RESULT (ic);
8326 sym_link *ctype = operandType (IC_LEFT (ic));
8327 sym_link *rtype = operandType (IC_RIGHT (ic));
8328 operand *right = IC_RIGHT (ic);
8331 D(emitcode(";", "genCast"));
8333 /* if they are equivalent then do nothing */
8334 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8337 aopOp (right, ic, FALSE);
8338 aopOp (result, ic, FALSE);
8340 /* if the result is a bit */
8341 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8342 if (IS_BITVAR(OP_SYMBOL(result)->type))
8344 /* if the right size is a literal then
8345 we know what the value is */
8346 if (AOP_TYPE (right) == AOP_LIT)
8348 if (((int) operandLitValue (right)))
8349 aopPut (AOP (result), one, 0);
8351 aopPut (AOP (result), zero, 0);
8356 /* the right is also a bit variable */
8357 if (AOP_TYPE (right) == AOP_CRY)
8359 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8360 aopPut (AOP (result), "c", 0);
8366 aopPut (AOP (result), "a", 0);
8370 /* if they are the same size : or less */
8371 if (AOP_SIZE (result) <= AOP_SIZE (right))
8374 /* if they are in the same place */
8375 if (sameRegs (AOP (right), AOP (result)))
8378 /* if they in different places then copy */
8379 size = AOP_SIZE (result);
8383 aopPut (AOP (result),
8384 aopGet (AOP (right), offset, FALSE, FALSE),
8392 /* if the result is of type pointer */
8397 sym_link *type = operandType (right);
8398 sym_link *etype = getSpec (type);
8400 /* pointer to generic pointer */
8401 if (IS_GENPTR (ctype))
8406 p_type = DCL_TYPE (type);
8409 if (SPEC_SCLS(etype)==S_REGISTER) {
8410 // let's assume it is a generic pointer
8413 /* we have to go by the storage class */
8414 p_type = PTR_TYPE (SPEC_OCLS (etype));
8418 /* the first two bytes are known */
8419 size = GPTRSIZE - 1;
8423 aopPut (AOP (result),
8424 aopGet (AOP (right), offset, FALSE, FALSE),
8428 /* the last byte depending on type */
8444 case PPOINTER: // what the fck is this?
8449 /* this should never happen */
8450 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8451 "got unknown pointer type");
8454 aopPut (AOP (result), l, GPTRSIZE - 1);
8458 /* just copy the pointers */
8459 size = AOP_SIZE (result);
8463 aopPut (AOP (result),
8464 aopGet (AOP (right), offset, FALSE, FALSE),
8471 /* so we now know that the size of destination is greater
8472 than the size of the source */
8473 /* we move to result for the size of source */
8474 size = AOP_SIZE (right);
8478 aopPut (AOP (result),
8479 aopGet (AOP (right), offset, FALSE, FALSE),
8484 /* now depending on the sign of the source && destination */
8485 size = AOP_SIZE (result) - AOP_SIZE (right);
8486 /* if unsigned or not an integral type */
8487 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8490 aopPut (AOP (result), zero, offset++);
8494 /* we need to extend the sign :{ */
8495 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8498 emitcode ("rlc", "a");
8499 emitcode ("subb", "a,acc");
8501 aopPut (AOP (result), "a", offset++);
8504 /* we are done hurray !!!! */
8507 freeAsmop (right, NULL, ic, TRUE);
8508 freeAsmop (result, NULL, ic, TRUE);
8512 /*-----------------------------------------------------------------*/
8513 /* genDjnz - generate decrement & jump if not zero instrucion */
8514 /*-----------------------------------------------------------------*/
8516 genDjnz (iCode * ic, iCode * ifx)
8522 D(emitcode (";", "genDjnz"));
8524 /* if the if condition has a false label
8525 then we cannot save */
8529 /* if the minus is not of the form
8531 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8532 !IS_OP_LITERAL (IC_RIGHT (ic)))
8535 if (operandLitValue (IC_RIGHT (ic)) != 1)
8538 /* if the size of this greater than one then no
8540 if (getSize (operandType (IC_RESULT (ic))) > 1)
8543 /* otherwise we can save BIG */
8544 lbl = newiTempLabel (NULL);
8545 lbl1 = newiTempLabel (NULL);
8547 aopOp (IC_RESULT (ic), ic, FALSE);
8549 if (AOP_NEEDSACC(IC_RESULT(ic)))
8551 /* If the result is accessed indirectly via
8552 * the accumulator, we must explicitly write
8553 * it back after the decrement.
8555 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8557 if (strcmp(rByte, "a"))
8559 /* Something is hopelessly wrong */
8560 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8561 __FILE__, __LINE__);
8562 /* We can just give up; the generated code will be inefficient,
8565 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8568 emitcode ("dec", "%s", rByte);
8569 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8570 emitcode ("jnz", "%05d$", lbl->key + 100);
8572 else if (IS_AOP_PREG (IC_RESULT (ic)))
8574 emitcode ("dec", "%s",
8575 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8576 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8577 emitcode ("jnz", "%05d$", lbl->key + 100);
8581 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8584 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8585 emitcode ("", "%05d$:", lbl->key + 100);
8586 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8587 emitcode ("", "%05d$:", lbl1->key + 100);
8589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8594 /*-----------------------------------------------------------------*/
8595 /* genReceive - generate code for a receive iCode */
8596 /*-----------------------------------------------------------------*/
8598 genReceive (iCode * ic)
8600 D(emitcode (";", "genReceive"));
8602 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8603 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8604 IS_TRUE_SYMOP (IC_RESULT (ic))))
8607 int size = getSize (operandType (IC_RESULT (ic)));
8608 int offset = fReturnSizeMCS51 - size;
8611 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8612 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8615 aopOp (IC_RESULT (ic), ic, FALSE);
8616 size = AOP_SIZE (IC_RESULT (ic));
8620 emitcode ("pop", "acc");
8621 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8628 aopOp (IC_RESULT (ic), ic, FALSE);
8630 assignResultValue (IC_RESULT (ic));
8633 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8636 /*-----------------------------------------------------------------*/
8637 /* gen51AggregateAssign - copy complete array's or structures */
8638 /*-----------------------------------------------------------------*/
8639 void gen51AggregateAssign(iCode *ic) {
8640 operand *left=IC_LEFT(ic);
8641 operand *right=IC_RIGHT(ic);
8642 char *fromName=OP_SYMBOL(right)->rname;
8643 char *toName=OP_SYMBOL(left)->rname;
8644 int fromSize=getSize(OP_SYMBOL(right)->type);
8645 int toSize=getSize(OP_SYMBOL(left)->type);
8648 D(emitcode (";", "gen51AggregateAssign"));
8650 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8651 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8652 // well, this code isn't used yet from anywhere else as for initialising
8653 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8657 if (fromSize!=toSize) {
8658 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8659 ic->filename, ic->lineno);
8664 // use the generic memcpy() for now
8665 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8666 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8667 emitcode ("mov", "a,#%s", fromName);
8668 emitcode ("movx", "@dptr,a");
8669 emitcode ("inc", "dptr");
8670 emitcode ("mov", "a,#(%s>>8)", fromName);
8671 emitcode ("movx", "@dptr,a");
8672 emitcode ("inc", "dptr");
8673 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8674 emitcode ("movx", "@dptr,a");
8675 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8676 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8677 emitcode ("movx", "@dptr,a");
8678 emitcode ("inc", "dptr");
8679 emitcode ("mov", "a,#(%d>>8)", count);
8680 emitcode ("movx", "@dptr,a");
8681 emitcode ("mov", "dptr,#%s", toName);
8682 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8683 emitcode ("lcall", "_memcpy");
8685 // more efficient, but will require the native_memcpy_cs2xs
8686 emitcode ("mov", "r0,#%s", fromName);
8687 emitcode ("mov", "r1,#(%s>>8)", fromName);
8688 emitcode ("mov", "r2,#%s", toName);
8689 emitcode ("mov", "r3,#(%s>>8)", toName);
8690 emitcode ("mov", "r4,#%d", count);
8691 emitcode ("mov", "r5,#(%d>>8)", count);
8692 emitcode ("lcall", "_native_memcpy_cs2xs");
8696 /*-----------------------------------------------------------------*/
8697 /* gen51Code - generate code for 8051 based controllers */
8698 /*-----------------------------------------------------------------*/
8700 gen51Code (iCode * lic)
8705 lineHead = lineCurr = NULL;
8707 /* print the allocation information */
8709 printAllocInfo (currFunc, codeOutFile);
8710 /* if debug information required */
8711 /* if (options.debug && currFunc) { */
8712 if (options.debug && currFunc)
8714 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8716 if (IS_STATIC (currFunc->etype))
8717 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8719 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8722 /* stack pointer name */
8723 if (options.useXstack)
8729 for (ic = lic; ic; ic = ic->next)
8732 if (cln != ic->lineno)
8737 emitcode ("", "C$%s$%d$%d$%d ==.",
8738 FileBaseName (ic->filename), ic->lineno,
8739 ic->level, ic->block);
8742 emitcode (";", "%s %d", ic->filename, ic->lineno);
8745 /* if the result is marked as
8746 spilt and rematerializable or code for
8747 this has already been generated then
8749 if (resultRemat (ic) || ic->generated)
8752 /* depending on the operation */
8772 /* IPOP happens only when trying to restore a
8773 spilt live range, if there is an ifx statement
8774 following this pop then the if statement might
8775 be using some of the registers being popped which
8776 would destory the contents of the register so
8777 we need to check for this condition and handle it */
8779 ic->next->op == IFX &&
8780 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8781 genIfx (ic->next, ic);
8799 genEndFunction (ic);
8819 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8836 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8840 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8847 /* note these two are xlated by algebraic equivalence
8848 during parsing SDCC.y */
8849 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8850 "got '>=' or '<=' shouldn't have come here");
8854 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8866 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8870 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8874 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8901 case GET_VALUE_AT_ADDRESS:
8902 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8906 if (POINTER_SET (ic))
8907 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8933 addSet (&_G.sendSet, ic);
8937 gen51AggregateAssign(ic);
8946 /* now we are ready to call the
8947 peep hole optimizer */
8948 if (!options.nopeep)
8949 peepHole (&lineHead);
8951 /* now do the actual printing */
8952 printLine (lineHead, codeOutFile);