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)
3748 etype = getSpec (operandType (result));
3750 /* read the first byte */
3758 emitcode ("ld", "r0,%s+", rname);
3762 emitcode ("ldm", "r0,%s+", rname);
3766 emitcode ("call", "__gptrget_pi");
3770 /* if we have bitdisplacement then it fits */
3771 /* into this byte completely or if length is */
3772 /* less than a byte */
3773 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8))
3776 /* shift right r0 */
3778 emitcode ("andi", "r0,0x%02x",
3779 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3781 aopPut (AOP (result), "r0", offset);
3785 /* bit field did not fit in a byte */
3786 rlen = SPEC_BLEN (etype) - 8;
3787 aopPut (AOP (result), "a", offset++);
3798 emitcode ("ld", "r0,%s+", rname);
3802 emitcode ("ldm", "r0,%s+", rname);
3806 emitcode ("lcall", "__gptrget_pi");
3811 /* if we are done */
3815 aopPut (AOP (result), "r0", offset++);
3821 emitcode ("andi", "r0,#0x%02x", ((unsigned char) -1) >> (-rlen));
3822 aopPut (AOP (result), "r0", offset);
3829 /*-----------------------------------------------------------------*/
3830 /* genDataPointerGet - generates code when ptr offset is known */
3831 /*-----------------------------------------------------------------*/
3833 genDataPointerGet (operand * left,
3839 int size, offset = 0;
3840 aopOp (result, ic, TRUE);
3842 /* get the string representation of the name */
3843 l = aopGet (AOP (left), 0);
3844 size = AOP_SIZE (result);
3848 sprintf (buffer, "(%s + %d)", l + 1, offset);
3850 sprintf (buffer, "%s", l + 1);
3851 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++), buffer);
3854 freeAsmop (left, NULL, ic, TRUE);
3855 freeAsmop (result, NULL, ic, TRUE);
3858 /*-----------------------------------------------------------------*/
3859 /* genNearPointerGet - emitcode for near pointer fetch */
3860 /*-----------------------------------------------------------------*/
3862 genNearPointerGet (operand * left,
3869 sym_link *rtype, *retype;
3870 sym_link *ltype = operandType (left);
3873 rtype = operandType (result);
3874 retype = getSpec (rtype);
3876 aopOp (left, ic, FALSE);
3878 /* if left is rematerialisable and
3879 result is not bit variable type and
3880 the left is pointer to data space i.e
3881 lower 128 bytes of space */
3882 if (AOP_TYPE (left) == AOP_IMMD &&
3883 !IS_BITVAR (retype) &&
3884 DCL_TYPE (ltype) == POINTER)
3886 genDataPointerGet (left, result, ic);
3890 /* if the value is already in a pointer register
3891 then don't need anything more */
3892 if (!AOP_INPREG (AOP (left)))
3894 /* otherwise get a free pointer register */
3896 preg = getFreePtr (ic, &aop, FALSE, 0);
3897 emitcode ("mov", "%s,%s",
3899 aopGet (AOP (left), 0));
3903 rname = aopGet (AOP (left), 0);
3905 freeAsmop (left, NULL, ic, TRUE);
3906 aopOp (result, ic, FALSE);
3908 /* if bitfield then unpack the bits */
3909 if (IS_BITVAR (retype))
3910 genUnpackBits (result, rname, POINTER);
3913 /* we have can just get the values */
3914 int size = AOP_SIZE (result);
3919 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
3922 emitcode ("mov", "a,@%s", rname);
3923 aopPut (AOP (result), "a", offset);
3927 sprintf (buffer, "@%s", rname);
3928 aopPut (AOP (result), buffer, offset);
3932 emitcode ("inc", "%s", rname);
3936 /* now some housekeeping stuff */
3939 /* we had to allocate for this iCode */
3940 freeAsmop (NULL, aop, ic, TRUE);
3944 /* we did not allocate which means left
3945 already in a pointer register, then
3946 if size > 0 && this could be used again
3947 we have to point it back to where it
3949 if (AOP_SIZE (result) > 1 &&
3950 !OP_SYMBOL (left)->remat &&
3951 (OP_SYMBOL (left)->liveTo > ic->seq ||
3954 int size = AOP_SIZE (result) - 1;
3956 emitcode ("dec", "%s", rname);
3961 freeAsmop (result, NULL, ic, TRUE);
3965 /*-----------------------------------------------------------------*/
3966 /* genPagedPointerGet - emitcode for paged pointer fetch */
3967 /*-----------------------------------------------------------------*/
3969 genPagedPointerGet (operand * left,
3976 sym_link *rtype, *retype;
3978 rtype = operandType (result);
3979 retype = getSpec (rtype);
3981 aopOp (left, ic, FALSE);
3983 /* if the value is already in a pointer register
3984 then don't need anything more */
3985 if (!AOP_INPREG (AOP (left)))
3987 /* otherwise get a free pointer register */
3989 preg = getFreePtr (ic, &aop, FALSE, 0);
3990 emitcode ("mov", "%s,%s",
3992 aopGet (AOP (left), 0));
3996 rname = aopGet (AOP (left), 0);
3998 freeAsmop (left, NULL, ic, TRUE);
3999 aopOp (result, ic, FALSE);
4001 /* if bitfield then unpack the bits */
4002 if (IS_BITVAR (retype))
4003 genUnpackBits (result, rname, PPOINTER);
4006 /* we have can just get the values */
4007 int size = AOP_SIZE (result);
4013 emitcode ("movx", "a,@%s", rname);
4014 aopPut (AOP (result), "a", offset);
4019 emitcode ("inc", "%s", rname);
4023 /* now some housekeeping stuff */
4026 /* we had to allocate for this iCode */
4027 freeAsmop (NULL, aop, ic, TRUE);
4031 /* we did not allocate which means left
4032 already in a pointer register, then
4033 if size > 0 && this could be used again
4034 we have to point it back to where it
4036 if (AOP_SIZE (result) > 1 &&
4037 !OP_SYMBOL (left)->remat &&
4038 (OP_SYMBOL (left)->liveTo > ic->seq ||
4041 int size = AOP_SIZE (result) - 1;
4043 emitcode ("dec", "%s", rname);
4048 freeAsmop (result, NULL, ic, TRUE);
4053 /*-----------------------------------------------------------------*/
4054 /* genFarPointerGet - gget value from far space */
4055 /*-----------------------------------------------------------------*/
4057 genFarPointerGet (operand * left,
4058 operand * result, iCode * ic)
4061 sym_link *retype = getSpec (operandType (result));
4063 aopOp (left, ic, FALSE);
4065 /* if the operand is already in dptr
4066 then we do nothing else we move the value to dptr */
4067 if (AOP_TYPE (left) != AOP_STR)
4069 /* if this is remateriazable */
4070 if (AOP_TYPE (left) == AOP_IMMD)
4071 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4073 { /* we need to get it byte by byte */
4074 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4075 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4076 if (options.model == MODEL_FLAT24)
4078 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4082 /* so dptr know contains the address */
4083 freeAsmop (left, NULL, ic, TRUE);
4084 aopOp (result, ic, FALSE);
4086 /* if bit then unpack */
4087 if (IS_BITVAR (retype))
4088 genUnpackBits (result, "dptr", FPOINTER);
4091 size = AOP_SIZE (result);
4096 emitcode ("movx", "a,@dptr");
4097 aopPut (AOP (result), "a", offset++);
4099 emitcode ("inc", "dptr");
4103 freeAsmop (result, NULL, ic, TRUE);
4106 /*-----------------------------------------------------------------*/
4107 /* emitcodePointerGet - gget value from code space */
4108 /*-----------------------------------------------------------------*/
4110 emitcodePointerGet (operand * left,
4111 operand * result, iCode * ic)
4114 sym_link *retype = getSpec (operandType (result));
4116 aopOp (left, ic, FALSE);
4118 /* if the operand is already in dptr
4119 then we do nothing else we move the value to dptr */
4120 if (AOP_TYPE (left) != AOP_STR)
4122 /* if this is remateriazable */
4123 if (AOP_TYPE (left) == AOP_IMMD)
4124 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4126 { /* we need to get it byte by byte */
4127 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4128 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4129 if (options.model == MODEL_FLAT24)
4131 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4135 /* so dptr know contains the address */
4136 freeAsmop (left, NULL, ic, TRUE);
4137 aopOp (result, ic, FALSE);
4139 /* if bit then unpack */
4140 if (IS_BITVAR (retype))
4141 genUnpackBits (result, "dptr", CPOINTER);
4144 size = AOP_SIZE (result);
4149 emitcode ("clr", "a");
4150 emitcode ("movc", "a,@a+dptr");
4151 aopPut (AOP (result), "a", offset++);
4153 emitcode ("inc", "dptr");
4157 freeAsmop (result, NULL, ic, TRUE);
4160 /*-----------------------------------------------------------------*/
4161 /* genGenPointerGet - gget value from generic pointer space */
4162 /*-----------------------------------------------------------------*/
4164 genGenPointerGet (operand * left,
4165 operand * result, iCode * ic)
4168 sym_link *retype = getSpec (operandType (result));
4170 aopOp (left, ic, FALSE);
4172 /* if the operand is already in dptr
4173 then we do nothing else we move the value to dptr */
4174 if (AOP_TYPE (left) != AOP_STR)
4176 /* if this is remateriazable */
4177 if (AOP_TYPE (left) == AOP_IMMD)
4179 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4180 emitcode ("mov", "b,#%d", pointerCode (retype));
4183 { /* we need to get it byte by byte */
4184 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4185 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4186 if (options.model == MODEL_FLAT24)
4188 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4189 emitcode ("mov", "b,%s", aopGet (AOP (left), 3));
4193 emitcode ("mov", "b,%s", aopGet (AOP (left), 2));
4197 /* so dptr know contains the address */
4198 freeAsmop (left, NULL, ic, TRUE);
4199 aopOp (result, ic, FALSE);
4201 /* if bit then unpack */
4202 if (IS_BITVAR (retype))
4203 genUnpackBits (result, "dptr", GPOINTER);
4206 size = AOP_SIZE (result);
4211 emitcode ("lcall", "__gptrget");
4212 aopPut (AOP (result), "a", offset++);
4214 emitcode ("inc", "dptr");
4218 freeAsmop (result, NULL, ic, TRUE);
4221 /*-----------------------------------------------------------------*/
4222 /* genPointerGet - generate code for pointer get */
4223 /*-----------------------------------------------------------------*/
4225 genPointerGet (iCode * ic)
4227 operand *left, *result;
4228 sym_link *type, *etype;
4231 left = IC_LEFT (ic);
4232 result = IC_RESULT (ic);
4234 /* depending on the type of pointer we need to
4235 move it to the correct pointer register */
4236 type = operandType (left);
4237 etype = getSpec (type);
4238 /* if left is of type of pointer then it is simple */
4239 if (IS_PTR (type) && !IS_FUNC (type->next))
4240 p_type = DCL_TYPE (type);
4243 /* we have to go by the storage class */
4244 p_type = PTR_TYPE (SPEC_OCLS (etype));
4246 /* if (SPEC_OCLS(etype)->codesp ) { */
4247 /* p_type = CPOINTER ; */
4250 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4251 /* p_type = FPOINTER ; */
4253 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4254 /* p_type = PPOINTER; */
4256 /* if (SPEC_OCLS(etype) == idata ) */
4257 /* p_type = IPOINTER; */
4259 /* p_type = POINTER ; */
4262 /* now that we have the pointer type we assign
4263 the pointer values */
4269 genNearPointerGet (left, result, ic);
4273 genPagedPointerGet (left, result, ic);
4277 genFarPointerGet (left, result, ic);
4281 emitcodePointerGet (left, result, ic);
4285 genGenPointerGet (left, result, ic);
4291 /*-----------------------------------------------------------------*/
4292 /* genPackBits - generates code for packed bit storage */
4293 /*-----------------------------------------------------------------*/
4295 genPackBits (sym_link * etype,
4297 char *rname, int p_type)
4305 blen = SPEC_BLEN (etype);
4306 bstr = SPEC_BSTR (etype);
4308 l = aopGet (AOP (right), offset++);
4311 /* if the bit lenth is less than or */
4312 /* it exactly fits a byte then */
4313 if (SPEC_BLEN (etype) <= 8)
4315 shCount = SPEC_BSTR (etype);
4317 /* shift left acc */
4320 if (SPEC_BLEN (etype) < 8)
4321 { /* if smaller than a byte */
4327 emitcode ("mov", "b,a");
4328 emitcode ("mov", "a,@%s", rname);
4332 emitcode ("mov", "b,a");
4333 emitcode ("movx", "a,@dptr");
4337 emitcode ("push", "b");
4338 emitcode ("push", "acc");
4339 emitcode ("lcall", "__gptrget");
4340 emitcode ("pop", "b");
4344 emitcode ("anl", "a,#0x%02x", (unsigned char)
4345 ((unsigned char) (0xFF << (blen + bstr)) |
4346 (unsigned char) (0xFF >> (8 - bstr))));
4347 emitcode ("orl", "a,b");
4348 if (p_type == GPOINTER)
4349 emitcode ("pop", "b");
4356 emitcode ("mov", "@%s,a", rname);
4360 emitcode ("movx", "@dptr,a");
4364 emitcode ("lcall", "__gptrput");
4369 if (SPEC_BLEN (etype) <= 8)
4372 emitcode ("inc", "%s", rname);
4373 rLen = SPEC_BLEN (etype);
4375 /* now generate for lengths greater than one byte */
4379 l = aopGet (AOP (right), offset++);
4391 emitcode ("mov", "@%s,a", rname);
4394 emitcode ("mov", "@%s,%s", rname, l);
4399 emitcode ("movx", "@dptr,a");
4404 emitcode ("lcall", "__gptrput");
4407 emitcode ("inc", "%s", rname);
4412 /* last last was not complete */
4415 /* save the byte & read byte */
4419 emitcode ("mov", "b,a");
4420 emitcode ("mov", "a,@%s", rname);
4424 emitcode ("mov", "b,a");
4425 emitcode ("movx", "a,@dptr");
4429 emitcode ("push", "b");
4430 emitcode ("push", "acc");
4431 emitcode ("lcall", "__gptrget");
4432 emitcode ("pop", "b");
4436 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << -rLen));
4437 emitcode ("orl", "a,b");
4440 if (p_type == GPOINTER)
4441 emitcode ("pop", "b");
4447 emitcode ("mov", "@%s,a", rname);
4451 emitcode ("movx", "@dptr,a");
4455 emitcode ("lcall", "__gptrput");
4459 /*-----------------------------------------------------------------*/
4460 /* genDataPointerSet - remat pointer to data space */
4461 /*-----------------------------------------------------------------*/
4463 genDataPointerSet (operand * right,
4467 int size, offset = 0;
4468 char *l, buffer[256];
4470 aopOp (right, ic, FALSE);
4472 l = aopGet (AOP (result), 0);
4473 size = AOP_SIZE (right);
4477 sprintf (buffer, "(%s + %d)", l + 1, offset);
4479 sprintf (buffer, "%s", l + 1);
4480 emitcode ("mov", "%s,%s", buffer,
4481 aopGet (AOP (right), offset++));
4484 freeAsmop (right, NULL, ic, TRUE);
4485 freeAsmop (result, NULL, ic, TRUE);
4488 /*-----------------------------------------------------------------*/
4489 /* genNearPointerSet - emitcode for near pointer put */
4490 /*-----------------------------------------------------------------*/
4492 genNearPointerSet (operand * right,
4500 sym_link *ptype = operandType (result);
4502 retype = getSpec (operandType (right));
4504 aopOp (result, ic, FALSE);
4506 /* if the result is rematerializable &
4507 in data space & not a bit variable */
4508 if (AOP_TYPE (result) == AOP_IMMD &&
4509 DCL_TYPE (ptype) == POINTER &&
4510 !IS_BITVAR (retype))
4512 genDataPointerSet (right, result, ic);
4516 /* if the value is already in a pointer register
4517 then don't need anything more */
4518 if (!AOP_INPREG (AOP (result)))
4520 /* otherwise get a free pointer register */
4522 preg = getFreePtr (ic, &aop, FALSE, 0);
4523 emitcode ("mov", "%s,%s",
4525 aopGet (AOP (result), 0));
4529 rname = aopGet (AOP (result), 0);
4531 freeAsmop (result, NULL, ic, TRUE);
4532 aopOp (right, ic, FALSE);
4534 /* if bitfield then unpack the bits */
4535 if (IS_BITVAR (retype))
4536 genPackBits (retype, right, rname, POINTER);
4539 /* we have can just get the values */
4540 int size = AOP_SIZE (right);
4545 l = aopGet (AOP (right), offset);
4549 emitcode ("mov", "@%s,a", rname);
4552 emitcode ("mov", "@%s,%s", rname, l);
4554 emitcode ("inc", "%s", rname);
4559 /* now some housekeeping stuff */
4562 /* we had to allocate for this iCode */
4563 freeAsmop (NULL, aop, ic, TRUE);
4567 /* we did not allocate which means left
4568 already in a pointer register, then
4569 if size > 0 && this could be used again
4570 we have to point it back to where it
4572 if (AOP_SIZE (right) > 1 &&
4573 !OP_SYMBOL (result)->remat &&
4574 (OP_SYMBOL (result)->liveTo > ic->seq ||
4577 int size = AOP_SIZE (right) - 1;
4579 emitcode ("dec", "%s", rname);
4584 freeAsmop (right, NULL, ic, TRUE);
4589 /*-----------------------------------------------------------------*/
4590 /* genPagedPointerSet - emitcode for Paged pointer put */
4591 /*-----------------------------------------------------------------*/
4593 genPagedPointerSet (operand * right,
4602 retype = getSpec (operandType (right));
4604 aopOp (result, ic, FALSE);
4606 /* if the value is already in a pointer register
4607 then don't need anything more */
4608 if (!AOP_INPREG (AOP (result)))
4610 /* otherwise get a free pointer register */
4612 preg = getFreePtr (ic, &aop, FALSE, 0);
4613 emitcode ("mov", "%s,%s",
4615 aopGet (AOP (result), 0));
4619 rname = aopGet (AOP (result), 0);
4621 freeAsmop (result, NULL, ic, TRUE);
4622 aopOp (right, ic, FALSE);
4624 /* if bitfield then unpack the bits */
4625 if (IS_BITVAR (retype))
4626 genPackBits (retype, right, rname, PPOINTER);
4629 /* we have can just get the values */
4630 int size = AOP_SIZE (right);
4635 l = aopGet (AOP (right), offset);
4638 emitcode ("movx", "@%s,a", rname);
4641 emitcode ("inc", "%s", rname);
4647 /* now some housekeeping stuff */
4650 /* we had to allocate for this iCode */
4651 freeAsmop (NULL, aop, ic, TRUE);
4655 /* we did not allocate which means left
4656 already in a pointer register, then
4657 if size > 0 && this could be used again
4658 we have to point it back to where it
4660 if (AOP_SIZE (right) > 1 &&
4661 !OP_SYMBOL (result)->remat &&
4662 (OP_SYMBOL (result)->liveTo > ic->seq ||
4665 int size = AOP_SIZE (right) - 1;
4667 emitcode ("dec", "%s", rname);
4672 freeAsmop (right, NULL, ic, TRUE);
4677 /*-----------------------------------------------------------------*/
4678 /* genFarPointerSet - set value from far space */
4679 /*-----------------------------------------------------------------*/
4681 genFarPointerSet (operand * right,
4682 operand * result, iCode * ic)
4685 sym_link *retype = getSpec (operandType (right));
4687 aopOp (result, ic, FALSE);
4689 /* if the operand is already in dptr
4690 then we do nothing else we move the value to dptr */
4691 if (AOP_TYPE (result) != AOP_STR)
4693 /* if this is remateriazable */
4694 if (AOP_TYPE (result) == AOP_IMMD)
4695 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4697 { /* we need to get it byte by byte */
4698 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4699 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4700 if (options.model == MODEL_FLAT24)
4702 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4706 /* so dptr know contains the address */
4707 freeAsmop (result, NULL, ic, TRUE);
4708 aopOp (right, ic, FALSE);
4710 /* if bit then unpack */
4711 if (IS_BITVAR (retype))
4712 genPackBits (retype, right, "dptr", FPOINTER);
4715 size = AOP_SIZE (right);
4720 char *l = aopGet (AOP (right), offset++);
4722 emitcode ("movx", "@dptr,a");
4724 emitcode ("inc", "dptr");
4728 freeAsmop (right, NULL, ic, TRUE);
4731 /*-----------------------------------------------------------------*/
4732 /* genGenPointerSet - set value from generic pointer space */
4733 /*-----------------------------------------------------------------*/
4735 genGenPointerSet (operand * right,
4736 operand * result, iCode * ic)
4739 sym_link *retype = getSpec (operandType (right));
4741 aopOp (result, ic, FALSE);
4743 /* if the operand is already in dptr
4744 then we do nothing else we move the value to dptr */
4745 if (AOP_TYPE (result) != AOP_STR)
4747 /* if this is remateriazable */
4748 if (AOP_TYPE (result) == AOP_IMMD)
4750 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4751 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0));
4754 { /* we need to get it byte by byte */
4755 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4756 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4757 if (options.model == MODEL_FLAT24)
4759 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4760 emitcode ("mov", "b,%s", aopGet (AOP (result), 3));
4764 emitcode ("mov", "b,%s", aopGet (AOP (result), 2));
4768 /* so dptr know contains the address */
4769 freeAsmop (result, NULL, ic, TRUE);
4770 aopOp (right, ic, FALSE);
4772 /* if bit then unpack */
4773 if (IS_BITVAR (retype))
4774 genPackBits (retype, right, "dptr", GPOINTER);
4777 size = AOP_SIZE (right);
4782 char *l = aopGet (AOP (right), offset++);
4784 emitcode ("lcall", "__gptrput");
4786 emitcode ("inc", "dptr");
4790 freeAsmop (right, NULL, ic, TRUE);
4793 /*-----------------------------------------------------------------*/
4794 /* genPointerSet - stores the value into a pointer location */
4795 /*-----------------------------------------------------------------*/
4797 genPointerSet (iCode * ic)
4799 operand *right, *result;
4800 sym_link *type, *etype;
4803 right = IC_RIGHT (ic);
4804 result = IC_RESULT (ic);
4806 /* depending on the type of pointer we need to
4807 move it to the correct pointer register */
4808 type = operandType (result);
4809 etype = getSpec (type);
4810 /* if left is of type of pointer then it is simple */
4811 if (IS_PTR (type) && !IS_FUNC (type->next))
4813 p_type = DCL_TYPE (type);
4817 /* we have to go by the storage class */
4818 p_type = PTR_TYPE (SPEC_OCLS (etype));
4820 /* if (SPEC_OCLS(etype)->codesp ) { */
4821 /* p_type = CPOINTER ; */
4824 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4825 /* p_type = FPOINTER ; */
4827 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4828 /* p_type = PPOINTER ; */
4830 /* if (SPEC_OCLS(etype) == idata ) */
4831 /* p_type = IPOINTER ; */
4833 /* p_type = POINTER ; */
4836 /* now that we have the pointer type we assign
4837 the pointer values */
4843 genNearPointerSet (right, result, ic);
4847 genPagedPointerSet (right, result, ic);
4851 genFarPointerSet (right, result, ic);
4855 genGenPointerSet (right, result, ic);
4861 /*-----------------------------------------------------------------*/
4862 /* genIfx - generate code for Ifx statement */
4863 /*-----------------------------------------------------------------*/
4865 genIfx (iCode * ic, iCode * popIc)
4867 operand *cond = IC_COND (ic);
4870 aopOp (cond, ic, FALSE);
4872 /* get the value into acc */
4873 if (AOP_TYPE (cond) != AOP_CRY)
4874 toBoolean (cond, "", 0);
4877 /* the result is now in the accumulator */
4878 freeAsmop (cond, NULL, ic, TRUE);
4880 /* if there was something to be popped then do it */
4884 /* if the condition is a bit variable */
4885 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4886 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4889 /* if (isbit && !IS_ITEMP(cond)) */
4890 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4892 /* // genIfxJump(ic,"a"); */
4897 /*-----------------------------------------------------------------*/
4898 /* genAddrOf - generates code for address of */
4899 /*-----------------------------------------------------------------*/
4901 genAddrOf (iCode * ic)
4903 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4906 aopOp (IC_RESULT (ic), ic, FALSE);
4908 /* if the operand is on the stack then we
4909 need to get the stack offset of this
4913 /* if it has an offset then we need to compute
4917 emitcode ("mov", "a,_bp");
4918 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
4919 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4923 /* we can just move _bp */
4924 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4926 /* fill the result with zero */
4927 size = AOP_SIZE (IC_RESULT (ic)) - 1;
4930 if (options.stack10bit && size < (FPTRSIZE - 1))
4933 "*** warning: pointer to stack var truncated.\n");
4940 if (options.stack10bit && offset == 2)
4942 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
4946 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4953 /* object not on stack then we need the name */
4954 size = AOP_SIZE (IC_RESULT (ic));
4959 char s[SDCC_NAME_MAX];
4961 sprintf (s, "#(%s >> %d)",
4965 sprintf (s, "#%s", sym->rname);
4966 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4970 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4974 /*-----------------------------------------------------------------*/
4975 /* genFarFarAssign - assignment when both are in far space */
4976 /*-----------------------------------------------------------------*/
4978 genFarFarAssign (operand * result, operand * right, iCode * ic)
4980 int size = AOP_SIZE (right);
4983 /* first push the right side on to the stack */
4986 l = aopGet (AOP (right), offset++);
4988 emitcode ("push", "acc");
4991 freeAsmop (right, NULL, ic, FALSE);
4992 /* now assign DPTR to result */
4993 aopOp (result, ic, FALSE);
4994 size = AOP_SIZE (result);
4997 emitcode ("pop", "acc");
4998 aopPut (AOP (result), "a", --offset);
5000 freeAsmop (result, NULL, ic, FALSE);
5004 /*-----------------------------------------------------------------*/
5005 /* genAssign - generate code for assignment */
5006 /*-----------------------------------------------------------------*/
5008 genAssign (iCode * ic)
5010 operand *result, *right;
5012 unsigned long lit = 0L;
5014 result = IC_RESULT (ic);
5015 right = IC_RIGHT (ic);
5017 /* if they are the same */
5018 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5021 aopOp (right, ic, FALSE);
5023 /* special case both in far space */
5024 if (AOP_TYPE (right) == AOP_DPTR &&
5025 IS_TRUE_SYMOP (result) &&
5026 isOperandInFarSpace (result))
5029 genFarFarAssign (result, right, ic);
5033 aopOp (result, ic, TRUE);
5035 /* if they are the same registers */
5036 if (sameRegs (AOP (right), AOP (result)))
5039 /* if the result is a bit */
5040 if (AOP_TYPE (result) == AOP_CRY)
5043 /* if the right size is a literal then
5044 we know what the value is */
5045 if (AOP_TYPE (right) == AOP_LIT)
5047 if (((int) operandLitValue (right)))
5048 aopPut (AOP (result), one, 0);
5050 aopPut (AOP (result), zero, 0);
5054 /* the right is also a bit variable */
5055 if (AOP_TYPE (right) == AOP_CRY)
5057 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5058 aopPut (AOP (result), "c", 0);
5063 toBoolean (right, "", 0);
5064 aopPut (AOP (result), "a", 0);
5068 /* bit variables done */
5070 size = AOP_SIZE (result);
5072 if (AOP_TYPE (right) == AOP_LIT)
5073 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5075 (AOP_TYPE (result) != AOP_REG) &&
5076 (AOP_TYPE (right) == AOP_LIT) &&
5077 !IS_FLOAT (operandType (right)) &&
5080 emitcode ("clr", "a");
5083 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
5084 aopPut (AOP (result), "a", size);
5086 aopPut (AOP (result),
5087 aopGet (AOP (right), size),
5095 aopPut (AOP (result),
5096 aopGet (AOP (right), offset),
5103 freeAsmop (right, NULL, ic, FALSE);
5104 freeAsmop (result, NULL, ic, TRUE);
5107 /*-----------------------------------------------------------------*/
5108 /* genJumpTab - genrates code for jump table */
5109 /*-----------------------------------------------------------------*/
5111 genJumpTab (iCode * ic)
5116 aopOp (IC_JTCOND (ic), ic, FALSE);
5117 /* get the condition into accumulator */
5118 l = aopGet (AOP (IC_JTCOND (ic)), 0);
5120 /* multiply by three */
5121 emitcode ("add", "a,acc");
5122 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
5123 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
5125 jtab = newiTempLabel (NULL);
5126 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
5127 emitcode ("jmp", "@a+dptr");
5128 emitcode ("", "%05d$:", jtab->key + 100);
5129 /* now generate the jump labels */
5130 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5131 jtab = setNextItem (IC_JTLABELS (ic)))
5132 emitcode ("ljmp", "%05d$", jtab->key + 100);
5136 /*-----------------------------------------------------------------*/
5137 /* genCast - gen code for casting */
5138 /*-----------------------------------------------------------------*/
5140 genCast (iCode * ic)
5142 operand *result = IC_RESULT (ic);
5143 sym_link *ctype = operandType (IC_LEFT (ic));
5144 sym_link *rtype = operandType (IC_RIGHT (ic));
5145 operand *right = IC_RIGHT (ic);
5148 /* if they are equivalent then do nothing */
5149 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5152 aopOp (right, ic, FALSE);
5153 aopOp (result, ic, FALSE);
5155 /* if the result is a bit */
5156 if (AOP_TYPE (result) == AOP_CRY)
5158 /* if the right size is a literal then
5159 we know what the value is */
5160 if (AOP_TYPE (right) == AOP_LIT)
5162 if (((int) operandLitValue (right)))
5163 aopPut (AOP (result), one, 0);
5165 aopPut (AOP (result), zero, 0);
5170 /* the right is also a bit variable */
5171 if (AOP_TYPE (right) == AOP_CRY)
5173 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5174 aopPut (AOP (result), "c", 0);
5179 toBoolean (right, "", 0);
5180 aopPut (AOP (result), "a", 0);
5184 /* if they are the same size : or less */
5185 if (AOP_SIZE (result) <= AOP_SIZE (right))
5188 /* if they are in the same place */
5189 if (sameRegs (AOP (right), AOP (result)))
5192 /* if they in different places then copy */
5193 size = AOP_SIZE (result);
5197 aopPut (AOP (result),
5198 aopGet (AOP (right), offset),
5206 /* if the result is of type pointer */
5211 sym_link *type = operandType (right);
5212 sym_link *etype = getSpec (type);
5214 /* pointer to generic pointer */
5215 if (IS_GENPTR (ctype))
5220 p_type = DCL_TYPE (type);
5223 /* we have to go by the storage class */
5224 p_type = PTR_TYPE (SPEC_OCLS (etype));
5227 /* the first two bytes are known */
5228 size = GPTRSIZE - 1;
5232 aopPut (AOP (result),
5233 aopGet (AOP (right), offset),
5237 /* the last byte depending on type */
5255 /* this should never happen */
5256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5257 "got unknown pointer type");
5260 aopPut (AOP (result), l, GPTRSIZE - 1);
5264 /* just copy the pointers */
5265 size = AOP_SIZE (result);
5269 aopPut (AOP (result),
5270 aopGet (AOP (right), offset),
5277 /* so we now know that the size of destination is greater
5278 than the size of the source */
5279 /* we move to result for the size of source */
5280 size = AOP_SIZE (right);
5284 aopPut (AOP (result),
5285 aopGet (AOP (right), offset),
5290 /* now depending on the sign of the source && destination */
5291 size = AOP_SIZE (result) - AOP_SIZE (right);
5292 /* if unsigned or not an integral type */
5293 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
5296 aopPut (AOP (result), zero, offset++);
5300 /* we need to extend the sign :{ */
5301 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5303 emitcode ("rlc", "a");
5304 emitcode ("subb", "a,acc");
5306 aopPut (AOP (result), "a", offset++);
5309 /* we are done hurray !!!! */
5312 freeAsmop (right, NULL, ic, TRUE);
5313 freeAsmop (result, NULL, ic, TRUE);
5317 /*-----------------------------------------------------------------*/
5318 /* genDjnz - generate decrement & jump if not zero instrucion */
5319 /*-----------------------------------------------------------------*/
5321 genDjnz (iCode * ic, iCode * ifx)
5327 /* if the if condition has a false label
5328 then we cannot save */
5332 /* if the minus is not of the form
5334 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5335 !IS_OP_LITERAL (IC_RIGHT (ic)))
5338 if (operandLitValue (IC_RIGHT (ic)) != 1)
5341 /* if the size of this greater than one then no
5343 if (getSize (operandType (IC_RESULT (ic))) > 1)
5346 /* otherwise we can save BIG */
5347 lbl = newiTempLabel (NULL);
5348 lbl1 = newiTempLabel (NULL);
5350 aopOp (IC_RESULT (ic), ic, FALSE);
5352 if (IS_AOP_PREG (IC_RESULT (ic)))
5354 emitcode ("dec", "%s",
5355 aopGet (AOP (IC_RESULT (ic)), 0));
5356 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5357 emitcode ("jnz", "%05d$", lbl->key + 100);
5361 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0),
5364 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5365 emitcode ("", "%05d$:", lbl->key + 100);
5366 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5367 emitcode ("", "%05d$:", lbl1->key + 100);
5369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5374 static char *recvregs[8] =
5376 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5380 /*-----------------------------------------------------------------*/
5381 /* genReceive - generate code for a receive iCode */
5382 /*-----------------------------------------------------------------*/
5384 genReceive (iCode * ic)
5386 int size, offset = 0;
5387 aopOp (IC_RESULT (ic), ic, FALSE);
5388 size = AOP_SIZE (IC_RESULT (ic));
5391 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5394 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5397 /*-----------------------------------------------------------------*/
5398 /* gen51Code - generate code for 8051 based controllers */
5399 /*-----------------------------------------------------------------*/
5401 genAVRCode (iCode * lic)
5406 lineHead = lineCurr = NULL;
5408 /* print the allocation information */
5410 printAllocInfo (currFunc, codeOutFile);
5411 /* if debug information required */
5412 /* if (options.debug && currFunc) { */
5415 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5417 emitcode("",".type %s,@function",currFunc->name);
5420 /* stack pointer name */
5424 for (ic = lic; ic; ic = ic->next)
5427 if (cln != ic->lineno)
5432 emitcode ("", "C$%s$%d$%d$%d ==.",
5433 FileBaseName (ic->filename), ic->lineno,
5434 ic->level, ic->block);
5437 emitcode (";", "%s %d", ic->filename, ic->lineno);
5440 /* if the result is marked as
5441 spilt and rematerializable or code for
5442 this has already been generated then
5444 if (resultRemat (ic) || ic->generated)
5447 /* depending on the operation */
5467 /* IPOP happens only when trying to restore a
5468 spilt live range, if there is an ifx statement
5469 following this pop then the if statement might
5470 be using some of the registers being popped which
5471 would destory the contents of the register so
5472 we need to check for this condition and handle it */
5474 ic->next->op == IFX &&
5475 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5476 genIfx (ic->next, ic);
5494 genEndFunction (ic);
5514 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5531 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5535 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5539 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5543 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5547 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5551 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5563 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5567 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5571 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5598 case GET_VALUE_AT_ADDRESS:
5603 if (POINTER_SET (ic))
5630 addSet (&_G.sendSet, ic);
5635 /* piCode(ic,stdout); */
5641 /* now we are ready to call the
5642 peep hole optimizer */
5643 if (!options.nopeep)
5644 peepHole (&lineHead);
5646 /* now do the actual printing */
5647 printLine (lineHead, codeOutFile);