1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
34 #ifdef HAVE_SYS_ISA_DEFS_H
35 #include <sys/isa_defs.h>
40 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
41 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
42 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
48 #include "SDCCpeeph.h"
52 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "0x00";
61 static char *one = "0x01";
65 {"r16", "r17", "r18", "r19"};
66 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
67 char **fAVRReturn = fReturnAVR;
68 static short rbank = -1;
69 static char *larray[4] =
70 {"lo8", "hi8", "hlo8", "hhi8"};
71 static char *tscr[4] =
72 {"r0", "r1", "r24", "r25"};
83 extern int avr_ptrRegReq;
85 extern FILE *codeOutFile;
86 static void saverbank (int, iCode *, bool);
87 #define RESULTONSTACK(x) \
88 (IC_RESULT(x) && IC_RESULT(x)->aop && \
89 IC_RESULT(x)->aop->type == AOP_STK )
91 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
92 #define CLRC emitcode("clc","")
93 #define SETC emitcode("stc","")
95 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
100 static unsigned char SLMask[] =
101 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] =
104 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
105 0x07, 0x03, 0x01, 0x00};
112 /*-----------------------------------------------------------------*/
113 /* emitcode - writes the code into a file : for now it is simple */
114 /*-----------------------------------------------------------------*/
116 emitcode (char *inst, char *fmt,...)
119 char lb[MAX_INLINEASM];
126 sprintf (lb, "%s\t", inst);
128 sprintf (lb, "%s", inst);
129 vsprintf (lb + (strlen (lb)), fmt, ap);
132 vsprintf (lb, fmt, ap);
134 while (isspace (*lbp)) lbp++;
137 lineCurr = (lineCurr ?
138 connectLine (lineCurr, newLineNode (lb)) :
139 (lineHead = newLineNode (lb)));
140 lineCurr->isInline = _G.inLine;
141 lineCurr->isDebug = _G.debugLine;
145 /*-----------------------------------------------------------------*/
146 /* getFreePtr - returns X or Z whichever is free or can be pushed */
147 /*-----------------------------------------------------------------*/
149 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
151 bool xiu = FALSE, ziu = FALSE;
152 bool xou = FALSE, zou = FALSE;
154 /* the logic: if x & z used in the instruction
155 then we are in trouble otherwise */
157 /* first check if x & z are used by this
158 instruction, in which case we are in trouble */
159 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
160 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
164 xou = bitVectBitValue (ic->rMask, X_IDX);
165 zou = bitVectBitValue (ic->rMask, Z_IDX);
167 /* if no usage of Z then return it */
169 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
170 (*aopp)->type = AOP_Z;
172 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
173 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
176 /* if no usage of X then return it */
177 if (!xiu && !xou && !zonly)
179 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
180 (*aopp)->type = AOP_X;
182 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
183 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
186 /* if z not used then */
190 /* push it if not already pushed */
193 emitcode ("push", "%s",
194 avr_regWithIdx (R30_IDX)->dname);
195 emitcode ("push", "%s",
196 avr_regWithIdx (R31_IDX)->dname);
200 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
201 (*aopp)->type = AOP_Z;
202 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
203 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
206 /* now we know they both have usage */
207 /* if x not used in this instruction */
210 /* push it if not already pushed */
213 emitcode ("push", "%s",
214 avr_regWithIdx (R26_IDX)->dname);
215 emitcode ("push", "%s",
216 avr_regWithIdx (R27_IDX)->dname);
220 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
221 (*aopp)->type = AOP_X;
223 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
224 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
229 /* I said end of world but not quite end of world yet */
230 /* if this is a result then we can push it on the stack */
233 (*aopp)->type = AOP_STK;
238 /* other wise this is true end of the world */
239 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
240 "getFreePtr should never reach here");
244 /*-----------------------------------------------------------------*/
245 /* newAsmop - creates a new asmOp */
246 /*-----------------------------------------------------------------*/
248 newAsmop (short type)
252 aop = Safe_calloc (1, sizeof (asmop));
257 /*-----------------------------------------------------------------*/
258 /* pointerCode - returns the code for a pointer type */
259 /*-----------------------------------------------------------------*/
261 pointerCode (sym_link * etype)
264 return PTR_TYPE (SPEC_OCLS (etype));
268 /*-----------------------------------------------------------------*/
269 /* aopForSym - for a true symbol */
270 /*-----------------------------------------------------------------*/
272 aopForSym (iCode * ic, symbol * sym, bool result)
275 memmap *space = SPEC_OCLS (sym->etype);
277 /* if already has one */
281 /* assign depending on the storage class */
282 /* if it is on the stack */
285 sym->aop = aop = newAsmop (0);
286 aop->size = getSize (sym->type);
288 /* we can use std / ldd instruction */
289 if (sym->stack > 0 && (sym->stack + getSize (sym->type) - 1) <= 63)
291 aop->type = AOP_STK_D;
292 aop->aopu.aop_stk = sym->stack;
296 /* otherwise get a free pointer register X/Z */
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
299 /* now assign the address of the variable to
300 the pointer register */
301 if (aop->type != AOP_STK)
303 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
306 if ((sym->stack - _G.nRegsSaved) > -63)
308 emitcode ("sbiw", "%s,0x%02x",
309 aop->aopu.aop_ptr->name,
310 (sym->stack - _G.nRegsSaved));
314 emitcode ("subi", "%s,lo8(%d)", aop->aopu.aop_ptr->name,
315 sym->stack - _G.nRegsSaved);
316 emitcode ("sbci", "%s,hi8(%d)", aop->aop_ptr2->name,
317 sym->stack - _G.nRegsSaved);
322 if (sym->stack <= 63)
324 emitcode ("adiw", "%s,0x%02x", aop->aopu.aop_ptr->name, sym->stack);
328 emitcode ("subi", "%s,lo8(-%d)", aop->aopu.aop_ptr->name, sym->stack);
329 emitcode ("sbci", "%s,hi8(-%d)", aop->aop_ptr2->name, sym->stack);
336 /* if in bit space */
337 if (IN_BITSPACE (space))
339 sym->aop = aop = newAsmop (AOP_CRY);
340 aop->aopu.aop_dir = sym->rname;
341 aop->size = getSize (sym->type);
344 /* if it is in direct space */
345 if (IN_DIRSPACE (space))
347 sym->aop = aop = newAsmop (AOP_DIR);
348 aop->aopu.aop_dir = sym->rname;
349 aop->size = getSize (sym->type);
353 /* special case for a function */
354 if (IS_FUNC (sym->type))
356 sym->aop = aop = newAsmop (AOP_IMMD);
357 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
358 strcpy (aop->aopu.aop_immd, sym->rname);
359 aop->size = FPTRSIZE;
363 /* only remaining is code / eeprom which will need pointer reg */
364 /* if it is in code space */
366 sym->aop = aop = newAsmop (0);
368 if (IN_CODESPACE (space))
371 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
372 aop->size = getSize (sym->type);
373 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
374 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
379 /*-----------------------------------------------------------------*/
380 /* aopForRemat - rematerialzes an object */
381 /*-----------------------------------------------------------------*/
383 aopForRemat (symbol * sym)
385 iCode *ic = sym->rematiCode;
386 asmop *aop = newAsmop (AOP_IMMD);
392 val += (int) operandLitValue (IC_RIGHT (ic));
393 else if (ic->op == '-')
394 val -= (int) operandLitValue (IC_RIGHT (ic));
398 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
402 sprintf (buffer, "(%s %c 0x%04x)",
403 OP_SYMBOL (IC_LEFT (ic))->rname,
404 val >= 0 ? '+' : '-',
407 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
409 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
410 strcpy (aop->aopu.aop_immd, buffer);
414 /*-----------------------------------------------------------------*/
415 /* regsInCommon - two operands have some registers in common */
416 /*-----------------------------------------------------------------*/
418 regsInCommon (operand * op1, operand * op2)
423 /* if they have registers in common */
424 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
427 sym1 = OP_SYMBOL (op1);
428 sym2 = OP_SYMBOL (op2);
430 if (sym1->nRegs == 0 || sym2->nRegs == 0)
433 for (i = 0; i < sym1->nRegs; i++)
439 for (j = 0; j < sym2->nRegs; j++)
444 if (sym2->regs[j] == sym1->regs[i])
452 /*-----------------------------------------------------------------*/
453 /* operandsEqu - equivalent */
454 /*-----------------------------------------------------------------*/
456 operandsEqu (operand * op1, operand * op2)
460 /* if they not symbols */
461 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
464 sym1 = OP_SYMBOL (op1);
465 sym2 = OP_SYMBOL (op2);
467 /* if both are itemps & one is spilt
468 and the other is not then false */
469 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
470 sym1->isspilt != sym2->isspilt)
473 /* if they are the same */
477 if (strcmp (sym1->rname, sym2->rname) == 0)
481 /* if left is a tmp & right is not */
482 if (IS_ITEMP (op1) &&
485 (sym1->usl.spillLoc == sym2))
488 if (IS_ITEMP (op2) &&
492 (sym2->usl.spillLoc == sym1))
498 /*-----------------------------------------------------------------*/
499 /* sameRegs - two asmops have the same registers */
500 /*-----------------------------------------------------------------*/
502 sameRegs (asmop * aop1, asmop * aop2)
509 if (aop1->type != AOP_REG ||
510 aop2->type != AOP_REG)
513 if (aop1->size != aop2->size)
516 for (i = 0; i < aop1->size; i++)
517 if (aop1->aopu.aop_reg[i] !=
518 aop2->aopu.aop_reg[i])
524 /*-----------------------------------------------------------------*/
525 /* isRegPair - for size 2 if this operand has a register pair */
526 /*-----------------------------------------------------------------*/
528 isRegPair (asmop * aop)
530 if (!aop || aop->size != 2)
532 if (aop->type == AOP_X || aop->type == AOP_Z)
534 if (aop->type != AOP_REG)
536 if ((aop->aopu.aop_reg[1]->rIdx -
537 aop->aopu.aop_reg[0]->rIdx) == 1)
542 /*-----------------------------------------------------------------*/
543 /* aopOp - allocates an asmop for an operand : */
544 /*-----------------------------------------------------------------*/
546 aopOp (operand * op, iCode * ic, bool result)
555 /* if this a literal */
556 if (IS_OP_LITERAL (op))
558 op->aop = aop = newAsmop (AOP_LIT);
559 aop->aopu.aop_lit = op->operand.valOperand;
560 aop->size = getSize (operandType (op));
564 /* if already has a asmop then continue */
568 /* if the underlying symbol has a aop */
569 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
571 op->aop = OP_SYMBOL (op)->aop;
575 /* if this is a true symbol */
576 if (IS_TRUE_SYMOP (op))
578 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
582 /* this is a temporary : this has
588 e) can be a return use only */
590 sym = OP_SYMBOL (op);
593 /* if the type is a conditional */
594 if (sym->regType == REG_CND)
596 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
601 /* if it is spilt then two situations
603 b) has a spill location */
604 if (sym->isspilt || sym->nRegs == 0)
607 /* rematerialize it NOW */
610 sym->aop = op->aop = aop =
612 aop->size = getSize (sym->type);
618 assert ("ACC_USE cannot happen in AVR\n");
624 aop = op->aop = sym->aop = newAsmop (AOP_STR);
625 aop->size = getSize (sym->type);
626 for (i = 0; i < (int) fAVRReturnSize; i++)
627 aop->aopu.aop_str[i] = fAVRReturn[i];
631 /* else spill location */
632 sym->aop = op->aop = aop =
633 aopForSym (ic, sym->usl.spillLoc, result);
634 aop->size = getSize (sym->type);
638 /* must be in a register */
639 sym->aop = op->aop = aop = newAsmop (AOP_REG);
640 aop->size = sym->nRegs;
641 for (i = 0; i < sym->nRegs; i++)
642 aop->aopu.aop_reg[i] = sym->regs[i];
645 /*-----------------------------------------------------------------*/
646 /* freeAsmop - free up the asmop given to an operand */
647 /*----------------------------------------------------------------*/
649 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
666 /* depending on the asmop type only three cases need work AOP_RO
667 , AOP_R1 && AOP_STK */
675 emitcode ("pop", "r26");
676 emitcode ("pop", "r27");
680 bitVectUnSetBit (ic->rUsed, X_IDX);
688 emitcode ("pop", "r30");
689 emitcode ("pop", "r31");
693 bitVectUnSetBit (ic->rUsed, Z_IDX);
699 int stk = aop->aopu.aop_stk + aop->size;
700 bitVectUnSetBit (ic->rUsed, X_IDX);
701 bitVectUnSetBit (ic->rUsed, Z_IDX);
703 getFreePtr (ic, &aop, FALSE, 0);
705 emitcode ("movw", "%s,r28");
708 if (stk <= 63 && stk > 0)
710 emitcode ("adiw", "%s,0x%02x", aop->aopu.aop_ptr->name, stk + 1);
714 emitcode ("subi", "%s,lo8(%d)", aop->aopu.aop_ptr->name, -(stk + 1));
715 emitcode ("sbci", "%s,hi8(%d)", aop->aop_ptr2->name, -(stk + 1));
721 emitcode ("pop", "r24");
722 emitcode ("st", "-%s,r24", aop->type == AOP_X ? "X" : "Z");
727 freeAsmop (op, NULL, ic, TRUE);
730 emitcode ("pop", "r26");
731 emitcode ("pop", "r27");
737 emitcode ("pop", "r30");
738 emitcode ("pop", "r31");
745 /* all other cases just dealloc */
751 OP_SYMBOL (op)->aop = NULL;
752 /* if the symbol has a spill */
754 SPIL_LOC (op)->aop = NULL;
759 /*-----------------------------------------------------------------*/
760 /* aopGet - for fetching value of the aop */
761 /*-----------------------------------------------------------------*/
763 aopGet (asmop * aop, int offset)
768 /* offset is greater than
770 if (offset > (aop->size - 1) &&
771 aop->type != AOP_LIT)
774 /* depending on type */
779 if (offset > aop->coff)
781 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name, offset - aop->coff);
784 if (offset < aop->coff)
786 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
790 emitcode ("ld", "%s,x",
791 (rs = ((offset & 1) ? "r25" : "r24")));
797 if (offset > aop->coff)
799 emitcode ("adiw", "r30,%d", offset - aop->coff);
803 emitcode ("sbiw", "r30,%d", aop->coff - offset);
805 emitcode ("lpm", "%s,z", (rs = ((offset & 1) ? "r25" : "r24")));
810 if (offset > aop->coff)
812 emitcode ("ldd", "%s,z+%d", (rs = ((offset & 1) ? "r25" : "r24")),
817 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
819 emitcode ("ld", "%s,z", (rs = ((offset & 1) ? "r25" : "r24")));
826 emitcode ("lds", "%s,(%s)+%d",
827 (rs = ((offset & 1) ? "r25" : "r24")),
828 aop->aopu.aop_immd, offset);
832 emitcode ("lds", "%s,(%s)+%d",
833 (rs = ((offset & 1) ? "r25" : "r24")),
834 aop->aopu.aop_dir, offset);
838 return aop->aopu.aop_reg[offset]->name;
841 assert ("cannot be in bit space AOP_CRY\n");
845 s = aopLiteral (aop->aopu.aop_lit, offset);
846 emitcode ("ldi", "%s,lo8(%s)", (rs = ((offset & 1) ? "r24" : "r25")), s);
851 return aop->aopu.aop_str[offset];
854 emitcode ("ldd", "%s,Y+%d",
855 (rs = ((offset & 1) ? "r25" : "r24")),
856 aop->aopu.aop_stk + offset);
860 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
861 "aopget got unsupported aop->type");
864 /*-----------------------------------------------------------------*/
865 /* aopPut - puts a string for a aop */
866 /*-----------------------------------------------------------------*/
868 aopPut (asmop * aop, char *s, int offset)
872 if (aop->size && offset > (aop->size - 1))
874 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
875 "aopPut got offset > aop->size");
879 /* will assign value to value */
880 /* depending on where it is ofcourse */
886 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
890 sprintf (d, "%s", aop->aopu.aop_dir);
893 emitcode ("sts", "%s,%s", d, s);
897 if (toupper (*s) != 'R')
901 emitcode ("clr", "%s", aop->aopu.aop_reg[offset]->name);
905 emitcode ("ldi", "r25,%s", s);
906 emitcode ("mov", "%s,r35", aop->aopu.aop_reg[offset]->name);
911 if (strcmp (aop->aopu.aop_reg[offset]->name, s))
913 emitcode ("mov", "%s,%s", aop->aopu.aop_reg[offset]->name, s);
919 if (offset > aop->coff)
921 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name, offset - aop->coff);
924 if (offset < aop->coff)
926 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
930 emitcode ("st", "x,%s", s);
936 if (offset > aop->coff)
938 emitcode ("adiw", "r30,%d", offset - aop->coff);
942 emitcode ("sbiw", "r30,%d", aop->coff - offset);
944 emitcode ("lpm", "%s,z", s);
949 if (offset > aop->coff)
951 emitcode ("sdd", "z+%d,%s", offset - aop->coff, s);
955 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
957 emitcode ("ld", "%s,z", s);
963 emitcode ("push", "%s", s);
967 /* if used only for a condition code check */
968 assert (toupper (*s) == 'R');
971 emitcode ("xrl", "r0,r0");
972 emitcode ("cpi", "%s,0", s);
976 emitcode ("cpc", "r0,%s", s);
982 if (strcmp (aop->aopu.aop_str[offset], s))
983 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
987 emitcode ("std", "y+%d,%s", offset, s);
991 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
992 "aopPut got unsupported aop->type");
998 /*-----------------------------------------------------------------*/
999 /* reAdjustPreg - points a register back to where it should */
1000 /*-----------------------------------------------------------------*/
1002 reAdjustPreg (asmop * aop)
1007 if ((size = aop->size) <= 1)
1014 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
1020 #define AOP(op) op->aop
1021 #define AOP_TYPE(op) AOP(op)->type
1022 #define AOP_SIZE(op) AOP(op)->size
1023 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1024 AOP_TYPE(x) == AOP_Z))
1025 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1026 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
1027 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
1029 /*-----------------------------------------------------------------*/
1030 /* genNotFloat - generates not for float operations */
1031 /*-----------------------------------------------------------------*/
1033 genNotFloat (operand * op, operand * res)
1039 /* we will put 127 in the first byte of
1041 aopPut (AOP (res), "127", 0);
1042 size = AOP_SIZE (op) - 1;
1045 l = aopGet (op->aop, offset++);
1050 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1052 tlbl = newiTempLabel (NULL);
1054 tlbl = newiTempLabel (NULL);
1055 aopPut (res->aop, zero, 1);
1056 emitcode ("cpi", "r0,0");
1057 emitcode ("breq", "L%05d", tlbl->key);
1058 aopPut (res->aop, one, 1);
1059 emitcode ("", "L%05d:", tlbl->key);
1061 size = res->aop->size - 2;
1063 /* put zeros in the rest */
1065 aopPut (res->aop, zero, offset++);
1068 /*-----------------------------------------------------------------*/
1069 /* opIsGptr: returns non-zero if the passed operand is */
1070 /* a generic pointer type. */
1071 /*-----------------------------------------------------------------*/
1073 opIsGptr (operand * op)
1075 sym_link *type = operandType (op);
1077 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1084 /*-----------------------------------------------------------------*/
1085 /* getDataSize - get the operand data size */
1086 /*-----------------------------------------------------------------*/
1088 getDataSize (operand * op)
1091 size = AOP_SIZE (op);
1092 if (size == GPTRSIZE)
1094 sym_link *type = operandType (op);
1095 if (IS_GENPTR (type))
1097 /* generic pointer; arithmetic operations
1098 * should ignore the high byte (pointer type).
1106 /*-----------------------------------------------------------------*/
1107 /* outAcc - output Acc */
1108 /*-----------------------------------------------------------------*/
1110 outAcc (operand * result)
1113 size = getDataSize (result);
1116 aopPut (AOP (result), "r0", 0);
1119 /* unsigned or positive */
1122 aopPut (AOP (result), zero, offset++);
1127 /*-----------------------------------------------------------------*/
1128 /* outBitC - output a bit C */
1129 /*-----------------------------------------------------------------*/
1131 outBitC (operand * result)
1133 emitcode ("clr", "r0");
1134 emitcode ("rol", "r0");
1138 /*-----------------------------------------------------------------*/
1139 /* toBoolean - emit code for orl a,operator(sizeop) */
1140 /*-----------------------------------------------------------------*/
1142 toBoolean (operand * oper, char *r, bool clr)
1144 int size = AOP_SIZE (oper);
1147 emitcode ("clr", "%s", r);
1149 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1153 /*-----------------------------------------------------------------*/
1154 /* genNot - generate code for ! operation */
1155 /*-----------------------------------------------------------------*/
1160 sym_link *optype = operandType (IC_LEFT (ic));
1161 int size, offset = 1;
1163 /* assign asmOps to operand & result */
1164 aopOp (IC_LEFT (ic), ic, FALSE);
1165 aopOp (IC_RESULT (ic), ic, TRUE);
1167 /* if type float then do float */
1168 if (IS_FLOAT (optype))
1170 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1173 emitcode ("clr", "r0");
1174 tlbl = newiTempLabel (NULL);
1175 size = AOP_SIZE (IC_LEFT (ic));
1179 emitcode ("cpse", "%s,r0", aopGet (AOP (IC_LEFT (ic)), 0));
1186 emitcode ("cpc", "%s,r0", aopGet (AOP (IC_LEFT (ic)), offset));
1188 emitcode ("cpi", "%s,0", aopGet (AOP (IC_LEFT (ic)), offset));
1191 emitcode ("bne", "L%05d", tlbl->key);
1193 emitcode ("ldi", "r0,1");
1194 emitcode ("", "L%05d:", tlbl->key);
1195 aopPut (AOP (IC_RESULT (ic)), "r0", 0);
1196 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1199 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1203 /* release the aops */
1204 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1205 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1209 /*-----------------------------------------------------------------*/
1210 /* genCpl - generate code for complement */
1211 /*-----------------------------------------------------------------*/
1219 /* assign asmOps to operand & result */
1220 aopOp (IC_LEFT (ic), ic, FALSE);
1221 aopOp (IC_RESULT (ic), ic, TRUE);
1222 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1223 size = AOP_SIZE (IC_RESULT (ic));
1226 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1229 emitcode ("com", "%s", l);
1233 aopPut (AOP (IC_RESULT (ic)), l, offset);
1234 emitcode ("com", "%s", aopGet (AOP (IC_RESULT (ic)), offset));
1239 /* release the aops */
1240 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1241 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1244 /*-----------------------------------------------------------------*/
1245 /* genUminusFloat - unary minus for floating points */
1246 /*-----------------------------------------------------------------*/
1248 genUminusFloat (operand * op, operand * result)
1250 int size, offset = 0;
1252 /* for this we just need to flip the
1253 first it then copy the rest in place */
1254 size = AOP_SIZE (op) - 1;
1255 l = aopGet (AOP (op), 3);
1257 emitcode ("ldi", "r24,0x80");
1258 if (sameRegs (AOP (op), AOP (result)))
1260 emitcode ("eor", "%s,r24", l);
1264 aopPut (AOP (result), l, 3);
1265 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1269 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1274 /*-----------------------------------------------------------------*/
1275 /* genUminus - unary minus code generation */
1276 /*-----------------------------------------------------------------*/
1278 genUminus (iCode * ic)
1281 sym_link *optype, *rtype;
1285 aopOp (IC_LEFT (ic), ic, FALSE);
1286 aopOp (IC_RESULT (ic), ic, TRUE);
1288 optype = operandType (IC_LEFT (ic));
1289 rtype = operandType (IC_RESULT (ic));
1291 /* if float then do float stuff */
1292 if (IS_FLOAT (optype))
1294 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1298 /* otherwise subtract from zero */
1299 size = AOP_SIZE (IC_LEFT (ic));
1301 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1306 emitcode ("neg", "%s", aopGet (AOP (IC_LEFT (ic)), 0));
1310 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), 0), 0);
1311 emitcode ("neg", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
1319 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1322 aopPut (AOP (IC_RESULT (ic)), l, offset);
1323 l = aopGet (AOP (IC_RESULT (ic)), offset);
1326 emitcode ("com", "%s", l);
1328 emitcode ("neg", "%s", l);
1331 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1335 emitcode ("sbci", "%s,lo8(-1)", aopGet (AOP (IC_RESULT (ic)), offset++));
1339 /* if any remaining bytes in the result */
1340 /* we just need to propagate the sign */
1341 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1343 symbol *tlbl = newiTempLabel (NULL);
1344 emitcode ("clr", "r0");
1345 emitcode ("brcc", "L%05d", tlbl->key);
1346 emitcode ("com", "r0");
1347 emitcode ("", "L%05d:", tlbl->key);
1349 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1353 /* release the aops */
1354 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1355 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1358 /*-----------------------------------------------------------------*/
1359 /* assignResultValue - */
1360 /*-----------------------------------------------------------------*/
1362 assignResultValue (operand * oper)
1365 int size = AOP_SIZE (oper);
1368 aopPut (AOP (oper), fAVRReturn[offset], offset);
1373 /*-----------------------------------------------------------------*/
1374 /* saveZreg - if indirect call then save z-pointer register */
1375 /*-----------------------------------------------------------------*/
1377 saveZreg (iCode * ic)
1379 /* only if live accross this call */
1380 if (ic->regsSaved == 0 &&
1381 (bitVectBitValue (ic->rMask, R30_IDX) ||
1382 bitVectBitValue (ic->rMask, R31_IDX)))
1385 emitcode ("push", "r30");
1386 emitcode ("push", "r31");
1390 /*-----------------------------------------------------------------*/
1391 /* popZreg - restore values of zreg */
1392 /*-----------------------------------------------------------------*/
1394 popZreg (iCode * ic)
1398 emitcode ("pop", "r31");
1399 emitcode ("pop", "r30");
1403 /*-----------------------------------------------------------------*/
1404 /* genIpush - genrate code for pushing this gets a little complex */
1405 /*-----------------------------------------------------------------*/
1407 genIpush (iCode * ic)
1409 int size, offset = 0;
1415 /* and the item is spilt then do nothing */
1416 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1422 for (lic = ic->next; lic; lic = lic->next)
1423 if (lic->op == PCALL)
1429 /* this is a paramter push */
1430 aopOp (IC_LEFT (ic), ic, FALSE);
1431 size = AOP_SIZE (IC_LEFT (ic));
1434 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1435 emitcode ("push", "%s", l);
1438 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1441 /*-----------------------------------------------------------------*/
1442 /* genIpop - recover the registers: can happen only for spilling */
1443 /*-----------------------------------------------------------------*/
1445 genIpop (iCode * ic)
1450 /* if the temp was not pushed then */
1451 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1454 aopOp (IC_LEFT (ic), ic, FALSE);
1455 size = AOP_SIZE (IC_LEFT (ic));
1456 offset = (size - 1);
1458 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1460 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1463 /*-----------------------------------------------------------------*/
1464 /* genCall - generates a call statement */
1465 /*-----------------------------------------------------------------*/
1467 genCall (iCode * ic)
1470 /* if send set is not empty the assign */
1475 for (sic = setFirstItem (_G.sendSet); sic;
1476 sic = setNextItem (_G.sendSet))
1478 int size, offset = 0;
1479 aopOp (IC_LEFT (sic), sic, FALSE);
1480 size = AOP_SIZE (IC_LEFT (sic));
1483 char *l = aopGet (AOP (IC_LEFT (sic)), offset);
1485 sprintf (buffer, "r%d", rnum++);
1487 emitcode ("mov", "%s,%s", b, l);
1490 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1495 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1496 OP_SYMBOL (IC_LEFT (ic))->rname :
1497 OP_SYMBOL (IC_LEFT (ic))->name));
1499 /* if we need assign a result value */
1500 if ((IS_ITEMP (IC_RESULT (ic)) &&
1501 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1502 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1503 IS_TRUE_SYMOP (IC_RESULT (ic)))
1506 aopOp (IC_RESULT (ic), ic, FALSE);
1507 assignResultValue (IC_RESULT (ic));
1508 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1511 /* adjust the stack for parameters if required */
1512 if (IC_LEFT (ic)->parmBytes)
1514 if (IC_LEFT (ic)->parmBytes > 63)
1516 emitcode ("sbiw", "r28,%d", IC_LEFT (ic)->parmBytes);
1520 emitcode ("subi", "r28,lo8(%d)", IC_LEFT (ic)->parmBytes);
1521 emitcode ("sbci", "r29,hi8(%d)", IC_LEFT (ic)->parmBytes);
1527 /*-----------------------------------------------------------------*/
1528 /* genPcall - generates a call by pointer statement */
1529 /*-----------------------------------------------------------------*/
1531 genPcall (iCode * ic)
1537 aopOp (IC_LEFT (ic), ic, FALSE);
1538 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1539 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1540 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1542 /* if send set is not empty the assign */
1547 for (sic = setFirstItem (_G.sendSet); sic;
1548 sic = setNextItem (_G.sendSet))
1550 int size, offset = 0;
1551 aopOp (IC_LEFT (sic), sic, FALSE);
1552 size = AOP_SIZE (IC_LEFT (sic));
1555 char *l = aopGet (AOP (IC_LEFT (sic)), offset);
1557 sprintf (b, "r%d", rnum++);
1559 emitcode ("mov", "%s,%s", b, l);
1562 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1567 emitcode ("icall", "");
1569 /* if we need assign a result value */
1570 if ((IS_ITEMP (IC_RESULT (ic)) &&
1571 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1572 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1573 IS_TRUE_SYMOP (IC_RESULT (ic)))
1576 aopOp (IC_RESULT (ic), ic, FALSE);
1578 assignResultValue (IC_RESULT (ic));
1579 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1582 /* adjust the stack for parameters if
1584 if (IC_LEFT (ic)->parmBytes)
1587 if (IC_LEFT (ic)->parmBytes > 3)
1589 emitcode ("mov", "a,%s", spname);
1590 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
1591 emitcode ("mov", "%s,a", spname);
1594 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
1595 emitcode ("dec", "%s", spname);
1599 /* adjust the stack for parameters if required */
1600 if (IC_LEFT (ic)->parmBytes)
1602 if (IC_LEFT (ic)->parmBytes > 63)
1604 emitcode ("sbiw", "r28,%d", IC_LEFT (ic)->parmBytes);
1608 emitcode ("subi", "r28,lo8(%d)", IC_LEFT (ic)->parmBytes);
1609 emitcode ("sbci", "r29,hi8(%d)", IC_LEFT (ic)->parmBytes);
1616 /*-----------------------------------------------------------------*/
1617 /* resultRemat - result is rematerializable */
1618 /*-----------------------------------------------------------------*/
1620 resultRemat (iCode * ic)
1622 if (SKIP_IC (ic) || ic->op == IFX)
1625 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
1627 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1628 if (sym->remat && !POINTER_SET (ic))
1635 #if defined(__BORLANDC__) || defined(_MSC_VER)
1636 #define STRCASECMP stricmp
1638 #define STRCASECMP strcasecmp
1641 /*-----------------------------------------------------------------*/
1642 /* inExcludeList - return 1 if the string is in exclude Reg list */
1643 /*-----------------------------------------------------------------*/
1645 inExcludeList (char *s)
1649 if (options.excludeRegs[i] &&
1650 STRCASECMP (options.excludeRegs[i], "none") == 0)
1653 for (i = 0; options.excludeRegs[i]; i++)
1655 if (options.excludeRegs[i] &&
1656 STRCASECMP (s, options.excludeRegs[i]) == 0)
1662 /*-----------------------------------------------------------------*/
1663 /* genFunction - generated code for function entry */
1664 /*-----------------------------------------------------------------*/
1666 genFunction (iCode * ic)
1673 /* create the function header */
1674 emitcode (";", "-----------------------------------------");
1675 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1676 emitcode (";", "-----------------------------------------");
1678 emitcode ("", "%s:", sym->rname);
1679 fetype = getSpec (operandType (IC_LEFT (ic)));
1681 /* if critical function then turn interrupts off */
1682 if (SPEC_CRTCL (fetype))
1683 emitcode ("cli", "");
1685 if (IS_ISR (sym->etype))
1689 /* save the preserved registers that are used in this function */
1690 for (i = R2_IDX; i <= R15_IDX; i++)
1692 if (bitVectBitValue (sym->regsUsed, i))
1695 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1698 /* now for the pointer registers */
1699 if (bitVectBitValue (sym->regsUsed, R26_IDX))
1702 emitcode ("push", "r26");
1704 if (bitVectBitValue (sym->regsUsed, R27_IDX))
1707 emitcode ("push", "r27");
1709 if (bitVectBitValue (sym->regsUsed, R30_IDX))
1712 emitcode ("push", "r30");
1714 if (bitVectBitValue (sym->regsUsed, R31_IDX))
1717 emitcode ("push", "r31");
1719 /* adjust the stack for the function */
1722 emitcode ("push", "r28");
1723 emitcode ("push", "r29");
1724 emitcode ("in", "r28,__SP_L__");
1725 emitcode ("in", "r29,__SP_H__");
1726 if (sym->stack <= 63)
1728 emitcode ("sbiw", "r28,%d", sym->stack);
1732 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1733 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1735 emitcode ("out", "__SP_L__,r28");
1736 emitcode ("out", "__SP_H__,r29");
1740 /*-----------------------------------------------------------------*/
1741 /* genEndFunction - generates epilogue for functions */
1742 /*-----------------------------------------------------------------*/
1744 genEndFunction (iCode * ic)
1746 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1749 /* restore stack pointer */
1752 if (sym->stack <= 63)
1754 emitcode ("adiw", "r28,%d", sym->stack);
1758 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1759 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1761 emitcode ("out", "__SP_L__,r28");
1762 emitcode ("out", "__SP_H__,r29");
1764 /* pop frame pointer */
1765 emitcode ("pop", "r29");
1766 emitcode ("pop", "r28");
1768 /* restore preserved registers */
1769 if (bitVectBitValue (sym->regsUsed, R31_IDX))
1772 emitcode ("pop", "r31");
1774 if (bitVectBitValue (sym->regsUsed, R30_IDX))
1777 emitcode ("pop", "r30");
1779 if (bitVectBitValue (sym->regsUsed, R27_IDX))
1782 emitcode ("push", "r27");
1784 if (bitVectBitValue (sym->regsUsed, R26_IDX))
1787 emitcode ("push", "r26");
1789 for (i = R15_IDX; i >= R2_IDX; i--)
1791 if (bitVectBitValue (sym->regsUsed, i))
1794 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1798 if (SPEC_CRTCL (sym->etype))
1799 emitcode ("sti", "");
1801 if (IS_ISR (sym->etype))
1803 emitcode ("rti", "");
1807 emitcode ("ret", "");
1812 /*-----------------------------------------------------------------*/
1813 /* genRet - generate code for return statement */
1814 /*-----------------------------------------------------------------*/
1818 int size, offset = 0;
1820 /* if we have no return value then
1821 just generate the "ret" */
1825 /* we have something to return then
1826 move the return value into place */
1827 aopOp (IC_LEFT (ic), ic, FALSE);
1828 size = AOP_SIZE (IC_LEFT (ic));
1832 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
1834 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset], larray[offset],
1835 (int) floatFromVal (AOP (IC_LEFT (ic))->aopu.aop_lit), offset);
1840 l = aopGet (AOP (IC_LEFT (ic)), offset);
1841 if (strcmp (fAVRReturn[offset], l))
1842 emitcode ("mov", "%s,%s", fAVRReturn[offset], l);
1847 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1850 /* generate a jump to the return label
1851 if the next is not the return statement */
1852 if (!(ic->next && ic->next->op == LABEL &&
1853 IC_LABEL (ic->next) == returnLabel))
1855 emitcode ("rjmp", "L%05d", returnLabel->key);
1859 /*-----------------------------------------------------------------*/
1860 /* genLabel - generates a label */
1861 /*-----------------------------------------------------------------*/
1863 genLabel (iCode * ic)
1865 /* special case never generate */
1866 if (IC_LABEL (ic) == entryLabel)
1869 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1872 /*-----------------------------------------------------------------*/
1873 /* genGoto - generates a ljmp */
1874 /*-----------------------------------------------------------------*/
1876 genGoto (iCode * ic)
1878 emitcode ("rjmp", "L%05d:", (IC_LABEL (ic)->key + 100));
1881 /*-----------------------------------------------------------------*/
1882 /* findLabelBackwards: walks back through the iCode chain looking */
1883 /* for the given label. Returns number of iCode instructions */
1884 /* between that label and given ic. */
1885 /* Returns zero if label not found. */
1886 /*-----------------------------------------------------------------*/
1888 findLabelBackwards (iCode * ic, int key)
1897 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
1899 /* printf("findLabelBackwards = %d\n", count); */
1907 /*-----------------------------------------------------------------*/
1908 /* genPlusIncr :- does addition with increment if possible */
1909 /*-----------------------------------------------------------------*/
1911 genPlusIncr (iCode * ic)
1913 unsigned int icount;
1915 /* will try to generate an increment */
1916 /* if the right side is not a literal
1918 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1921 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
1923 /* if the sizes are greater than 2 or they are not the same regs
1925 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1928 /* so we know LEFT & RESULT in the same registers and add
1930 /* for short & char types */
1931 if (AOP_SIZE (IC_RESULT (ic)) < 2)
1935 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0));
1938 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_LEFT (ic)), 0), -icount);
1942 if (AOP_SIZE (IC_RESULT (ic)) <= 3)
1944 /* if register pair and starts with 26/30 then adiw */
1945 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0 && icount < 64 &&
1946 (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1947 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX)))
1949 emitcode ("adiw", "%s,%d", aopGet (AOP (IC_RESULT (ic)), 0), icount);
1954 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0), -icount);
1955 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1), -icount);
1959 /* for 32 bit longs */
1960 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0), -icount);
1961 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1), -icount);
1962 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2), -icount);
1963 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3), -icount);
1968 /* This is the pure and virtuous version of this code.
1969 * I'm pretty certain it's right, but not enough to toss the old
1973 adjustArithmeticResult (iCode * ic)
1975 if (opIsGptr (IC_RESULT (ic)) &&
1976 opIsGptr (IC_LEFT (ic)) &&
1977 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
1979 aopPut (AOP (IC_RESULT (ic)),
1980 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1984 if (opIsGptr (IC_RESULT (ic)) &&
1985 opIsGptr (IC_RIGHT (ic)) &&
1986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
1988 aopPut (AOP (IC_RESULT (ic)),
1989 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1993 if (opIsGptr (IC_RESULT (ic)) &&
1994 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1995 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1996 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1997 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2000 sprintf (buffer, "%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2001 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2005 /*-----------------------------------------------------------------*/
2006 /* genPlus - generates code for addition */
2007 /*-----------------------------------------------------------------*/
2009 genPlus (iCode * ic)
2011 int size, offset = 0;
2015 /* special cases :- */
2017 aopOp (IC_LEFT (ic), ic, FALSE);
2018 aopOp (IC_RIGHT (ic), ic, FALSE);
2019 aopOp (IC_RESULT (ic), ic, TRUE);
2021 /* if I can do an increment instead
2022 of add then GOOD for ME */
2023 if (genPlusIncr (ic) == TRUE)
2026 size = getDataSize (IC_RESULT (ic));
2027 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2032 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), offset), offset);
2034 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2042 emitcode (l, "%s,%s", aopGet (AOP (IC_RESULT (ic)), offset),
2043 aopGet (AOP (IC_RIGHT (ic)), offset));
2052 emitcode (l, "%s,%s(-%d)", aopGet (AOP (IC_RESULT (ic)), offset),
2054 (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit));
2059 adjustArithmeticResult (ic);
2062 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2063 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2064 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2067 /*-----------------------------------------------------------------*/
2068 /* genMinusDec :- does subtraction with deccrement if possible */
2069 /*-----------------------------------------------------------------*/
2071 genMinusDec (iCode * ic)
2073 unsigned int icount;
2075 /* will try to generate an increment */
2076 /* if the right side is not a literal
2078 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2081 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2083 /* if the sizes are greater than 2 or they are not the same regs
2085 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2088 /* so we know LEFT & RESULT in the same registers and add
2090 /* for short & char types */
2091 if (AOP_SIZE (IC_RESULT (ic)) < 2)
2095 emitcode ("dec", "%s", aopGet (AOP (IC_LEFT (ic)), 0));
2098 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_LEFT (ic)), 0), icount);
2102 if (AOP_SIZE (IC_RESULT (ic)) <= 3)
2104 /* if register pair and starts with 26/30 then adiw */
2105 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0 && icount < 64 &&
2106 (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2107 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX)))
2109 emitcode ("sbiw", "%s,%d", aopGet (AOP (IC_RESULT (ic)), 0), icount);
2114 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0), icount);
2115 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1), icount);
2118 /* for 32 bit longs */
2119 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0), icount);
2120 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1), icount);
2121 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2), icount);
2122 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3), icount);
2127 /*-----------------------------------------------------------------*/
2128 /* addSign - complete with sign */
2129 /*-----------------------------------------------------------------*/
2131 addSign (operand * result, int offset, int sign)
2133 int size = (getDataSize (result) - offset);
2138 emitcode ("rlc", "a");
2139 emitcode ("subb", "a,acc");
2141 aopPut (AOP (result), "a", offset++);
2145 aopPut (AOP (result), zero, offset++);
2149 /*-----------------------------------------------------------------*/
2150 /* genMinus - generates code for subtraction */
2151 /*-----------------------------------------------------------------*/
2153 genMinus (iCode * ic)
2155 int size, offset = 0, samer;
2158 aopOp (IC_LEFT (ic), ic, FALSE);
2159 aopOp (IC_RIGHT (ic), ic, FALSE);
2160 aopOp (IC_RESULT (ic), ic, TRUE);
2162 /* if I can do an decrement instead
2163 of subtract then GOOD for ME */
2164 if (genMinusDec (ic) == TRUE)
2167 size = getDataSize (IC_RESULT (ic));
2168 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2172 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), offset), offset);
2174 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2182 emitcode (l, "%s,%s", aopGet (AOP (IC_RESULT (ic)), offset),
2183 aopGet (AOP (IC_RIGHT (ic)), offset));
2192 emitcode (l, "%s,%s(%d)", aopGet (AOP (IC_RESULT (ic)), offset),
2194 (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit));
2199 adjustArithmeticResult (ic);
2202 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2203 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2204 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2207 /*-----------------------------------------------------------------*/
2208 /* genMultOneByte : 8 bit multiplication & division */
2209 /*-----------------------------------------------------------------*/
2211 genMultOneByte (operand * left,
2215 sym_link *opetype = operandType (result);
2219 /* (if two literals, the value is computed before) */
2220 /* if one literal, literal on the right */
2221 if (AOP_TYPE (left) == AOP_LIT)
2228 size = AOP_SIZE (result);
2230 if (SPEC_USIGN (opetype))
2232 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2236 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2237 aopGet (AOP (right), 0));
2239 aopPut (AOP (result), "r0", 0);
2242 aopPut (AOP (result), "r1", 1);
2245 if (SPEC_USIGN (opetype))
2249 aopPut (AOP (result), zero, offset++);
2256 lbl = newiTempLabel (NULL);
2257 emitcode ("ldi", "r24,0");
2258 emitcode ("brcc", "L%05d", lbl->key);
2259 emitcode ("ldi", "r24,lo8(-1)");
2260 emitcode ("", "L%05d:", lbl->key);
2262 aopPut (AOP (result), "r24", offset++);
2269 /*-----------------------------------------------------------------*/
2270 /* genMult - generates code for multiplication */
2271 /*-----------------------------------------------------------------*/
2273 genMult (iCode * ic)
2275 operand *left = IC_LEFT (ic);
2276 operand *right = IC_RIGHT (ic);
2277 operand *result = IC_RESULT (ic);
2279 /* assign the amsops */
2280 aopOp (left, ic, FALSE);
2281 aopOp (right, ic, FALSE);
2282 aopOp (result, ic, TRUE);
2284 /* if both are of size == 1 */
2285 if (AOP_SIZE (left) == 1 &&
2286 AOP_SIZE (right) == 1)
2288 genMultOneByte (left, right, result);
2292 /* should have been converted to function call */
2296 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2297 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2298 freeAsmop (result, NULL, ic, TRUE);
2301 /*-----------------------------------------------------------------*/
2302 /* genDiv - generates code for division */
2303 /*-----------------------------------------------------------------*/
2307 /* should have been converted to function call */
2311 /*-----------------------------------------------------------------*/
2312 /* genMod - generates code for division */
2313 /*-----------------------------------------------------------------*/
2317 /* should have been converted to function call */
2330 /*-----------------------------------------------------------------*/
2331 /* revavrcnd - reverse a conditional for avr */
2332 /*-----------------------------------------------------------------*/
2334 revavrcnd (int type)
2352 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++)
2354 if (rar[i].type == type)
2355 return rar[i].rtype;
2356 if (rar[i].rtype == type)
2359 assert (1); /* cannot happen */
2360 return 0; /* makes the compiler happy */
2363 static char *br_name[4] =
2364 {"breq", "brne", "brlt", "brge"};
2365 static char *br_uname[4] =
2366 {"breq", "brne", "brlo", "brcc"};
2368 /*-----------------------------------------------------------------*/
2369 /* genBranch - generate the branch instruction */
2370 /*-----------------------------------------------------------------*/
2372 genBranch (iCode * ifx, int br_type, int sign)
2374 int tj = (IC_TRUE (ifx) ? 1 : 0);
2377 { /* if true jump */
2378 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2379 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2382 { /* if false jump */
2383 int rtype = revavrcnd (br_type);
2384 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2385 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2390 /*-----------------------------------------------------------------*/
2391 /* genCmp - compare & jump */
2392 /*-----------------------------------------------------------------*/
2394 genCmp (iCode * ic, iCode * ifx, int br_type)
2396 operand *left, *right, *result;
2397 sym_link *letype, *retype;
2399 int sign, size, offset = 0;
2401 left = IC_LEFT (ic);
2402 right = IC_RIGHT (ic);
2403 result = IC_RESULT (ic);
2405 letype = getSpec (operandType (left));
2406 retype = getSpec (operandType (right));
2407 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2409 /* assign the amsops */
2410 aopOp (left, ic, FALSE);
2411 aopOp (right, ic, FALSE);
2412 aopOp (result, ic, TRUE);
2413 size = AOP_SIZE (left);
2419 if (AOP_TYPE (right) == AOP_LIT)
2421 emitcode ("cpi", "%s,lo8(%d)", aopGet (AOP (left), 0),
2422 (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit));
2423 genBranch (ifx, br_type, sign);
2426 { /* right != literal */
2427 emitcode ("cp", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2428 genBranch (ifx, br_type, sign);
2436 emitcode ("cp", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2438 emitcode ("cpc", "%s,%s", aopGet (AOP (left), offset), aopGet (AOP (right), offset));
2441 genBranch (ifx, br_type, sign);
2446 emitcode ("clr", "r0");
2450 emitcode ("cp", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2452 emitcode ("cpc", "%s,%s", aopGet (AOP (left), offset), aopGet (AOP (right), offset));
2455 lbl = newiTempLabel (NULL);
2456 br_type = revavrcnd (br_type);
2458 emitcode (br_uname[br_type], "L%05d", lbl->key);
2460 emitcode (br_name[br_type], "L%05d", lbl->key);
2461 emitcode ("inc", "r0");
2462 emitcode ("", "L%05d:", lbl->key);
2463 aopPut (AOP (result), "r0", 0);
2464 size = AOP_SIZE (result) - 1;
2467 aopPut (AOP (result), zero, offset++);
2470 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2472 freeAsmop (result, NULL, ic, TRUE);
2475 /*-----------------------------------------------------------------*/
2476 /* genCmpGt :- greater than comparison */
2477 /*-----------------------------------------------------------------*/
2479 genCmpGt (iCode * ic, iCode * ifx)
2481 /* should have transformed by the parser */
2485 /*-----------------------------------------------------------------*/
2486 /* genCmpLt - less than comparisons */
2487 /*-----------------------------------------------------------------*/
2489 genCmpLt (iCode * ic, iCode * ifx)
2491 genCmp (ic, ifx, AVR_LT);
2494 /*-----------------------------------------------------------------*/
2495 /* genCmpEq - generates code for equal to */
2496 /*-----------------------------------------------------------------*/
2498 genCmpEq (iCode * ic, iCode * ifx)
2500 genCmp (ic, ifx, AVR_EQ);
2503 /*-----------------------------------------------------------------*/
2504 /* genCmpNe - generates code for not equal to */
2505 /*-----------------------------------------------------------------*/
2507 genCmpNe (iCode * ic, iCode * ifx)
2509 genCmp (ic, ifx, AVR_NE);
2512 /*-----------------------------------------------------------------*/
2513 /* genCmpGe - generates code for greater than equal to */
2514 /*-----------------------------------------------------------------*/
2516 genCmpGe (iCode * ic, iCode * ifx)
2518 genCmp (ic, ifx, AVR_GE);
2521 /*-----------------------------------------------------------------*/
2522 /* genCmpLe - generates code for less than equal to */
2523 /*-----------------------------------------------------------------*/
2525 genCmpLe (iCode * ic, iCode * ifx)
2527 operand *left = IC_LEFT (ic);
2528 operand *right = IC_RIGHT (ic);
2530 IC_RIGHT (ic) = left;
2531 IC_LEFT (ic) = right;
2532 genCmp (ic, ifx, AVR_GE);
2535 /*-----------------------------------------------------------------*/
2536 /* ifxForOp - returns the icode containing the ifx for operand */
2537 /*-----------------------------------------------------------------*/
2539 ifxForOp (operand * op, iCode * ic)
2541 /* if true symbol then needs to be assigned */
2542 if (IS_TRUE_SYMOP (op))
2545 /* if this has register type condition and
2546 the next instruction is ifx with the same operand
2547 and live to of the operand is upto the ifx only then */
2549 ic->next->op == IFX &&
2550 IC_COND (ic->next)->key == op->key &&
2551 OP_SYMBOL (op)->liveTo <= ic->next->seq)
2556 /*-----------------------------------------------------------------*/
2557 /* genAndOp - for && operation */
2558 /*-----------------------------------------------------------------*/
2560 genAndOp (iCode * ic)
2562 operand *left, *right, *result;
2566 /* note here that && operations that are in an
2567 if statement are taken away by backPatchLabels
2568 only those used in arthmetic operations remain */
2569 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2570 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2571 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2573 tlbl = newiTempLabel (NULL);
2574 toBoolean (left, "r0", TRUE);
2575 toBoolean (right, "r1", TRUE);
2576 emitcode ("and", "r0,r1");
2577 emitcode ("ldi", "r24,1");
2578 emitcode ("breq", "L%05d", tlbl->key);
2579 emitcode ("dec", "r24");
2580 emitcode ("", "L%05d:", tlbl->key);
2581 aopPut (AOP (result), "r24", 0);
2582 size = AOP_SIZE (result) - 1;
2585 aopPut (AOP (result), zero, offset++);
2587 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2588 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2589 freeAsmop (result, NULL, ic, TRUE);
2593 /*-----------------------------------------------------------------*/
2594 /* genOrOp - for || operation */
2595 /*-----------------------------------------------------------------*/
2597 genOrOp (iCode * ic)
2599 operand *left, *right, *result;
2603 /* note here that || operations that are in an
2604 if statement are taken away by backPatchLabels
2605 only those used in arthmetic operations remain */
2606 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2607 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2608 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2610 tlbl = newiTempLabel (NULL);
2611 toBoolean (left, "r0", TRUE);
2612 toBoolean (right, "r0", FALSE);
2613 emitcode ("ldi", "r24,1");
2614 emitcode ("breq", "L%05d", tlbl->key);
2615 emitcode ("dec", "r24");
2616 emitcode ("", "L%05d:", tlbl->key);
2617 aopPut (AOP (result), "r24", 0);
2618 size = AOP_SIZE (result) - 1;
2621 aopPut (AOP (result), zero, offset++);
2623 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2624 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2625 freeAsmop (result, NULL, ic, TRUE);
2628 /*-----------------------------------------------------------------*/
2629 /* isLiteralBit - test if lit == 2^n */
2630 /*-----------------------------------------------------------------*/
2632 isLiteralBit (unsigned long lit)
2634 unsigned long pw[32] =
2635 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
2636 0x100L, 0x200L, 0x400L, 0x800L,
2637 0x1000L, 0x2000L, 0x4000L, 0x8000L,
2638 0x10000L, 0x20000L, 0x40000L, 0x80000L,
2639 0x100000L, 0x200000L, 0x400000L, 0x800000L,
2640 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
2641 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
2644 for (idx = 0; idx < 32; idx++)
2652 AVR_AND = 0, AVR_OR, AVR_XOR
2654 static char *bopnames_lit[] =
2656 static char *bopnames[] =
2657 {"and", "or", "eor"};
2658 /*-----------------------------------------------------------------*/
2659 /* genBitWise - generate bitwise operations */
2660 /*-----------------------------------------------------------------*/
2662 genBitWise (iCode * ic, iCode * ifx, int bitop)
2664 operand *left, *right, *result;
2665 int size, offset = 0;
2670 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2671 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2672 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2674 size = AOP_SIZE (left);
2677 { /* used only for jumps */
2678 if (AOP_TYPE (right) == AOP_LIT &&
2679 (bitop == AVR_AND || bitop == AVR_OR))
2681 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
2682 int p2 = powof2 (lit);
2683 if (bitop == AVR_AND && p2)
2684 { /* right side is a power of 2 */
2685 l = aopGet (AOP (left), p2 / 8);
2688 emitcode ("sbrc", "%s,%d", l, (p2 % 8));
2689 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2693 emitcode ("sbrs", "%s,%d", l, (p2 % 8));
2694 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2698 { /* right not power of two */
2699 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2704 emitcode (bopnames_lit[bitop], "%s,lo8(%d)",
2705 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2709 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2710 emitcode (bopnames_lit[bitop], "r0,lo8(%d)", lit);
2712 lbl = newiTempLabel (NULL);
2715 emitcode ("breq", "L%05d", lbl->key);
2716 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2720 emitcode ("brne", "L%05d", lbl->key);
2721 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2723 emitcode ("", "L%05d:", lbl->key);
2727 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2728 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2729 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2730 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2731 emitcode ("sbiw", "r24,0");
2732 lbl = newiTempLabel (NULL);
2735 emitcode ("breq", "L%05d", lbl->key);
2736 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2740 emitcode ("brne", "L%05d", lbl->key);
2741 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2743 emitcode ("", "L%05d:", lbl->key);
2747 lbl = newiTempLabel (NULL);
2748 lbl1 = newiTempLabel (NULL);
2753 emitcode (bopnames_lit[bitop], "%s,lo8(%d)",
2754 aopGet (AOP (IC_LEFT (ic)), offset), lit);
2758 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2759 emitcode ("andi", "r0,lo8(%d)", lit);
2761 emitcode ("brne", "L%05d", lbl->key);
2766 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2768 emitcode ("rjmp", "L%05d", lbl1->key);
2769 emitcode ("", "L%05d:", lbl->key);
2772 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2773 emitcode ("", "L%05d:", lbl1->key);
2779 { /* right is not a literal */
2780 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2781 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2786 emitcode (bopnames[bitop], "%s,%s",
2787 aopGet (AOP (IC_LEFT (ic)), 0),
2788 aopGet (AOP (IC_RIGHT (ic)), 0));
2792 emitcode (bopnames[bitop], "%s,%s",
2793 aopGet (AOP (IC_RIGHT (ic)), 0),
2794 aopGet (AOP (IC_LEFT (ic)), 0));
2798 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2799 emitcode (bopnames[bitop], "r0,%s", aopGet (AOP (IC_RIGHT (ic)), 0));
2801 lbl = newiTempLabel (NULL);
2804 emitcode ("breq", "L%05d", lbl->key);
2805 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2809 emitcode ("brne", "L%05d", lbl->key);
2810 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2812 emitcode ("", "L%05d:", lbl->key);
2816 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2817 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2818 emitcode (bopnames[bitop], "r24,%s", aopGet (AOP (IC_RIGHT (ic)), 0));
2819 emitcode (bopnames[bitop], "r25,%s", aopGet (AOP (IC_RIGHT (ic)), 1));
2820 emitcode ("sbiw", "r24,0");
2821 lbl = newiTempLabel (NULL);
2824 emitcode ("breq", "L%05d", lbl->key);
2825 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2829 emitcode ("brne", "L%05d", lbl->key);
2830 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2832 emitcode ("", "L%05d:", lbl->key);
2836 lbl = newiTempLabel (NULL);
2837 lbl1 = newiTempLabel (NULL);
2842 emitcode (bopnames[bitop], "%s,%s",
2843 aopGet (AOP (IC_LEFT (ic)), offset),
2844 aopGet (AOP (IC_RIGHT (ic)), offset));
2848 emitcode (bopnames[bitop], "%s,%s",
2849 aopGet (AOP (IC_RIGHT (ic)), offset),
2850 aopGet (AOP (IC_LEFT (ic)), offset));
2854 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2855 emitcode (bopnames[bitop], "r0,%s", aopGet (AOP (IC_RIGHT (ic)), offset));
2857 emitcode ("brne", "L%05d", lbl->key);
2862 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2864 emitcode ("rjmp", "L%05d", lbl1->key);
2865 emitcode ("", "L%05d:", lbl->key);
2868 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2869 emitcode ("", "L%05d:", lbl1->key);
2876 /* result needs to go a register */
2877 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2878 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2881 if (AOP_TYPE (right) == AOP_LIT)
2883 unsigned int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
2884 if (((lit >> (8 * offset)) & 0xff) == 0)
2886 if (bitop == AVR_AND)
2888 aopPut (AOP (result), zero, offset++);
2891 else if (bitop == AVR_OR)
2894 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
2902 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && (bitop == AVR_AND || bitop == AVR_OR))
2904 emitcode (bopnames_lit[bitop], "%s,%s(%d)", aopGet (AOP (IC_LEFT (ic)), offset),
2905 larray[offset], (int) floatFromVal (AOP (right)->aopu.aop_lit));
2909 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), offset),
2910 aopGet (AOP (IC_RIGHT (ic)), offset));
2915 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_RIGHT (ic)), offset),
2916 aopGet (AOP (IC_LEFT (ic)), offset));
2920 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), offset), offset);
2921 emitcode (bopnames[bitop], aopGet (AOP (IC_RESULT (ic)), offset),
2922 aopGet (AOP (IC_RIGHT (ic)), offset));
2927 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2928 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2929 freeAsmop (result, NULL, ic, TRUE);
2932 /*-----------------------------------------------------------------*/
2933 /* genAnd - code for and */
2934 /*-----------------------------------------------------------------*/
2936 genAnd (iCode * ic, iCode * ifx)
2938 genBitWise (ic, ifx, AVR_AND);
2941 /*-----------------------------------------------------------------*/
2942 /* genOr - code for or */
2943 /*-----------------------------------------------------------------*/
2945 genOr (iCode * ic, iCode * ifx)
2947 genBitWise (ic, ifx, AVR_OR);
2950 /*-----------------------------------------------------------------*/
2951 /* genXor - code for xclusive or */
2952 /*-----------------------------------------------------------------*/
2954 genXor (iCode * ic, iCode * ifx)
2956 genBitWise (ic, ifx, AVR_XOR);
2959 /*-----------------------------------------------------------------*/
2960 /* genInline - write the inline code out */
2961 /*-----------------------------------------------------------------*/
2963 genInline (iCode * ic)
2965 char buffer[MAX_INLINEASM];
2969 _G.inLine += (!options.asmpeep);
2970 strcpy (buffer, IC_INLINE (ic));
2972 /* emit each line as a code */
2997 /* emitcode("",buffer); */
2998 _G.inLine -= (!options.asmpeep);
3001 /*-----------------------------------------------------------------*/
3002 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
3003 /*-----------------------------------------------------------------*/
3005 genRotC (iCode * ic, int lr)
3007 operand *left, *result;
3008 int size, offset = 0;
3010 /* rotate right with carry */
3011 left = IC_LEFT (ic);
3012 result = IC_RESULT (ic);
3013 aopOp (left, ic, FALSE);
3014 aopOp (result, ic, FALSE);
3016 /* move it to the result */
3017 size = AOP_SIZE (result);
3018 if (!sameRegs (AOP (left), AOP (result)))
3023 aopPut (AOP (result),
3024 aopGet (AOP (left), offset),
3028 size = AOP_SIZE (result);
3036 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3038 emitcode ("sec", "");
3042 emitcode ((lr ? "ror" : "rol"), "%s", aopGet (AOP (result), offset));
3048 freeAsmop (left, NULL, ic, TRUE);
3049 freeAsmop (result, NULL, ic, TRUE);
3052 /*-----------------------------------------------------------------*/
3053 /* genRRC - rotate right with carry */
3054 /*-----------------------------------------------------------------*/
3061 /*-----------------------------------------------------------------*/
3062 /* genRLC - generate code for rotate left with carry */
3063 /*-----------------------------------------------------------------*/
3070 /*-----------------------------------------------------------------*/
3071 /* genGetHbit - generates code get highest order bit */
3072 /*-----------------------------------------------------------------*/
3074 genGetHbit (iCode * ic)
3076 operand *left, *result;
3079 left = IC_LEFT (ic);
3080 result = IC_RESULT (ic);
3081 aopOp (left, ic, FALSE);
3082 aopOp (result, ic, FALSE);
3084 size = AOP_SIZE (result);
3085 if (!sameRegs (AOP (left), AOP (result)))
3087 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3088 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3089 emitcode ("subi", "%s,lo8(-1)", aopGet (AOP (result), size - 1));
3093 emitcode ("clr", "r0");
3094 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3095 emitcode ("subi", "r0,lo8(-1)");
3096 aopPut (AOP (result), "r0", 0);
3102 emitcode ("clr", aopGet (AOP (result), offset++));
3104 freeAsmop (left, NULL, ic, TRUE);
3105 freeAsmop (result, NULL, ic, TRUE);
3108 /*-----------------------------------------------------------------*/
3109 /* genShiftLeftLit - shift left by a known amount */
3110 /*-----------------------------------------------------------------*/
3112 genShiftLeftLit (iCode * ic)
3114 operand *left, *right, *result;
3115 int size, shCount, offset = 0;
3118 right = IC_RIGHT (ic);
3119 left = IC_LEFT (ic);
3120 result = IC_RESULT (ic);
3122 aopOp (left, ic, FALSE);
3123 aopOp (result, ic, FALSE);
3124 size = AOP_SIZE (result);
3125 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3127 if (shCount > (size * 8 - 1))
3130 aopPut (AOP (result), zero, offset++);
3136 if (!sameRegs (AOP (left), AOP (result)))
3137 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3140 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3141 emitcode ("andi", "%s,0xf0");
3146 emitcode ("add", "%s,%s", aopGet (AOP (result), 0), aopGet (AOP (result), 0));
3150 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3155 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3156 aopPut (AOP (result), zero, 0);
3157 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3158 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3164 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3165 aopPut (AOP (result), zero, 0);
3172 if (!sameRegs (AOP (left), AOP (result)))
3174 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3175 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3177 emitcode ("mov", "r1,%s", aopGet (AOP (result), 0));
3178 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3179 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3180 emitcode ("andi", "r1,0x0f");
3181 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3182 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3183 emitcode ("or", "%s,r1", aopGet (AOP (result), 1));
3186 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3187 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3190 if (!lByteZ && !sameRegs (AOP (result), AOP (left)) && shCount)
3195 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3203 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3207 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3208 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3213 assert ("shifting generic pointer ?\n");
3216 /* 32 bits we do only byte boundaries */
3219 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3220 aopPut (AOP (result), zero, 2);
3221 aopPut (AOP (result), zero, 1);
3222 aopPut (AOP (result), zero, 0);
3228 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3229 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3230 aopPut (AOP (result), zero, 1);
3231 aopPut (AOP (result), zero, 0);
3237 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3238 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3239 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3240 aopPut (AOP (result), zero, 0);
3244 if (!lByteZ && !sameRegs (AOP (left), AOP (right)))
3249 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3253 size = AOP_SIZE (result);
3262 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3263 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3264 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3265 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3271 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3272 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3273 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3279 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3280 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3286 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3294 freeAsmop (left, NULL, ic, TRUE);
3295 freeAsmop (right, NULL, ic, TRUE);
3296 freeAsmop (result, NULL, ic, TRUE);
3299 /*-----------------------------------------------------------------*/
3300 /* genLeftShift - generates code for left shifting */
3301 /*-----------------------------------------------------------------*/
3303 genLeftShift (iCode * ic)
3305 operand *left, *right, *result;
3309 right = IC_RIGHT (ic);
3310 left = IC_LEFT (ic);
3311 result = IC_RESULT (ic);
3313 aopOp (right, ic, FALSE);
3315 if (AOP_TYPE (right) == AOP_LIT)
3317 genShiftLeftLit (ic);
3322 aopOp (left, ic, FALSE);
3323 aopOp (result, ic, FALSE);
3324 size = AOP_SIZE (result);
3326 if (AOP_SIZE (right) > 1)
3328 if (isRegPair (AOP (right)))
3330 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3334 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3335 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3340 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3342 if (!sameRegs (AOP (left), AOP (result)))
3346 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3349 size = AOP_SIZE (result);
3351 tlbl = newiTempLabel (NULL);
3352 emitcode ("", "L%05d:", tlbl->key);
3357 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3359 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3362 if (AOP_SIZE (right) > 1)
3363 emitcode ("sbiw", "r24,1");
3365 emitcode ("dec", "r24");
3366 emitcode ("brne", "L%05d", tlbl->key);
3368 freeAsmop (left, NULL, ic, TRUE);
3369 freeAsmop (right, NULL, ic, TRUE);
3370 freeAsmop (result, NULL, ic, TRUE);
3373 /*-----------------------------------------------------------------*/
3374 /* genShiftRightLit - generate for right shift with known count */
3375 /*-----------------------------------------------------------------*/
3377 genShiftRightLit (iCode * ic)
3379 operand *left = IC_LEFT (ic)
3380 ,*right = IC_RIGHT (ic)
3381 ,*result = IC_RESULT (ic);
3382 int size, shCount, offset = 0;
3384 sym_link *letype = getSpec (operandType (left));
3385 int sign = !SPEC_USIGN (letype);
3387 right = IC_RIGHT (ic);
3388 left = IC_LEFT (ic);
3389 result = IC_RESULT (ic);
3391 aopOp (left, ic, FALSE);
3392 aopOp (result, ic, FALSE);
3393 size = AOP_SIZE (result);
3394 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3396 /* if signed then give up and use a loop to shift */
3400 if (!sameRegs (AOP (left), AOP (result)))
3404 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3407 size = size = AOP_SIZE (result);
3410 /* be as economical as possible */
3417 size = AOP_SIZE (result);
3420 if (offset == (size - 1))
3421 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3423 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3430 emitcode ("ldi", "r24,lo8(%d)", shCount);
3431 tlbl = newiTempLabel (NULL);
3432 emitcode ("", "L%05d:", tlbl->key);
3436 if (offset == (size - 1))
3437 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3439 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3442 emitcode ("dec", "r24");
3443 emitcode ("brne", "L%05d", tlbl->key);
3447 if (shCount > (size * 8 - 1))
3450 aopPut (AOP (result), zero, offset++);
3453 /* for unsigned we can much more efficient */
3457 if (!sameRegs (AOP (left), AOP (result)))
3458 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3461 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3462 emitcode ("andi", "%s,0x0f");
3466 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3471 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3472 aopPut (AOP (result), zero, 1);
3473 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3474 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3480 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3481 aopPut (AOP (result), zero, 1);
3488 if (!sameRegs (AOP (left), AOP (result)))
3490 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3491 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3493 emitcode ("mov", "r1,%s", aopGet (AOP (result), 1));
3494 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3495 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3496 emitcode ("andi", "r1,0xf0");
3497 emitcode ("or", "%s,r1", aopGet (AOP (result), 0));
3498 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3499 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3502 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3503 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3507 if (!hByteZ && !sameRegs (AOP (result), AOP (left)) && shCount)
3512 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3520 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3524 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3525 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3531 assert ("shifting generic pointer ?\n");
3534 /* 32 bits we do only byte boundaries */
3537 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3538 aopPut (AOP (result), zero, 1);
3539 aopPut (AOP (result), zero, 2);
3540 aopPut (AOP (result), zero, 3);
3546 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3547 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3548 aopPut (AOP (result), zero, 2);
3549 aopPut (AOP (result), zero, 3);
3555 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3556 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3557 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3558 aopPut (AOP (result), zero, 3);
3562 if (!hByteZ && !sameRegs (AOP (left), AOP (right)))
3567 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3571 size = AOP_SIZE (result);
3580 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3581 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3582 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3583 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3589 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3590 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3591 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3597 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3598 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3604 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3611 freeAsmop (left, NULL, ic, TRUE);
3612 freeAsmop (right, NULL, ic, TRUE);
3613 freeAsmop (result, NULL, ic, TRUE);
3616 /*-----------------------------------------------------------------*/
3617 /* genRightShift - generate code for right shifting */
3618 /*-----------------------------------------------------------------*/
3620 genRightShift (iCode * ic)
3622 operand *right, *left, *result;
3625 int sign = 0, first = 1;
3628 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3629 if (AOP_TYPE (right) == AOP_LIT)
3631 genShiftRightLit (ic);
3635 if (AOP_SIZE (right) > 1)
3637 if (isRegPair (AOP (right)))
3639 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3643 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3644 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3649 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3651 aopOp (left = IC_LEFT (ic), ic, FALSE);
3652 aopOp (result = IC_RESULT (ic), ic, FALSE);
3653 size = AOP_SIZE (result);
3654 tlbl = newiTempLabel (NULL);
3655 emitcode ("", "L%05d:", tlbl->key);
3657 letype = getSpec (operandType (left));
3658 sign = !SPEC_USIGN (letype);
3659 if (!sameRegs (AOP (left), AOP (result)))
3663 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3666 size = AOP_SIZE (result);
3668 size = AOP_SIZE (result);
3674 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3676 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3680 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3683 if (AOP_SIZE (right) > 1)
3684 emitcode ("sbiw", "r24,1");
3686 emitcode ("dec", "r24");
3687 emitcode ("brne", "L%05d", tlbl->key);
3689 freeAsmop (left, NULL, ic, TRUE);
3690 freeAsmop (result, NULL, ic, TRUE);
3693 /*-----------------------------------------------------------------*/
3694 /* R0Rsh - shift right r0 by known count */
3695 /*-----------------------------------------------------------------*/
3699 shCount &= 0x0007; // shCount : 0..7
3706 emitcode ("lsr", "r0");
3709 emitcode ("lsr", "r0");
3710 emitcode ("lsr", "r0");
3713 emitcode ("swap", "r0");
3714 emitcode ("lsl", "r0");
3717 emitcode ("swap", "r0");
3720 emitcode ("swap", "r0");
3721 emitcode ("lsr", "r0");
3724 emitcode ("swap", "r0");
3725 emitcode ("lsr", "r0");
3726 emitcode ("lsr", "r0");
3729 emitcode ("swap", "r0");
3730 emitcode ("lsr", "r0");
3731 emitcode ("lsr", "r0");
3732 emitcode ("lsr", "r0");
3737 /*-----------------------------------------------------------------*/
3738 /* genUnpackBits - generates code for unpacking bits */
3739 /*-----------------------------------------------------------------*/
3741 genUnpackBits (operand * result, char *rname, int ptype)
3749 etype = getSpec (operandType (result));
3750 rsize = getSize (operandType (result));
3751 /* read the first byte */
3756 emitcode ("mov", "a,@%s", rname);
3760 emitcode ("movx", "a,@%s", rname);
3764 emitcode ("movx", "a,@dptr");
3768 emitcode ("clr", "a");
3769 emitcode ("movc", "a", "@a+dptr");
3773 emitcode ("lcall", "__gptrget");
3777 rlen = SPEC_BLEN (etype);
3779 /* if we have bitdisplacement then it fits */
3780 /* into this byte completely or if length is */
3781 /* less than a byte */
3782 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3784 /* shift right acc */
3787 emitcode ("anl", "a,#0x%02x",
3788 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3789 aopPut (AOP (result), "a", offset++);
3793 /* bit field did not fit in a byte */
3794 aopPut (AOP (result), "a", offset++);
3802 emitcode ("inc", "%s", rname);
3803 emitcode ("mov", "a,@%s", rname);
3807 emitcode ("inc", "%s", rname);
3808 emitcode ("movx", "a,@%s", rname);
3812 emitcode ("inc", "dptr");
3813 emitcode ("movx", "a,@dptr");
3817 emitcode ("clr", "a");
3818 emitcode ("inc", "dptr");
3819 emitcode ("movc", "a", "@a+dptr");
3823 emitcode ("inc", "dptr");
3824 emitcode ("lcall", "__gptrget");
3829 /* if we are done */
3833 aopPut (AOP (result), "a", offset++);
3838 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
3839 // AccLsh (8 - rlen);
3840 aopPut (AOP (result), "a", offset++);
3844 if (offset < rsize) {
3847 aopPut (AOP (result), zero, offset++);
3852 /*-----------------------------------------------------------------*/
3853 /* genDataPointerGet - generates code when ptr offset is known */
3854 /*-----------------------------------------------------------------*/
3856 genDataPointerGet (operand * left,
3862 int size, offset = 0;
3863 aopOp (result, ic, TRUE);
3865 /* get the string representation of the name */
3866 l = aopGet (AOP (left), 0);
3867 size = AOP_SIZE (result);
3870 sprintf (buffer, "(%s + %d)", l + 1, offset);
3872 sprintf (buffer, "%s", l + 1);
3873 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++), buffer);
3876 freeAsmop (left, NULL, ic, TRUE);
3877 freeAsmop (result, NULL, ic, TRUE);
3880 /*-----------------------------------------------------------------*/
3881 /* genNearPointerGet - emitcode for near pointer fetch */
3882 /*-----------------------------------------------------------------*/
3884 genNearPointerGet (operand * left,
3891 sym_link *rtype, *retype;
3892 sym_link *ltype = operandType (left);
3895 rtype = operandType (result);
3896 retype = getSpec (rtype);
3898 aopOp (left, ic, FALSE);
3900 /* if left is rematerialisable and
3901 result is not bit variable type and
3902 the left is pointer to data space i.e
3903 lower 128 bytes of space */
3904 if (AOP_TYPE (left) == AOP_IMMD &&
3905 !IS_BITVAR (retype) &&
3906 DCL_TYPE (ltype) == POINTER) {
3907 genDataPointerGet (left, result, ic);
3911 /* if the value is already in a pointer register
3912 then don't need anything more */
3913 if (!AOP_INPREG (AOP (left))) {
3914 /* otherwise get a free pointer register */
3916 preg = getFreePtr (ic, &aop, FALSE, 0);
3917 emitcode ("mov", "%s,%s",
3919 aopGet (AOP (left), 0));
3923 rname = aopGet (AOP (left), 0);
3925 freeAsmop (left, NULL, ic, TRUE);
3926 aopOp (result, ic, FALSE);
3928 /* if bitfield then unpack the bits */
3929 if (IS_BITVAR (retype))
3930 genUnpackBits (result, rname, POINTER);
3932 /* we have can just get the values */
3933 int size = AOP_SIZE (result);
3937 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK) {
3939 emitcode ("mov", "a,@%s", rname);
3940 aopPut (AOP (result), "a", offset);
3944 sprintf (buffer, "@%s", rname);
3945 aopPut (AOP (result), buffer, offset);
3949 emitcode ("inc", "%s", rname);
3953 /* now some housekeeping stuff */
3956 /* we had to allocate for this iCode */
3957 freeAsmop (NULL, aop, ic, TRUE);
3961 /* we did not allocate which means left
3962 already in a pointer register, then
3963 if size > 0 && this could be used again
3964 we have to point it back to where it
3966 if (AOP_SIZE (result) > 1 &&
3967 !OP_SYMBOL (left)->remat &&
3968 (OP_SYMBOL (left)->liveTo > ic->seq ||
3971 int size = AOP_SIZE (result) - 1;
3973 emitcode ("dec", "%s", rname);
3978 freeAsmop (result, NULL, ic, TRUE);
3982 /*-----------------------------------------------------------------*/
3983 /* genPagedPointerGet - emitcode for paged pointer fetch */
3984 /*-----------------------------------------------------------------*/
3986 genPagedPointerGet (operand * left,
3993 sym_link *rtype, *retype;
3995 rtype = operandType (result);
3996 retype = getSpec (rtype);
3998 aopOp (left, ic, FALSE);
4000 /* if the value is already in a pointer register
4001 then don't need anything more */
4002 if (!AOP_INPREG (AOP (left)))
4004 /* otherwise get a free pointer register */
4006 preg = getFreePtr (ic, &aop, FALSE, 0);
4007 emitcode ("mov", "%s,%s",
4009 aopGet (AOP (left), 0));
4013 rname = aopGet (AOP (left), 0);
4015 freeAsmop (left, NULL, ic, TRUE);
4016 aopOp (result, ic, FALSE);
4018 /* if bitfield then unpack the bits */
4019 if (IS_BITVAR (retype))
4020 genUnpackBits (result, rname, PPOINTER);
4023 /* we have can just get the values */
4024 int size = AOP_SIZE (result);
4030 emitcode ("movx", "a,@%s", rname);
4031 aopPut (AOP (result), "a", offset);
4036 emitcode ("inc", "%s", rname);
4040 /* now some housekeeping stuff */
4043 /* we had to allocate for this iCode */
4044 freeAsmop (NULL, aop, ic, TRUE);
4048 /* we did not allocate which means left
4049 already in a pointer register, then
4050 if size > 0 && this could be used again
4051 we have to point it back to where it
4053 if (AOP_SIZE (result) > 1 &&
4054 !OP_SYMBOL (left)->remat &&
4055 (OP_SYMBOL (left)->liveTo > ic->seq ||
4058 int size = AOP_SIZE (result) - 1;
4060 emitcode ("dec", "%s", rname);
4065 freeAsmop (result, NULL, ic, TRUE);
4070 /*-----------------------------------------------------------------*/
4071 /* genFarPointerGet - gget value from far space */
4072 /*-----------------------------------------------------------------*/
4074 genFarPointerGet (operand * left,
4075 operand * result, iCode * ic)
4078 sym_link *retype = getSpec (operandType (result));
4080 aopOp (left, ic, FALSE);
4082 /* if the operand is already in dptr
4083 then we do nothing else we move the value to dptr */
4084 if (AOP_TYPE (left) != AOP_STR)
4086 /* if this is remateriazable */
4087 if (AOP_TYPE (left) == AOP_IMMD)
4088 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4090 { /* we need to get it byte by byte */
4091 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4092 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4093 if (options.model == MODEL_FLAT24)
4095 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4099 /* so dptr know contains the address */
4100 freeAsmop (left, NULL, ic, TRUE);
4101 aopOp (result, ic, FALSE);
4103 /* if bit then unpack */
4104 if (IS_BITVAR (retype))
4105 genUnpackBits (result, "dptr", FPOINTER);
4108 size = AOP_SIZE (result);
4113 emitcode ("movx", "a,@dptr");
4114 aopPut (AOP (result), "a", offset++);
4116 emitcode ("inc", "dptr");
4120 freeAsmop (result, NULL, ic, TRUE);
4123 /*-----------------------------------------------------------------*/
4124 /* emitcodePointerGet - gget value from code space */
4125 /*-----------------------------------------------------------------*/
4127 emitcodePointerGet (operand * left,
4128 operand * result, iCode * ic)
4131 sym_link *retype = getSpec (operandType (result));
4133 aopOp (left, ic, FALSE);
4135 /* if the operand is already in dptr
4136 then we do nothing else we move the value to dptr */
4137 if (AOP_TYPE (left) != AOP_STR)
4139 /* if this is remateriazable */
4140 if (AOP_TYPE (left) == AOP_IMMD)
4141 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4143 { /* we need to get it byte by byte */
4144 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4145 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4146 if (options.model == MODEL_FLAT24)
4148 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4152 /* so dptr know contains the address */
4153 freeAsmop (left, NULL, ic, TRUE);
4154 aopOp (result, ic, FALSE);
4156 /* if bit then unpack */
4157 if (IS_BITVAR (retype))
4158 genUnpackBits (result, "dptr", CPOINTER);
4161 size = AOP_SIZE (result);
4166 emitcode ("clr", "a");
4167 emitcode ("movc", "a,@a+dptr");
4168 aopPut (AOP (result), "a", offset++);
4170 emitcode ("inc", "dptr");
4174 freeAsmop (result, NULL, ic, TRUE);
4177 /*-----------------------------------------------------------------*/
4178 /* genGenPointerGet - gget value from generic pointer space */
4179 /*-----------------------------------------------------------------*/
4181 genGenPointerGet (operand * left,
4182 operand * result, iCode * ic)
4185 sym_link *retype = getSpec (operandType (result));
4187 aopOp (left, ic, FALSE);
4189 /* if the operand is already in dptr
4190 then we do nothing else we move the value to dptr */
4191 if (AOP_TYPE (left) != AOP_STR)
4193 /* if this is remateriazable */
4194 if (AOP_TYPE (left) == AOP_IMMD)
4196 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4197 emitcode ("mov", "b,#%d", pointerCode (retype));
4200 { /* we need to get it byte by byte */
4201 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4202 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4203 if (options.model == MODEL_FLAT24)
4205 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4206 emitcode ("mov", "b,%s", aopGet (AOP (left), 3));
4210 emitcode ("mov", "b,%s", aopGet (AOP (left), 2));
4214 /* so dptr know contains the address */
4215 freeAsmop (left, NULL, ic, TRUE);
4216 aopOp (result, ic, FALSE);
4218 /* if bit then unpack */
4219 if (IS_BITVAR (retype))
4220 genUnpackBits (result, "dptr", GPOINTER);
4223 size = AOP_SIZE (result);
4228 emitcode ("lcall", "__gptrget");
4229 aopPut (AOP (result), "a", offset++);
4231 emitcode ("inc", "dptr");
4235 freeAsmop (result, NULL, ic, TRUE);
4238 /*-----------------------------------------------------------------*/
4239 /* genPointerGet - generate code for pointer get */
4240 /*-----------------------------------------------------------------*/
4242 genPointerGet (iCode * ic)
4244 operand *left, *result;
4245 sym_link *type, *etype;
4248 left = IC_LEFT (ic);
4249 result = IC_RESULT (ic);
4251 /* depending on the type of pointer we need to
4252 move it to the correct pointer register */
4253 type = operandType (left);
4254 etype = getSpec (type);
4255 /* if left is of type of pointer then it is simple */
4256 if (IS_PTR (type) && !IS_FUNC (type->next))
4257 p_type = DCL_TYPE (type);
4260 /* we have to go by the storage class */
4261 p_type = PTR_TYPE (SPEC_OCLS (etype));
4263 /* if (SPEC_OCLS(etype)->codesp ) { */
4264 /* p_type = CPOINTER ; */
4267 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4268 /* p_type = FPOINTER ; */
4270 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4271 /* p_type = PPOINTER; */
4273 /* if (SPEC_OCLS(etype) == idata ) */
4274 /* p_type = IPOINTER; */
4276 /* p_type = POINTER ; */
4279 /* now that we have the pointer type we assign
4280 the pointer values */
4286 genNearPointerGet (left, result, ic);
4290 genPagedPointerGet (left, result, ic);
4294 genFarPointerGet (left, result, ic);
4298 emitcodePointerGet (left, result, ic);
4302 genGenPointerGet (left, result, ic);
4308 /*-----------------------------------------------------------------*/
4309 /* genPackBits - generates code for packed bit storage */
4310 /*-----------------------------------------------------------------*/
4312 genPackBits (sym_link * etype,
4314 char *rname, int p_type)
4322 blen = SPEC_BLEN (etype);
4323 bstr = SPEC_BSTR (etype);
4325 l = aopGet (AOP (right), offset++);
4328 /* if the bit lenth is less than or */
4329 /* it exactly fits a byte then */
4330 if (SPEC_BLEN (etype) <= 8)
4332 shCount = SPEC_BSTR (etype);
4334 /* shift left acc */
4337 if (SPEC_BLEN (etype) < 8)
4338 { /* if smaller than a byte */
4344 emitcode ("mov", "b,a");
4345 emitcode ("mov", "a,@%s", rname);
4349 emitcode ("mov", "b,a");
4350 emitcode ("movx", "a,@dptr");
4354 emitcode ("push", "b");
4355 emitcode ("push", "acc");
4356 emitcode ("lcall", "__gptrget");
4357 emitcode ("pop", "b");
4361 emitcode ("anl", "a,#0x%02x", (unsigned char)
4362 ((unsigned char) (0xFF << (blen + bstr)) |
4363 (unsigned char) (0xFF >> (8 - bstr))));
4364 emitcode ("orl", "a,b");
4365 if (p_type == GPOINTER)
4366 emitcode ("pop", "b");
4373 emitcode ("mov", "@%s,a", rname);
4377 emitcode ("movx", "@dptr,a");
4381 emitcode ("lcall", "__gptrput");
4386 if (SPEC_BLEN (etype) <= 8)
4389 emitcode ("inc", "%s", rname);
4390 rLen = SPEC_BLEN (etype);
4392 /* now generate for lengths greater than one byte */
4396 l = aopGet (AOP (right), offset++);
4408 emitcode ("mov", "@%s,a", rname);
4411 emitcode ("mov", "@%s,%s", rname, l);
4416 emitcode ("movx", "@dptr,a");
4421 emitcode ("lcall", "__gptrput");
4424 emitcode ("inc", "%s", rname);
4429 /* last last was not complete */
4432 /* save the byte & read byte */
4436 emitcode ("mov", "b,a");
4437 emitcode ("mov", "a,@%s", rname);
4441 emitcode ("mov", "b,a");
4442 emitcode ("movx", "a,@dptr");
4446 emitcode ("push", "b");
4447 emitcode ("push", "acc");
4448 emitcode ("lcall", "__gptrget");
4449 emitcode ("pop", "b");
4453 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << -rLen));
4454 emitcode ("orl", "a,b");
4457 if (p_type == GPOINTER)
4458 emitcode ("pop", "b");
4464 emitcode ("mov", "@%s,a", rname);
4468 emitcode ("movx", "@dptr,a");
4472 emitcode ("lcall", "__gptrput");
4476 /*-----------------------------------------------------------------*/
4477 /* genDataPointerSet - remat pointer to data space */
4478 /*-----------------------------------------------------------------*/
4480 genDataPointerSet (operand * right,
4484 int size, offset = 0;
4485 char *l, buffer[256];
4487 aopOp (right, ic, FALSE);
4489 l = aopGet (AOP (result), 0);
4490 size = AOP_SIZE (right);
4494 sprintf (buffer, "(%s + %d)", l + 1, offset);
4496 sprintf (buffer, "%s", l + 1);
4497 emitcode ("mov", "%s,%s", buffer,
4498 aopGet (AOP (right), offset++));
4501 freeAsmop (right, NULL, ic, TRUE);
4502 freeAsmop (result, NULL, ic, TRUE);
4505 /*-----------------------------------------------------------------*/
4506 /* genNearPointerSet - emitcode for near pointer put */
4507 /*-----------------------------------------------------------------*/
4509 genNearPointerSet (operand * right,
4517 sym_link *ptype = operandType (result);
4519 retype = getSpec (operandType (right));
4521 aopOp (result, ic, FALSE);
4523 /* if the result is rematerializable &
4524 in data space & not a bit variable */
4525 if (AOP_TYPE (result) == AOP_IMMD &&
4526 DCL_TYPE (ptype) == POINTER &&
4527 !IS_BITVAR (retype))
4529 genDataPointerSet (right, result, ic);
4533 /* if the value is already in a pointer register
4534 then don't need anything more */
4535 if (!AOP_INPREG (AOP (result)))
4537 /* otherwise get a free pointer register */
4539 preg = getFreePtr (ic, &aop, FALSE, 0);
4540 emitcode ("mov", "%s,%s",
4542 aopGet (AOP (result), 0));
4546 rname = aopGet (AOP (result), 0);
4548 freeAsmop (result, NULL, ic, TRUE);
4549 aopOp (right, ic, FALSE);
4551 /* if bitfield then unpack the bits */
4552 if (IS_BITVAR (retype))
4553 genPackBits (retype, right, rname, POINTER);
4556 /* we have can just get the values */
4557 int size = AOP_SIZE (right);
4562 l = aopGet (AOP (right), offset);
4566 emitcode ("mov", "@%s,a", rname);
4569 emitcode ("mov", "@%s,%s", rname, l);
4571 emitcode ("inc", "%s", rname);
4576 /* now some housekeeping stuff */
4579 /* we had to allocate for this iCode */
4580 freeAsmop (NULL, aop, ic, TRUE);
4584 /* we did not allocate which means left
4585 already in a pointer register, then
4586 if size > 0 && this could be used again
4587 we have to point it back to where it
4589 if (AOP_SIZE (right) > 1 &&
4590 !OP_SYMBOL (result)->remat &&
4591 (OP_SYMBOL (result)->liveTo > ic->seq ||
4594 int size = AOP_SIZE (right) - 1;
4596 emitcode ("dec", "%s", rname);
4601 freeAsmop (right, NULL, ic, TRUE);
4606 /*-----------------------------------------------------------------*/
4607 /* genPagedPointerSet - emitcode for Paged pointer put */
4608 /*-----------------------------------------------------------------*/
4610 genPagedPointerSet (operand * right,
4619 retype = getSpec (operandType (right));
4621 aopOp (result, ic, FALSE);
4623 /* if the value is already in a pointer register
4624 then don't need anything more */
4625 if (!AOP_INPREG (AOP (result)))
4627 /* otherwise get a free pointer register */
4629 preg = getFreePtr (ic, &aop, FALSE, 0);
4630 emitcode ("mov", "%s,%s",
4632 aopGet (AOP (result), 0));
4636 rname = aopGet (AOP (result), 0);
4638 freeAsmop (result, NULL, ic, TRUE);
4639 aopOp (right, ic, FALSE);
4641 /* if bitfield then unpack the bits */
4642 if (IS_BITVAR (retype))
4643 genPackBits (retype, right, rname, PPOINTER);
4646 /* we have can just get the values */
4647 int size = AOP_SIZE (right);
4652 l = aopGet (AOP (right), offset);
4655 emitcode ("movx", "@%s,a", rname);
4658 emitcode ("inc", "%s", rname);
4664 /* now some housekeeping stuff */
4667 /* we had to allocate for this iCode */
4668 freeAsmop (NULL, aop, ic, TRUE);
4672 /* we did not allocate which means left
4673 already in a pointer register, then
4674 if size > 0 && this could be used again
4675 we have to point it back to where it
4677 if (AOP_SIZE (right) > 1 &&
4678 !OP_SYMBOL (result)->remat &&
4679 (OP_SYMBOL (result)->liveTo > ic->seq ||
4682 int size = AOP_SIZE (right) - 1;
4684 emitcode ("dec", "%s", rname);
4689 freeAsmop (right, NULL, ic, TRUE);
4694 /*-----------------------------------------------------------------*/
4695 /* genFarPointerSet - set value from far space */
4696 /*-----------------------------------------------------------------*/
4698 genFarPointerSet (operand * right,
4699 operand * result, iCode * ic)
4702 sym_link *retype = getSpec (operandType (right));
4704 aopOp (result, ic, FALSE);
4706 /* if the operand is already in dptr
4707 then we do nothing else we move the value to dptr */
4708 if (AOP_TYPE (result) != AOP_STR)
4710 /* if this is remateriazable */
4711 if (AOP_TYPE (result) == AOP_IMMD)
4712 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4714 { /* we need to get it byte by byte */
4715 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4716 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4717 if (options.model == MODEL_FLAT24)
4719 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4723 /* so dptr know contains the address */
4724 freeAsmop (result, NULL, ic, TRUE);
4725 aopOp (right, ic, FALSE);
4727 /* if bit then unpack */
4728 if (IS_BITVAR (retype))
4729 genPackBits (retype, right, "dptr", FPOINTER);
4732 size = AOP_SIZE (right);
4737 char *l = aopGet (AOP (right), offset++);
4739 emitcode ("movx", "@dptr,a");
4741 emitcode ("inc", "dptr");
4745 freeAsmop (right, NULL, ic, TRUE);
4748 /*-----------------------------------------------------------------*/
4749 /* genGenPointerSet - set value from generic pointer space */
4750 /*-----------------------------------------------------------------*/
4752 genGenPointerSet (operand * right,
4753 operand * result, iCode * ic)
4756 sym_link *retype = getSpec (operandType (right));
4758 aopOp (result, ic, FALSE);
4760 /* if the operand is already in dptr
4761 then we do nothing else we move the value to dptr */
4762 if (AOP_TYPE (result) != AOP_STR)
4764 /* if this is remateriazable */
4765 if (AOP_TYPE (result) == AOP_IMMD)
4767 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4768 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0));
4771 { /* we need to get it byte by byte */
4772 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4773 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4774 if (options.model == MODEL_FLAT24)
4776 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4777 emitcode ("mov", "b,%s", aopGet (AOP (result), 3));
4781 emitcode ("mov", "b,%s", aopGet (AOP (result), 2));
4785 /* so dptr know contains the address */
4786 freeAsmop (result, NULL, ic, TRUE);
4787 aopOp (right, ic, FALSE);
4789 /* if bit then unpack */
4790 if (IS_BITVAR (retype))
4791 genPackBits (retype, right, "dptr", GPOINTER);
4794 size = AOP_SIZE (right);
4799 char *l = aopGet (AOP (right), offset++);
4801 emitcode ("lcall", "__gptrput");
4803 emitcode ("inc", "dptr");
4807 freeAsmop (right, NULL, ic, TRUE);
4810 /*-----------------------------------------------------------------*/
4811 /* genPointerSet - stores the value into a pointer location */
4812 /*-----------------------------------------------------------------*/
4814 genPointerSet (iCode * ic)
4816 operand *right, *result;
4817 sym_link *type, *etype;
4820 right = IC_RIGHT (ic);
4821 result = IC_RESULT (ic);
4823 /* depending on the type of pointer we need to
4824 move it to the correct pointer register */
4825 type = operandType (result);
4826 etype = getSpec (type);
4827 /* if left is of type of pointer then it is simple */
4828 if (IS_PTR (type) && !IS_FUNC (type->next))
4830 p_type = DCL_TYPE (type);
4834 /* we have to go by the storage class */
4835 p_type = PTR_TYPE (SPEC_OCLS (etype));
4837 /* if (SPEC_OCLS(etype)->codesp ) { */
4838 /* p_type = CPOINTER ; */
4841 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4842 /* p_type = FPOINTER ; */
4844 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4845 /* p_type = PPOINTER ; */
4847 /* if (SPEC_OCLS(etype) == idata ) */
4848 /* p_type = IPOINTER ; */
4850 /* p_type = POINTER ; */
4853 /* now that we have the pointer type we assign
4854 the pointer values */
4860 genNearPointerSet (right, result, ic);
4864 genPagedPointerSet (right, result, ic);
4868 genFarPointerSet (right, result, ic);
4872 genGenPointerSet (right, result, ic);
4878 /*-----------------------------------------------------------------*/
4879 /* genIfx - generate code for Ifx statement */
4880 /*-----------------------------------------------------------------*/
4882 genIfx (iCode * ic, iCode * popIc)
4884 operand *cond = IC_COND (ic);
4887 aopOp (cond, ic, FALSE);
4889 /* get the value into acc */
4890 if (AOP_TYPE (cond) != AOP_CRY)
4891 toBoolean (cond, "", 0);
4894 /* the result is now in the accumulator */
4895 freeAsmop (cond, NULL, ic, TRUE);
4897 /* if there was something to be popped then do it */
4901 /* if the condition is a bit variable */
4902 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4903 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4906 /* if (isbit && !IS_ITEMP(cond)) */
4907 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4909 /* // genIfxJump(ic,"a"); */
4914 /*-----------------------------------------------------------------*/
4915 /* genAddrOf - generates code for address of */
4916 /*-----------------------------------------------------------------*/
4918 genAddrOf (iCode * ic)
4920 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4923 aopOp (IC_RESULT (ic), ic, FALSE);
4925 /* if the operand is on the stack then we
4926 need to get the stack offset of this
4930 /* if it has an offset then we need to compute
4934 emitcode ("mov", "a,_bp");
4935 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
4936 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4940 /* we can just move _bp */
4941 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4943 /* fill the result with zero */
4944 size = AOP_SIZE (IC_RESULT (ic)) - 1;
4947 if (options.stack10bit && size < (FPTRSIZE - 1))
4950 "*** warning: pointer to stack var truncated.\n");
4957 if (options.stack10bit && offset == 2)
4959 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
4963 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4970 /* object not on stack then we need the name */
4971 size = AOP_SIZE (IC_RESULT (ic));
4976 char s[SDCC_NAME_MAX];
4978 sprintf (s, "#(%s >> %d)",
4982 sprintf (s, "#%s", sym->rname);
4983 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4987 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4991 /*-----------------------------------------------------------------*/
4992 /* genFarFarAssign - assignment when both are in far space */
4993 /*-----------------------------------------------------------------*/
4995 genFarFarAssign (operand * result, operand * right, iCode * ic)
4997 int size = AOP_SIZE (right);
5000 /* first push the right side on to the stack */
5003 l = aopGet (AOP (right), offset++);
5005 emitcode ("push", "acc");
5008 freeAsmop (right, NULL, ic, FALSE);
5009 /* now assign DPTR to result */
5010 aopOp (result, ic, FALSE);
5011 size = AOP_SIZE (result);
5014 emitcode ("pop", "acc");
5015 aopPut (AOP (result), "a", --offset);
5017 freeAsmop (result, NULL, ic, FALSE);
5021 /*-----------------------------------------------------------------*/
5022 /* genAssign - generate code for assignment */
5023 /*-----------------------------------------------------------------*/
5025 genAssign (iCode * ic)
5027 operand *result, *right;
5029 unsigned long lit = 0L;
5031 result = IC_RESULT (ic);
5032 right = IC_RIGHT (ic);
5034 /* if they are the same */
5035 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5038 aopOp (right, ic, FALSE);
5040 /* special case both in far space */
5041 if (AOP_TYPE (right) == AOP_DPTR &&
5042 IS_TRUE_SYMOP (result) &&
5043 isOperandInFarSpace (result))
5046 genFarFarAssign (result, right, ic);
5050 aopOp (result, ic, TRUE);
5052 /* if they are the same registers */
5053 if (sameRegs (AOP (right), AOP (result)))
5056 /* if the result is a bit */
5057 if (AOP_TYPE (result) == AOP_CRY)
5060 /* if the right size is a literal then
5061 we know what the value is */
5062 if (AOP_TYPE (right) == AOP_LIT)
5064 if (((int) operandLitValue (right)))
5065 aopPut (AOP (result), one, 0);
5067 aopPut (AOP (result), zero, 0);
5071 /* the right is also a bit variable */
5072 if (AOP_TYPE (right) == AOP_CRY)
5074 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5075 aopPut (AOP (result), "c", 0);
5080 toBoolean (right, "", 0);
5081 aopPut (AOP (result), "a", 0);
5085 /* bit variables done */
5087 size = AOP_SIZE (result);
5089 if (AOP_TYPE (right) == AOP_LIT)
5090 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5092 (AOP_TYPE (result) != AOP_REG) &&
5093 (AOP_TYPE (right) == AOP_LIT) &&
5094 !IS_FLOAT (operandType (right)) &&
5097 emitcode ("clr", "a");
5100 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
5101 aopPut (AOP (result), "a", size);
5103 aopPut (AOP (result),
5104 aopGet (AOP (right), size),
5112 aopPut (AOP (result),
5113 aopGet (AOP (right), offset),
5120 freeAsmop (right, NULL, ic, FALSE);
5121 freeAsmop (result, NULL, ic, TRUE);
5124 /*-----------------------------------------------------------------*/
5125 /* genJumpTab - genrates code for jump table */
5126 /*-----------------------------------------------------------------*/
5128 genJumpTab (iCode * ic)
5133 aopOp (IC_JTCOND (ic), ic, FALSE);
5134 /* get the condition into accumulator */
5135 l = aopGet (AOP (IC_JTCOND (ic)), 0);
5137 /* multiply by three */
5138 emitcode ("add", "a,acc");
5139 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
5140 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
5142 jtab = newiTempLabel (NULL);
5143 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
5144 emitcode ("jmp", "@a+dptr");
5145 emitcode ("", "%05d$:", jtab->key + 100);
5146 /* now generate the jump labels */
5147 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5148 jtab = setNextItem (IC_JTLABELS (ic)))
5149 emitcode ("ljmp", "%05d$", jtab->key + 100);
5153 /*-----------------------------------------------------------------*/
5154 /* genCast - gen code for casting */
5155 /*-----------------------------------------------------------------*/
5157 genCast (iCode * ic)
5159 operand *result = IC_RESULT (ic);
5160 sym_link *ctype = operandType (IC_LEFT (ic));
5161 sym_link *rtype = operandType (IC_RIGHT (ic));
5162 operand *right = IC_RIGHT (ic);
5165 /* if they are equivalent then do nothing */
5166 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5169 aopOp (right, ic, FALSE);
5170 aopOp (result, ic, FALSE);
5172 /* if the result is a bit */
5173 if (AOP_TYPE (result) == AOP_CRY)
5175 /* if the right size is a literal then
5176 we know what the value is */
5177 if (AOP_TYPE (right) == AOP_LIT)
5179 if (((int) operandLitValue (right)))
5180 aopPut (AOP (result), one, 0);
5182 aopPut (AOP (result), zero, 0);
5187 /* the right is also a bit variable */
5188 if (AOP_TYPE (right) == AOP_CRY)
5190 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5191 aopPut (AOP (result), "c", 0);
5196 toBoolean (right, "", 0);
5197 aopPut (AOP (result), "a", 0);
5201 /* if they are the same size : or less */
5202 if (AOP_SIZE (result) <= AOP_SIZE (right))
5205 /* if they are in the same place */
5206 if (sameRegs (AOP (right), AOP (result)))
5209 /* if they in different places then copy */
5210 size = AOP_SIZE (result);
5214 aopPut (AOP (result),
5215 aopGet (AOP (right), offset),
5223 /* if the result is of type pointer */
5228 sym_link *type = operandType (right);
5229 sym_link *etype = getSpec (type);
5231 /* pointer to generic pointer */
5232 if (IS_GENPTR (ctype))
5237 p_type = DCL_TYPE (type);
5240 /* we have to go by the storage class */
5241 p_type = PTR_TYPE (SPEC_OCLS (etype));
5244 /* the first two bytes are known */
5245 size = GPTRSIZE - 1;
5249 aopPut (AOP (result),
5250 aopGet (AOP (right), offset),
5254 /* the last byte depending on type */
5272 /* this should never happen */
5273 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5274 "got unknown pointer type");
5277 aopPut (AOP (result), l, GPTRSIZE - 1);
5281 /* just copy the pointers */
5282 size = AOP_SIZE (result);
5286 aopPut (AOP (result),
5287 aopGet (AOP (right), offset),
5294 /* so we now know that the size of destination is greater
5295 than the size of the source */
5296 /* we move to result for the size of source */
5297 size = AOP_SIZE (right);
5301 aopPut (AOP (result),
5302 aopGet (AOP (right), offset),
5307 /* now depending on the sign of the source && destination */
5308 size = AOP_SIZE (result) - AOP_SIZE (right);
5309 /* if unsigned or not an integral type */
5310 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
5313 aopPut (AOP (result), zero, offset++);
5317 /* we need to extend the sign :{ */
5318 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5320 emitcode ("rlc", "a");
5321 emitcode ("subb", "a,acc");
5323 aopPut (AOP (result), "a", offset++);
5326 /* we are done hurray !!!! */
5329 freeAsmop (right, NULL, ic, TRUE);
5330 freeAsmop (result, NULL, ic, TRUE);
5334 /*-----------------------------------------------------------------*/
5335 /* genDjnz - generate decrement & jump if not zero instrucion */
5336 /*-----------------------------------------------------------------*/
5338 genDjnz (iCode * ic, iCode * ifx)
5344 /* if the if condition has a false label
5345 then we cannot save */
5349 /* if the minus is not of the form
5351 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5352 !IS_OP_LITERAL (IC_RIGHT (ic)))
5355 if (operandLitValue (IC_RIGHT (ic)) != 1)
5358 /* if the size of this greater than one then no
5360 if (getSize (operandType (IC_RESULT (ic))) > 1)
5363 /* otherwise we can save BIG */
5364 lbl = newiTempLabel (NULL);
5365 lbl1 = newiTempLabel (NULL);
5367 aopOp (IC_RESULT (ic), ic, FALSE);
5369 if (IS_AOP_PREG (IC_RESULT (ic)))
5371 emitcode ("dec", "%s",
5372 aopGet (AOP (IC_RESULT (ic)), 0));
5373 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5374 emitcode ("jnz", "%05d$", lbl->key + 100);
5378 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0),
5381 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5382 emitcode ("", "%05d$:", lbl->key + 100);
5383 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5384 emitcode ("", "%05d$:", lbl1->key + 100);
5386 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5391 static char *recvregs[8] =
5393 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5397 /*-----------------------------------------------------------------*/
5398 /* genReceive - generate code for a receive iCode */
5399 /*-----------------------------------------------------------------*/
5401 genReceive (iCode * ic)
5403 int size, offset = 0;
5404 aopOp (IC_RESULT (ic), ic, FALSE);
5405 size = AOP_SIZE (IC_RESULT (ic));
5408 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5411 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5414 /*-----------------------------------------------------------------*/
5415 /* gen51Code - generate code for 8051 based controllers */
5416 /*-----------------------------------------------------------------*/
5418 genAVRCode (iCode * lic)
5423 lineHead = lineCurr = NULL;
5425 /* print the allocation information */
5427 printAllocInfo (currFunc, codeOutFile);
5428 /* if debug information required */
5429 /* if (options.debug && currFunc) { */
5432 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5434 emitcode("",".type %s,@function",currFunc->name);
5437 /* stack pointer name */
5441 for (ic = lic; ic; ic = ic->next)
5444 if (cln != ic->lineno)
5449 emitcode ("", "C$%s$%d$%d$%d ==.",
5450 FileBaseName (ic->filename), ic->lineno,
5451 ic->level, ic->block);
5454 emitcode (";", "%s %d", ic->filename, ic->lineno);
5457 /* if the result is marked as
5458 spilt and rematerializable or code for
5459 this has already been generated then
5461 if (resultRemat (ic) || ic->generated)
5464 /* depending on the operation */
5484 /* IPOP happens only when trying to restore a
5485 spilt live range, if there is an ifx statement
5486 following this pop then the if statement might
5487 be using some of the registers being popped which
5488 would destory the contents of the register so
5489 we need to check for this condition and handle it */
5491 ic->next->op == IFX &&
5492 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5493 genIfx (ic->next, ic);
5511 genEndFunction (ic);
5531 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5548 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5552 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5556 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5560 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5564 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5568 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5580 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5584 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5588 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5615 case GET_VALUE_AT_ADDRESS:
5620 if (POINTER_SET (ic))
5647 addSet (&_G.sendSet, ic);
5652 /* piCode(ic,stdout); */
5658 /* now we are ready to call the
5659 peep hole optimizer */
5660 if (!options.nopeep)
5661 peepHole (&lineHead);
5663 /* now do the actual printing */
5664 printLine (lineHead, codeOutFile);