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"};
85 extern int avr_ptrRegReq;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *, bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
94 #define CLRC emitcode("clc","")
95 #define SETC emitcode("stc","")
97 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
99 static lineNode *lineHead = NULL;
100 static lineNode *lineCurr = NULL;
102 static unsigned char SLMask[] =
103 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
104 0xE0, 0xC0, 0x80, 0x00};
105 static unsigned char SRMask[] =
106 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107 0x07, 0x03, 0x01, 0x00};
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple */
116 /*-----------------------------------------------------------------*/
118 emitcode (char *inst, char *fmt,...)
121 char lb[MAX_INLINEASM];
129 sprintf (lb, "%s\t", inst);
131 sprintf (lb, "%s", inst);
132 vsprintf (lb + (strlen (lb)), fmt, ap);
135 vsprintf (lb, fmt, ap);
137 while (isspace (*lbp))
141 lineCurr = (lineCurr ?
142 connectLine (lineCurr, newLineNode (lb)) :
143 (lineHead = newLineNode (lb)));
144 lineCurr->isInline = _G.inLine;
145 lineCurr->isDebug = _G.debugLine;
149 /*-----------------------------------------------------------------*/
150 /* getFreePtr - returns X or Z whichever is free or can be pushed */
151 /*-----------------------------------------------------------------*/
153 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
155 bool xiu = FALSE, ziu = FALSE;
156 bool xou = FALSE, zou = FALSE;
158 /* the logic: if x & z used in the instruction
159 then we are in trouble otherwise */
161 /* first check if x & z are used by this
162 instruction, in which case we are in trouble */
163 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
164 (ziu = bitVectBitValue (ic->rUsed, Z_IDX)))
169 xou = bitVectBitValue (ic->rMask, X_IDX);
170 zou = bitVectBitValue (ic->rMask, Z_IDX);
172 /* if no usage of Z then return it */
175 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
176 (*aopp)->type = AOP_Z;
178 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
179 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
182 /* if no usage of X then return it */
183 if (!xiu && !xou && !zonly)
185 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
186 (*aopp)->type = AOP_X;
188 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
189 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
192 /* if z not used then */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 avr_regWithIdx (R30_IDX)->dname);
201 emitcode ("push", "%s",
202 avr_regWithIdx (R31_IDX)->dname);
206 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
207 (*aopp)->type = AOP_Z;
208 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
209 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
212 /* now we know they both have usage */
213 /* if x not used in this instruction */
216 /* push it if not already pushed */
219 emitcode ("push", "%s",
220 avr_regWithIdx (R26_IDX)->dname);
221 emitcode ("push", "%s",
222 avr_regWithIdx (R27_IDX)->dname);
226 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
227 (*aopp)->type = AOP_X;
229 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
230 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
244 /* other wise this is true end of the world */
245 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
246 "getFreePtr should never reach here");
250 /*-----------------------------------------------------------------*/
251 /* newAsmop - creates a new asmOp */
252 /*-----------------------------------------------------------------*/
254 newAsmop (short type)
258 aop = Safe_calloc (1, sizeof (asmop));
263 /*-----------------------------------------------------------------*/
264 /* pointerCode - returns the code for a pointer type */
265 /*-----------------------------------------------------------------*/
267 pointerCode (sym_link * etype)
270 return PTR_TYPE (SPEC_OCLS (etype));
274 /*-----------------------------------------------------------------*/
275 /* aopForSym - for a true symbol */
276 /*-----------------------------------------------------------------*/
278 aopForSym (iCode * ic, symbol * sym, bool result)
281 memmap *space = SPEC_OCLS (sym->etype);
283 /* if already has one */
287 /* assign depending on the storage class */
288 /* if it is on the stack */
291 sym->aop = aop = newAsmop (0);
292 aop->size = getSize (sym->type);
294 /* we can use std / ldd instruction */
295 if (sym->stack > 0 && (sym->stack + getSize (sym->type) - 1) <= 63)
297 aop->type = AOP_STK_D;
298 aop->aopu.aop_stk = sym->stack;
302 /* otherwise get a free pointer register X/Z */
303 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
305 /* now assign the address of the variable to
306 the pointer register */
307 if (aop->type != AOP_STK)
309 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
312 if ((sym->stack - _G.nRegsSaved) > -63)
314 emitcode ("sbiw", "%s,0x%02x",
315 aop->aopu.aop_ptr->name,
316 (sym->stack - _G.nRegsSaved));
320 emitcode ("subi", "%s,lo8(%d)", aop->aopu.aop_ptr->name,
321 sym->stack - _G.nRegsSaved);
322 emitcode ("sbci", "%s,hi8(%d)", aop->aop_ptr2->name,
323 sym->stack - _G.nRegsSaved);
328 if (sym->stack <= 63)
330 emitcode ("adiw", "%s,0x%02x", aop->aopu.aop_ptr->name, sym->stack);
334 emitcode ("subi", "%s,lo8(-%d)", aop->aopu.aop_ptr->name, sym->stack);
335 emitcode ("sbci", "%s,hi8(-%d)", aop->aop_ptr2->name, sym->stack);
342 /* if in bit space */
343 if (IN_BITSPACE (space))
345 sym->aop = aop = newAsmop (AOP_CRY);
346 aop->aopu.aop_dir = sym->rname;
347 aop->size = getSize (sym->type);
350 /* if it is in direct space */
351 if (IN_DIRSPACE (space))
353 sym->aop = aop = newAsmop (AOP_DIR);
354 aop->aopu.aop_dir = sym->rname;
355 aop->size = getSize (sym->type);
359 /* special case for a function */
360 if (IS_FUNC (sym->type))
362 sym->aop = aop = newAsmop (AOP_IMMD);
363 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
364 strcpy (aop->aopu.aop_immd, sym->rname);
365 aop->size = FPTRSIZE;
369 /* only remaining is code / eeprom which will need pointer reg */
370 /* if it is in code space */
372 sym->aop = aop = newAsmop (0);
374 if (IN_CODESPACE (space))
377 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
378 aop->size = getSize (sym->type);
379 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
380 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
385 /*-----------------------------------------------------------------*/
386 /* aopForRemat - rematerialzes an object */
387 /*-----------------------------------------------------------------*/
389 aopForRemat (symbol * sym)
391 iCode *ic = sym->rematiCode;
392 asmop *aop = newAsmop (AOP_IMMD);
398 val += (int) operandLitValue (IC_RIGHT (ic));
399 else if (ic->op == '-')
400 val -= (int) operandLitValue (IC_RIGHT (ic));
404 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
408 sprintf (buffer, "(%s %c 0x%04x)",
409 OP_SYMBOL (IC_LEFT (ic))->rname,
410 val >= 0 ? '+' : '-',
413 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
415 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
416 strcpy (aop->aopu.aop_immd, buffer);
420 /*-----------------------------------------------------------------*/
421 /* regsInCommon - two operands have some registers in common */
422 /*-----------------------------------------------------------------*/
424 regsInCommon (operand * op1, operand * op2)
429 /* if they have registers in common */
430 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
433 sym1 = OP_SYMBOL (op1);
434 sym2 = OP_SYMBOL (op2);
436 if (sym1->nRegs == 0 || sym2->nRegs == 0)
439 for (i = 0; i < sym1->nRegs; i++)
445 for (j = 0; j < sym2->nRegs; j++)
450 if (sym2->regs[j] == sym1->regs[i])
458 /*-----------------------------------------------------------------*/
459 /* operandsEqu - equivalent */
460 /*-----------------------------------------------------------------*/
462 operandsEqu (operand * op1, operand * op2)
466 /* if they not symbols */
467 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
470 sym1 = OP_SYMBOL (op1);
471 sym2 = OP_SYMBOL (op2);
473 /* if both are itemps & one is spilt
474 and the other is not then false */
475 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
476 sym1->isspilt != sym2->isspilt)
479 /* if they are the same */
483 if (strcmp (sym1->rname, sym2->rname) == 0)
487 /* if left is a tmp & right is not */
488 if (IS_ITEMP (op1) &&
491 (sym1->usl.spillLoc == sym2))
494 if (IS_ITEMP (op2) &&
498 (sym2->usl.spillLoc == sym1))
504 /*-----------------------------------------------------------------*/
505 /* sameRegs - two asmops have the same registers */
506 /*-----------------------------------------------------------------*/
508 sameRegs (asmop * aop1, asmop * aop2)
515 if (aop1->type != AOP_REG ||
516 aop2->type != AOP_REG)
519 if (aop1->size != aop2->size)
522 for (i = 0; i < aop1->size; i++)
523 if (aop1->aopu.aop_reg[i] !=
524 aop2->aopu.aop_reg[i])
530 /*-----------------------------------------------------------------*/
531 /* isRegPair - for size 2 if this operand has a register pair */
532 /*-----------------------------------------------------------------*/
534 isRegPair (asmop * aop)
536 if (!aop || aop->size != 2)
538 if (aop->type == AOP_X || aop->type == AOP_Z)
540 if (aop->type != AOP_REG)
542 if ((aop->aopu.aop_reg[1]->rIdx -
543 aop->aopu.aop_reg[0]->rIdx) == 1)
548 /*-----------------------------------------------------------------*/
549 /* aopOp - allocates an asmop for an operand : */
550 /*-----------------------------------------------------------------*/
552 aopOp (operand * op, iCode * ic, bool result)
561 /* if this a literal */
562 if (IS_OP_LITERAL (op))
564 op->aop = aop = newAsmop (AOP_LIT);
565 aop->aopu.aop_lit = op->operand.valOperand;
566 aop->size = getSize (operandType (op));
570 /* if already has a asmop then continue */
574 /* if the underlying symbol has a aop */
575 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
577 op->aop = OP_SYMBOL (op)->aop;
581 /* if this is a true symbol */
582 if (IS_TRUE_SYMOP (op))
584 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
588 /* this is a temporary : this has
594 e) can be a return use only */
596 sym = OP_SYMBOL (op);
599 /* if the type is a conditional */
600 if (sym->regType == REG_CND)
602 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
607 /* if it is spilt then two situations
609 b) has a spill location */
610 if (sym->isspilt || sym->nRegs == 0)
613 /* rematerialize it NOW */
616 sym->aop = op->aop = aop =
618 aop->size = getSize (sym->type);
624 assert ("ACC_USE cannot happen in AVR\n");
630 aop = op->aop = sym->aop = newAsmop (AOP_STR);
631 aop->size = getSize (sym->type);
632 for (i = 0; i < (int) fAVRReturnSize; i++)
633 aop->aopu.aop_str[i] = fAVRReturn[i];
637 /* else spill location */
638 sym->aop = op->aop = aop =
639 aopForSym (ic, sym->usl.spillLoc, result);
640 aop->size = getSize (sym->type);
644 /* must be in a register */
645 sym->aop = op->aop = aop = newAsmop (AOP_REG);
646 aop->size = sym->nRegs;
647 for (i = 0; i < sym->nRegs; i++)
648 aop->aopu.aop_reg[i] = sym->regs[i];
651 /*-----------------------------------------------------------------*/
652 /* freeAsmop - free up the asmop given to an operand */
653 /*----------------------------------------------------------------*/
655 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
672 /* depending on the asmop type only three cases need work AOP_RO
673 , AOP_R1 && AOP_STK */
681 emitcode ("pop", "r26");
682 emitcode ("pop", "r27");
686 bitVectUnSetBit (ic->rUsed, X_IDX);
694 emitcode ("pop", "r30");
695 emitcode ("pop", "r31");
699 bitVectUnSetBit (ic->rUsed, Z_IDX);
705 int stk = aop->aopu.aop_stk + aop->size;
706 bitVectUnSetBit (ic->rUsed, X_IDX);
707 bitVectUnSetBit (ic->rUsed, Z_IDX);
709 getFreePtr (ic, &aop, FALSE, 0);
711 emitcode ("movw", "%s,r28");
714 if (stk <= 63 && stk > 0)
716 emitcode ("adiw", "%s,0x%02x", aop->aopu.aop_ptr->name, stk + 1);
720 emitcode ("subi", "%s,lo8(%d)", aop->aopu.aop_ptr->name, -(stk + 1));
721 emitcode ("sbci", "%s,hi8(%d)", aop->aop_ptr2->name, -(stk + 1));
727 emitcode ("pop", "r24");
728 emitcode ("st", "-%s,r24", aop->type == AOP_X ? "X" : "Z");
733 freeAsmop (op, NULL, ic, TRUE);
736 emitcode ("pop", "r26");
737 emitcode ("pop", "r27");
743 emitcode ("pop", "r30");
744 emitcode ("pop", "r31");
751 /* all other cases just dealloc */
757 OP_SYMBOL (op)->aop = NULL;
758 /* if the symbol has a spill */
760 SPIL_LOC (op)->aop = NULL;
765 /*-----------------------------------------------------------------*/
766 /* aopGet - for fetching value of the aop */
767 /*-----------------------------------------------------------------*/
769 aopGet (asmop * aop, int offset)
774 /* offset is greater than
776 if (offset > (aop->size - 1) &&
777 aop->type != AOP_LIT)
780 /* depending on type */
785 if (offset > aop->coff)
787 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name, offset - aop->coff);
790 if (offset < aop->coff)
792 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
796 emitcode ("ld", "%s,x",
797 (rs = ((offset & 1) ? "r25" : "r24")));
803 if (offset > aop->coff)
805 emitcode ("adiw", "r30,%d", offset - aop->coff);
809 emitcode ("sbiw", "r30,%d", aop->coff - offset);
811 emitcode ("lpm", "%s,z", (rs = ((offset & 1) ? "r25" : "r24")));
816 if (offset > aop->coff)
818 emitcode ("ldd", "%s,z+%d", (rs = ((offset & 1) ? "r25" : "r24")),
823 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
825 emitcode ("ld", "%s,z", (rs = ((offset & 1) ? "r25" : "r24")));
832 emitcode ("lds", "%s,(%s)+%d",
833 (rs = ((offset & 1) ? "r25" : "r24")),
834 aop->aopu.aop_immd, offset);
838 emitcode ("lds", "%s,(%s)+%d",
839 (rs = ((offset & 1) ? "r25" : "r24")),
840 aop->aopu.aop_dir, offset);
844 return aop->aopu.aop_reg[offset]->name;
847 assert ("cannot be in bit space AOP_CRY\n");
851 s = aopLiteral (aop->aopu.aop_lit, offset);
852 emitcode ("ldi", "%s,lo8(%s)", (rs = ((offset & 1) ? "r24" : "r25")), s);
857 return aop->aopu.aop_str[offset];
860 emitcode ("ldd", "%s,Y+%d",
861 (rs = ((offset & 1) ? "r25" : "r24")),
862 aop->aopu.aop_stk + offset);
866 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
867 "aopget got unsupported aop->type");
870 /*-----------------------------------------------------------------*/
871 /* aopPut - puts a string for a aop */
872 /*-----------------------------------------------------------------*/
874 aopPut (asmop * aop, char *s, int offset)
878 if (aop->size && offset > (aop->size - 1))
880 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
881 "aopPut got offset > aop->size");
885 /* will assign value to value */
886 /* depending on where it is ofcourse */
892 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
896 sprintf (d, "%s", aop->aopu.aop_dir);
899 emitcode ("sts", "%s,%s", d, s);
903 if (toupper (*s) != 'R')
907 emitcode ("clr", "%s", aop->aopu.aop_reg[offset]->name);
911 emitcode ("ldi", "r25,%s", s);
912 emitcode ("mov", "%s,r35", aop->aopu.aop_reg[offset]->name);
917 if (strcmp (aop->aopu.aop_reg[offset]->name, s))
919 emitcode ("mov", "%s,%s", aop->aopu.aop_reg[offset]->name, s);
925 if (offset > aop->coff)
927 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name, offset - aop->coff);
930 if (offset < aop->coff)
932 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
936 emitcode ("st", "x,%s", s);
942 if (offset > aop->coff)
944 emitcode ("adiw", "r30,%d", offset - aop->coff);
948 emitcode ("sbiw", "r30,%d", aop->coff - offset);
950 emitcode ("lpm", "%s,z", s);
955 if (offset > aop->coff)
957 emitcode ("sdd", "z+%d,%s", offset - aop->coff, s);
961 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, aop->coff - offset);
963 emitcode ("ld", "%s,z", s);
969 emitcode ("push", "%s", s);
973 /* if used only for a condition code check */
974 assert (toupper (*s) == 'R');
977 emitcode ("xrl", "r0,r0");
978 emitcode ("cpi", "%s,0", s);
982 emitcode ("cpc", "r0,%s", s);
988 if (strcmp (aop->aopu.aop_str[offset], s))
989 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
993 emitcode ("std", "y+%d,%s", offset, s);
997 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
998 "aopPut got unsupported aop->type");
1004 /*-----------------------------------------------------------------*/
1005 /* reAdjustPreg - points a register back to where it should */
1006 /*-----------------------------------------------------------------*/
1008 reAdjustPreg (asmop * aop)
1013 if ((size = aop->size) <= 1)
1020 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
1026 #define AOP(op) op->aop
1027 #define AOP_TYPE(op) AOP(op)->type
1028 #define AOP_SIZE(op) AOP(op)->size
1029 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1030 AOP_TYPE(x) == AOP_Z))
1031 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1032 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
1033 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
1035 /*-----------------------------------------------------------------*/
1036 /* genNotFloat - generates not for float operations */
1037 /*-----------------------------------------------------------------*/
1039 genNotFloat (operand * op, operand * res)
1045 /* we will put 127 in the first byte of
1047 aopPut (AOP (res), "127", 0);
1048 size = AOP_SIZE (op) - 1;
1051 l = aopGet (op->aop, offset++);
1056 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1058 tlbl = newiTempLabel (NULL);
1060 tlbl = newiTempLabel (NULL);
1061 aopPut (res->aop, zero, 1);
1062 emitcode ("cpi", "r0,0");
1063 emitcode ("breq", "L%05d", tlbl->key);
1064 aopPut (res->aop, one, 1);
1065 emitcode ("", "L%05d:", tlbl->key);
1067 size = res->aop->size - 2;
1069 /* put zeros in the rest */
1071 aopPut (res->aop, zero, offset++);
1074 /*-----------------------------------------------------------------*/
1075 /* opIsGptr: returns non-zero if the passed operand is */
1076 /* a generic pointer type. */
1077 /*-----------------------------------------------------------------*/
1079 opIsGptr (operand * op)
1081 sym_link *type = operandType (op);
1083 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1090 /*-----------------------------------------------------------------*/
1091 /* getDataSize - get the operand data size */
1092 /*-----------------------------------------------------------------*/
1094 getDataSize (operand * op)
1097 size = AOP_SIZE (op);
1098 if (size == GPTRSIZE)
1100 sym_link *type = operandType (op);
1101 if (IS_GENPTR (type))
1103 /* generic pointer; arithmetic operations
1104 * should ignore the high byte (pointer type).
1112 /*-----------------------------------------------------------------*/
1113 /* outAcc - output Acc */
1114 /*-----------------------------------------------------------------*/
1116 outAcc (operand * result)
1119 size = getDataSize (result);
1122 aopPut (AOP (result), "r0", 0);
1125 /* unsigned or positive */
1128 aopPut (AOP (result), zero, offset++);
1133 /*-----------------------------------------------------------------*/
1134 /* outBitC - output a bit C */
1135 /*-----------------------------------------------------------------*/
1137 outBitC (operand * result)
1139 emitcode ("clr", "r0");
1140 emitcode ("rol", "r0");
1144 /*-----------------------------------------------------------------*/
1145 /* toBoolean - emit code for orl a,operator(sizeop) */
1146 /*-----------------------------------------------------------------*/
1148 toBoolean (operand * oper, char *r, bool clr)
1150 int size = AOP_SIZE (oper);
1153 emitcode ("clr", "%s", r);
1155 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1159 /*-----------------------------------------------------------------*/
1160 /* genNot - generate code for ! operation */
1161 /*-----------------------------------------------------------------*/
1166 sym_link *optype = operandType (IC_LEFT (ic));
1167 int size, offset = 1;
1169 /* assign asmOps to operand & result */
1170 aopOp (IC_LEFT (ic), ic, FALSE);
1171 aopOp (IC_RESULT (ic), ic, TRUE);
1173 /* if type float then do float */
1174 if (IS_FLOAT (optype))
1176 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1179 emitcode ("clr", "r0");
1180 tlbl = newiTempLabel (NULL);
1181 size = AOP_SIZE (IC_LEFT (ic));
1185 emitcode ("cpse", "%s,r0", aopGet (AOP (IC_LEFT (ic)), 0));
1192 emitcode ("cpc", "%s,r0", aopGet (AOP (IC_LEFT (ic)), offset));
1194 emitcode ("cpi", "%s,0", aopGet (AOP (IC_LEFT (ic)), offset));
1197 emitcode ("bne", "L%05d", tlbl->key);
1199 emitcode ("ldi", "r0,1");
1200 emitcode ("", "L%05d:", tlbl->key);
1201 aopPut (AOP (IC_RESULT (ic)), "r0", 0);
1202 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1205 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1209 /* release the aops */
1210 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1211 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1215 /*-----------------------------------------------------------------*/
1216 /* genCpl - generate code for complement */
1217 /*-----------------------------------------------------------------*/
1225 /* assign asmOps to operand & result */
1226 aopOp (IC_LEFT (ic), ic, FALSE);
1227 aopOp (IC_RESULT (ic), ic, TRUE);
1228 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1229 size = AOP_SIZE (IC_RESULT (ic));
1232 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1235 emitcode ("com", "%s", l);
1239 aopPut (AOP (IC_RESULT (ic)), l, offset);
1240 emitcode ("com", "%s", aopGet (AOP (IC_RESULT (ic)), offset));
1245 /* release the aops */
1246 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1247 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1250 /*-----------------------------------------------------------------*/
1251 /* genUminusFloat - unary minus for floating points */
1252 /*-----------------------------------------------------------------*/
1254 genUminusFloat (operand * op, operand * result)
1256 int size, offset = 0;
1258 /* for this we just need to flip the
1259 first it then copy the rest in place */
1260 size = AOP_SIZE (op) - 1;
1261 l = aopGet (AOP (op), 3);
1263 emitcode ("ldi", "r24,0x80");
1264 if (sameRegs (AOP (op), AOP (result)))
1266 emitcode ("eor", "%s,r24", l);
1270 aopPut (AOP (result), l, 3);
1271 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1275 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1280 /*-----------------------------------------------------------------*/
1281 /* genUminus - unary minus code generation */
1282 /*-----------------------------------------------------------------*/
1284 genUminus (iCode * ic)
1287 sym_link *optype, *rtype;
1291 aopOp (IC_LEFT (ic), ic, FALSE);
1292 aopOp (IC_RESULT (ic), ic, TRUE);
1294 optype = operandType (IC_LEFT (ic));
1295 rtype = operandType (IC_RESULT (ic));
1297 /* if float then do float stuff */
1298 if (IS_FLOAT (optype))
1300 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1304 /* otherwise subtract from zero */
1305 size = AOP_SIZE (IC_LEFT (ic));
1307 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1312 emitcode ("neg", "%s", aopGet (AOP (IC_LEFT (ic)), 0));
1316 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), 0), 0);
1317 emitcode ("neg", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
1325 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1328 aopPut (AOP (IC_RESULT (ic)), l, offset);
1329 l = aopGet (AOP (IC_RESULT (ic)), offset);
1332 emitcode ("com", "%s", l);
1334 emitcode ("neg", "%s", l);
1337 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1341 emitcode ("sbci", "%s,lo8(-1)", aopGet (AOP (IC_RESULT (ic)), offset++));
1345 /* if any remaining bytes in the result */
1346 /* we just need to propagate the sign */
1347 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1349 symbol *tlbl = newiTempLabel (NULL);
1350 emitcode ("clr", "r0");
1351 emitcode ("brcc", "L%05d", tlbl->key);
1352 emitcode ("com", "r0");
1353 emitcode ("", "L%05d:", tlbl->key);
1355 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1359 /* release the aops */
1360 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1361 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1364 /*-----------------------------------------------------------------*/
1365 /* assignResultValue - */
1366 /*-----------------------------------------------------------------*/
1368 assignResultValue (operand * oper)
1371 int size = AOP_SIZE (oper);
1374 aopPut (AOP (oper), fAVRReturn[offset], offset);
1379 /*-----------------------------------------------------------------*/
1380 /* saveZreg - if indirect call then save z-pointer register */
1381 /*-----------------------------------------------------------------*/
1383 saveZreg (iCode * ic)
1385 /* only if live accross this call */
1386 if (ic->regsSaved == 0 &&
1387 (bitVectBitValue (ic->rMask, R30_IDX) ||
1388 bitVectBitValue (ic->rMask, R31_IDX)))
1391 emitcode ("push", "r30");
1392 emitcode ("push", "r31");
1396 /*-----------------------------------------------------------------*/
1397 /* popZreg - restore values of zreg */
1398 /*-----------------------------------------------------------------*/
1400 popZreg (iCode * ic)
1404 emitcode ("pop", "r31");
1405 emitcode ("pop", "r30");
1409 /*-----------------------------------------------------------------*/
1410 /* genIpush - genrate code for pushing this gets a little complex */
1411 /*-----------------------------------------------------------------*/
1413 genIpush (iCode * ic)
1415 int size, offset = 0;
1421 /* and the item is spilt then do nothing */
1422 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1428 for (lic = ic->next; lic; lic = lic->next)
1429 if (lic->op == PCALL)
1435 /* this is a paramter push */
1436 aopOp (IC_LEFT (ic), ic, FALSE);
1437 size = AOP_SIZE (IC_LEFT (ic));
1440 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1441 emitcode ("push", "%s", l);
1444 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1447 /*-----------------------------------------------------------------*/
1448 /* genIpop - recover the registers: can happen only for spilling */
1449 /*-----------------------------------------------------------------*/
1451 genIpop (iCode * ic)
1456 /* if the temp was not pushed then */
1457 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1460 aopOp (IC_LEFT (ic), ic, FALSE);
1461 size = AOP_SIZE (IC_LEFT (ic));
1462 offset = (size - 1);
1464 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1466 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1469 /*-----------------------------------------------------------------*/
1470 /* genCall - generates a call statement */
1471 /*-----------------------------------------------------------------*/
1473 genCall (iCode * ic)
1476 /* if send set is not empty the assign */
1481 for (sic = setFirstItem (_G.sendSet); sic;
1482 sic = setNextItem (_G.sendSet))
1484 int size, offset = 0;
1485 aopOp (IC_LEFT (sic), sic, FALSE);
1486 size = AOP_SIZE (IC_LEFT (sic));
1489 char *l = aopGet (AOP (IC_LEFT (sic)), offset);
1491 sprintf (buffer, "r%d", rnum++);
1493 emitcode ("mov", "%s,%s", b, l);
1496 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1501 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1502 OP_SYMBOL (IC_LEFT (ic))->rname :
1503 OP_SYMBOL (IC_LEFT (ic))->name));
1505 /* if we need assign a result value */
1506 if ((IS_ITEMP (IC_RESULT (ic)) &&
1507 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1508 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1509 IS_TRUE_SYMOP (IC_RESULT (ic)))
1512 aopOp (IC_RESULT (ic), ic, FALSE);
1513 assignResultValue (IC_RESULT (ic));
1514 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1517 /* adjust the stack for parameters if required */
1518 if (IC_LEFT (ic)->parmBytes)
1520 if (IC_LEFT (ic)->parmBytes > 63)
1522 emitcode ("sbiw", "r28,%d", IC_LEFT (ic)->parmBytes);
1526 emitcode ("subi", "r28,lo8(%d)", IC_LEFT (ic)->parmBytes);
1527 emitcode ("sbci", "r29,hi8(%d)", IC_LEFT (ic)->parmBytes);
1533 /*-----------------------------------------------------------------*/
1534 /* genPcall - generates a call by pointer statement */
1535 /*-----------------------------------------------------------------*/
1537 genPcall (iCode * ic)
1543 aopOp (IC_LEFT (ic), ic, FALSE);
1544 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1545 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1546 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1548 /* if send set is not empty the assign */
1553 for (sic = setFirstItem (_G.sendSet); sic;
1554 sic = setNextItem (_G.sendSet))
1556 int size, offset = 0;
1557 aopOp (IC_LEFT (sic), sic, FALSE);
1558 size = AOP_SIZE (IC_LEFT (sic));
1561 char *l = aopGet (AOP (IC_LEFT (sic)), offset);
1563 sprintf (b, "r%d", rnum++);
1565 emitcode ("mov", "%s,%s", b, l);
1568 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1573 emitcode ("icall", "");
1575 /* if we need assign a result value */
1576 if ((IS_ITEMP (IC_RESULT (ic)) &&
1577 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1578 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1579 IS_TRUE_SYMOP (IC_RESULT (ic)))
1582 aopOp (IC_RESULT (ic), ic, FALSE);
1584 assignResultValue (IC_RESULT (ic));
1585 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1588 /* adjust the stack for parameters if
1590 if (IC_LEFT (ic)->parmBytes)
1593 if (IC_LEFT (ic)->parmBytes > 3)
1595 emitcode ("mov", "a,%s", spname);
1596 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
1597 emitcode ("mov", "%s,a", spname);
1600 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
1601 emitcode ("dec", "%s", spname);
1605 /* adjust the stack for parameters if required */
1606 if (IC_LEFT (ic)->parmBytes)
1608 if (IC_LEFT (ic)->parmBytes > 63)
1610 emitcode ("sbiw", "r28,%d", IC_LEFT (ic)->parmBytes);
1614 emitcode ("subi", "r28,lo8(%d)", IC_LEFT (ic)->parmBytes);
1615 emitcode ("sbci", "r29,hi8(%d)", IC_LEFT (ic)->parmBytes);
1622 /*-----------------------------------------------------------------*/
1623 /* resultRemat - result is rematerializable */
1624 /*-----------------------------------------------------------------*/
1626 resultRemat (iCode * ic)
1628 if (SKIP_IC (ic) || ic->op == IFX)
1631 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
1633 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1634 if (sym->remat && !POINTER_SET (ic))
1641 #if defined(__BORLANDC__) || defined(_MSC_VER)
1642 #define STRCASECMP stricmp
1644 #define STRCASECMP strcasecmp
1647 /*-----------------------------------------------------------------*/
1648 /* inExcludeList - return 1 if the string is in exclude Reg list */
1649 /*-----------------------------------------------------------------*/
1651 inExcludeList (char *s)
1655 if (options.excludeRegs[i] &&
1656 STRCASECMP (options.excludeRegs[i], "none") == 0)
1659 for (i = 0; options.excludeRegs[i]; i++)
1661 if (options.excludeRegs[i] &&
1662 STRCASECMP (s, options.excludeRegs[i]) == 0)
1668 /*-----------------------------------------------------------------*/
1669 /* genFunction - generated code for function entry */
1670 /*-----------------------------------------------------------------*/
1672 genFunction (iCode * ic)
1679 /* create the function header */
1680 emitcode (";", "-----------------------------------------");
1681 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1682 emitcode (";", "-----------------------------------------");
1684 emitcode ("", "%s:", sym->rname);
1685 fetype = getSpec (operandType (IC_LEFT (ic)));
1687 /* if critical function then turn interrupts off */
1688 if (SPEC_CRTCL (fetype))
1689 emitcode ("cli", "");
1691 if (IS_ISR (sym->etype))
1695 /* save the preserved registers that are used in this function */
1696 for (i = R2_IDX; i <= R15_IDX; i++)
1698 if (bitVectBitValue (sym->regsUsed, i))
1701 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1704 /* now for the pointer registers */
1705 if (bitVectBitValue (sym->regsUsed, R26_IDX))
1708 emitcode ("push", "r26");
1710 if (bitVectBitValue (sym->regsUsed, R27_IDX))
1713 emitcode ("push", "r27");
1715 if (bitVectBitValue (sym->regsUsed, R30_IDX))
1718 emitcode ("push", "r30");
1720 if (bitVectBitValue (sym->regsUsed, R31_IDX))
1723 emitcode ("push", "r31");
1725 /* adjust the stack for the function */
1728 emitcode ("push", "r28");
1729 emitcode ("push", "r29");
1730 emitcode ("in", "r28,__SP_L__");
1731 emitcode ("in", "r29,__SP_H__");
1732 if (sym->stack <= 63)
1734 emitcode ("sbiw", "r28,%d", sym->stack);
1738 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1739 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1741 emitcode ("out", "__SP_L__,r28");
1742 emitcode ("out", "__SP_H__,r29");
1746 /*-----------------------------------------------------------------*/
1747 /* genEndFunction - generates epilogue for functions */
1748 /*-----------------------------------------------------------------*/
1750 genEndFunction (iCode * ic)
1752 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1755 /* restore stack pointer */
1758 if (sym->stack <= 63)
1760 emitcode ("adiw", "r28,%d", sym->stack);
1764 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1765 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1767 emitcode ("out", "__SP_L__,r28");
1768 emitcode ("out", "__SP_H__,r29");
1770 /* pop frame pointer */
1771 emitcode ("pop", "r29");
1772 emitcode ("pop", "r28");
1774 /* restore preserved registers */
1775 if (bitVectBitValue (sym->regsUsed, R31_IDX))
1778 emitcode ("pop", "r31");
1780 if (bitVectBitValue (sym->regsUsed, R30_IDX))
1783 emitcode ("pop", "r30");
1785 if (bitVectBitValue (sym->regsUsed, R27_IDX))
1788 emitcode ("push", "r27");
1790 if (bitVectBitValue (sym->regsUsed, R26_IDX))
1793 emitcode ("push", "r26");
1795 for (i = R15_IDX; i >= R2_IDX; i--)
1797 if (bitVectBitValue (sym->regsUsed, i))
1800 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1804 if (SPEC_CRTCL (sym->etype))
1805 emitcode ("sti", "");
1807 if (IS_ISR (sym->etype))
1809 emitcode ("rti", "");
1813 emitcode ("ret", "");
1818 /*-----------------------------------------------------------------*/
1819 /* genRet - generate code for return statement */
1820 /*-----------------------------------------------------------------*/
1824 int size, offset = 0;
1826 /* if we have no return value then
1827 just generate the "ret" */
1831 /* we have something to return then
1832 move the return value into place */
1833 aopOp (IC_LEFT (ic), ic, FALSE);
1834 size = AOP_SIZE (IC_LEFT (ic));
1838 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
1840 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset], larray[offset],
1841 (int) floatFromVal (AOP (IC_LEFT (ic))->aopu.aop_lit), offset);
1846 l = aopGet (AOP (IC_LEFT (ic)), offset);
1847 if (strcmp (fAVRReturn[offset], l))
1848 emitcode ("mov", "%s,%s", fAVRReturn[offset], l);
1853 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1856 /* generate a jump to the return label
1857 if the next is not the return statement */
1858 if (!(ic->next && ic->next->op == LABEL &&
1859 IC_LABEL (ic->next) == returnLabel))
1861 emitcode ("rjmp", "L%05d", returnLabel->key);
1865 /*-----------------------------------------------------------------*/
1866 /* genLabel - generates a label */
1867 /*-----------------------------------------------------------------*/
1869 genLabel (iCode * ic)
1871 /* special case never generate */
1872 if (IC_LABEL (ic) == entryLabel)
1875 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1878 /*-----------------------------------------------------------------*/
1879 /* genGoto - generates a ljmp */
1880 /*-----------------------------------------------------------------*/
1882 genGoto (iCode * ic)
1884 emitcode ("rjmp", "L%05d:", (IC_LABEL (ic)->key + 100));
1887 /*-----------------------------------------------------------------*/
1888 /* findLabelBackwards: walks back through the iCode chain looking */
1889 /* for the given label. Returns number of iCode instructions */
1890 /* between that label and given ic. */
1891 /* Returns zero if label not found. */
1892 /*-----------------------------------------------------------------*/
1894 findLabelBackwards (iCode * ic, int key)
1903 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
1905 /* printf("findLabelBackwards = %d\n", count); */
1913 /*-----------------------------------------------------------------*/
1914 /* genPlusIncr :- does addition with increment if possible */
1915 /*-----------------------------------------------------------------*/
1917 genPlusIncr (iCode * ic)
1919 unsigned int icount;
1921 /* will try to generate an increment */
1922 /* if the right side is not a literal
1924 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1927 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
1929 /* if the sizes are greater than 2 or they are not the same regs
1931 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1934 /* so we know LEFT & RESULT in the same registers and add
1936 /* for short & char types */
1937 if (AOP_SIZE (IC_RESULT (ic)) < 2)
1941 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0));
1944 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_LEFT (ic)), 0), -icount);
1948 if (AOP_SIZE (IC_RESULT (ic)) <= 3)
1950 /* if register pair and starts with 26/30 then adiw */
1951 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0 && icount < 64 &&
1952 (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1953 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX)))
1955 emitcode ("adiw", "%s,%d", aopGet (AOP (IC_RESULT (ic)), 0), icount);
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);
1965 /* for 32 bit longs */
1966 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0), -icount);
1967 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1), -icount);
1968 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2), -icount);
1969 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3), -icount);
1974 /* This is the pure and virtuous version of this code.
1975 * I'm pretty certain it's right, but not enough to toss the old
1979 adjustArithmeticResult (iCode * ic)
1981 if (opIsGptr (IC_RESULT (ic)) &&
1982 opIsGptr (IC_LEFT (ic)) &&
1983 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
1985 aopPut (AOP (IC_RESULT (ic)),
1986 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1990 if (opIsGptr (IC_RESULT (ic)) &&
1991 opIsGptr (IC_RIGHT (ic)) &&
1992 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
1994 aopPut (AOP (IC_RESULT (ic)),
1995 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1999 if (opIsGptr (IC_RESULT (ic)) &&
2000 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2001 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2002 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2003 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2006 sprintf (buffer, "%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2007 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2011 /*-----------------------------------------------------------------*/
2012 /* genPlus - generates code for addition */
2013 /*-----------------------------------------------------------------*/
2015 genPlus (iCode * ic)
2017 int size, offset = 0;
2021 /* special cases :- */
2023 aopOp (IC_LEFT (ic), ic, FALSE);
2024 aopOp (IC_RIGHT (ic), ic, FALSE);
2025 aopOp (IC_RESULT (ic), ic, TRUE);
2027 /* if I can do an increment instead
2028 of add then GOOD for ME */
2029 if (genPlusIncr (ic) == TRUE)
2032 size = getDataSize (IC_RESULT (ic));
2033 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2038 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), offset), offset);
2040 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2048 emitcode (l, "%s,%s", aopGet (AOP (IC_RESULT (ic)), offset),
2049 aopGet (AOP (IC_RIGHT (ic)), offset));
2058 emitcode (l, "%s,%s(-%d)", aopGet (AOP (IC_RESULT (ic)), offset),
2060 (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit));
2065 adjustArithmeticResult (ic);
2068 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2069 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2070 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2073 /*-----------------------------------------------------------------*/
2074 /* genMinusDec :- does subtraction with deccrement if possible */
2075 /*-----------------------------------------------------------------*/
2077 genMinusDec (iCode * ic)
2079 unsigned int icount;
2081 /* will try to generate an increment */
2082 /* if the right side is not a literal
2084 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2087 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2089 /* if the sizes are greater than 2 or they are not the same regs
2091 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2094 /* so we know LEFT & RESULT in the same registers and add
2096 /* for short & char types */
2097 if (AOP_SIZE (IC_RESULT (ic)) < 2)
2101 emitcode ("dec", "%s", aopGet (AOP (IC_LEFT (ic)), 0));
2104 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_LEFT (ic)), 0), icount);
2108 if (AOP_SIZE (IC_RESULT (ic)) <= 3)
2110 /* if register pair and starts with 26/30 then adiw */
2111 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0 && icount < 64 &&
2112 (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2113 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX)))
2115 emitcode ("sbiw", "%s,%d", aopGet (AOP (IC_RESULT (ic)), 0), icount);
2120 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0), icount);
2121 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1), icount);
2124 /* for 32 bit longs */
2125 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0), icount);
2126 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1), icount);
2127 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2), icount);
2128 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3), icount);
2133 /*-----------------------------------------------------------------*/
2134 /* addSign - complete with sign */
2135 /*-----------------------------------------------------------------*/
2137 addSign (operand * result, int offset, int sign)
2139 int size = (getDataSize (result) - offset);
2144 emitcode ("rlc", "a");
2145 emitcode ("subb", "a,acc");
2147 aopPut (AOP (result), "a", offset++);
2151 aopPut (AOP (result), zero, offset++);
2155 /*-----------------------------------------------------------------*/
2156 /* genMinus - generates code for subtraction */
2157 /*-----------------------------------------------------------------*/
2159 genMinus (iCode * ic)
2161 int size, offset = 0, samer;
2164 aopOp (IC_LEFT (ic), ic, FALSE);
2165 aopOp (IC_RIGHT (ic), ic, FALSE);
2166 aopOp (IC_RESULT (ic), ic, TRUE);
2168 /* if I can do an decrement instead
2169 of subtract then GOOD for ME */
2170 if (genMinusDec (ic) == TRUE)
2173 size = getDataSize (IC_RESULT (ic));
2174 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2178 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), offset), offset);
2180 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2188 emitcode (l, "%s,%s", aopGet (AOP (IC_RESULT (ic)), offset),
2189 aopGet (AOP (IC_RIGHT (ic)), offset));
2198 emitcode (l, "%s,%s(%d)", aopGet (AOP (IC_RESULT (ic)), offset),
2200 (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit));
2205 adjustArithmeticResult (ic);
2208 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2209 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2213 /*-----------------------------------------------------------------*/
2214 /* genMultOneByte : 8 bit multiplication & division */
2215 /*-----------------------------------------------------------------*/
2217 genMultOneByte (operand * left,
2221 sym_link *opetype = operandType (result);
2225 /* (if two literals, the value is computed before) */
2226 /* if one literal, literal on the right */
2227 if (AOP_TYPE (left) == AOP_LIT)
2234 size = AOP_SIZE (result);
2236 if (SPEC_USIGN (opetype))
2238 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2242 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2243 aopGet (AOP (right), 0));
2245 aopPut (AOP (result), "r0", 0);
2248 aopPut (AOP (result), "r1", 1);
2251 if (SPEC_USIGN (opetype))
2255 aopPut (AOP (result), zero, offset++);
2262 lbl = newiTempLabel (NULL);
2263 emitcode ("ldi", "r24,0");
2264 emitcode ("brcc", "L%05d", lbl->key);
2265 emitcode ("ldi", "r24,lo8(-1)");
2266 emitcode ("", "L%05d:", lbl->key);
2268 aopPut (AOP (result), "r24", offset++);
2275 /*-----------------------------------------------------------------*/
2276 /* genMult - generates code for multiplication */
2277 /*-----------------------------------------------------------------*/
2279 genMult (iCode * ic)
2281 operand *left = IC_LEFT (ic);
2282 operand *right = IC_RIGHT (ic);
2283 operand *result = IC_RESULT (ic);
2285 /* assign the amsops */
2286 aopOp (left, ic, FALSE);
2287 aopOp (right, ic, FALSE);
2288 aopOp (result, ic, TRUE);
2290 /* if both are of size == 1 */
2291 if (AOP_SIZE (left) == 1 &&
2292 AOP_SIZE (right) == 1)
2294 genMultOneByte (left, right, result);
2298 /* should have been converted to function call */
2302 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2303 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2304 freeAsmop (result, NULL, ic, TRUE);
2307 /*-----------------------------------------------------------------*/
2308 /* genDiv - generates code for division */
2309 /*-----------------------------------------------------------------*/
2313 /* should have been converted to function call */
2317 /*-----------------------------------------------------------------*/
2318 /* genMod - generates code for division */
2319 /*-----------------------------------------------------------------*/
2323 /* should have been converted to function call */
2336 /*-----------------------------------------------------------------*/
2337 /* revavrcnd - reverse a conditional for avr */
2338 /*-----------------------------------------------------------------*/
2340 revavrcnd (int type)
2358 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++)
2360 if (rar[i].type == type)
2361 return rar[i].rtype;
2362 if (rar[i].rtype == type)
2365 assert (1); /* cannot happen */
2366 return 0; /* makes the compiler happy */
2369 static char *br_name[4] =
2370 {"breq", "brne", "brlt", "brge"};
2371 static char *br_uname[4] =
2372 {"breq", "brne", "brlo", "brcc"};
2374 /*-----------------------------------------------------------------*/
2375 /* genBranch - generate the branch instruction */
2376 /*-----------------------------------------------------------------*/
2378 genBranch (iCode * ifx, int br_type, int sign)
2380 int tj = (IC_TRUE (ifx) ? 1 : 0);
2383 { /* if true jump */
2384 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2385 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2388 { /* if false jump */
2389 int rtype = revavrcnd (br_type);
2390 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2391 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2396 /*-----------------------------------------------------------------*/
2397 /* genCmp - compare & jump */
2398 /*-----------------------------------------------------------------*/
2400 genCmp (iCode * ic, iCode * ifx, int br_type)
2402 operand *left, *right, *result;
2403 sym_link *letype, *retype;
2405 int sign, size, offset = 0;
2407 left = IC_LEFT (ic);
2408 right = IC_RIGHT (ic);
2409 result = IC_RESULT (ic);
2411 letype = getSpec (operandType (left));
2412 retype = getSpec (operandType (right));
2413 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2415 /* assign the amsops */
2416 aopOp (left, ic, FALSE);
2417 aopOp (right, ic, FALSE);
2418 aopOp (result, ic, TRUE);
2419 size = AOP_SIZE (left);
2425 if (AOP_TYPE (right) == AOP_LIT)
2427 emitcode ("cpi", "%s,lo8(%d)", aopGet (AOP (left), 0),
2428 (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit));
2429 genBranch (ifx, br_type, sign);
2432 { /* right != literal */
2433 emitcode ("cp", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2434 genBranch (ifx, br_type, sign);
2442 emitcode ("cp", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2444 emitcode ("cpc", "%s,%s", aopGet (AOP (left), offset), aopGet (AOP (right), offset));
2447 genBranch (ifx, br_type, sign);
2452 emitcode ("clr", "r0");
2456 emitcode ("cp", "%s,%s", aopGet (AOP (left), 0), aopGet (AOP (right), 0));
2458 emitcode ("cpc", "%s,%s", aopGet (AOP (left), offset), aopGet (AOP (right), offset));
2461 lbl = newiTempLabel (NULL);
2462 br_type = revavrcnd (br_type);
2464 emitcode (br_uname[br_type], "L%05d", lbl->key);
2466 emitcode (br_name[br_type], "L%05d", lbl->key);
2467 emitcode ("inc", "r0");
2468 emitcode ("", "L%05d:", lbl->key);
2469 aopPut (AOP (result), "r0", 0);
2470 size = AOP_SIZE (result) - 1;
2473 aopPut (AOP (result), zero, offset++);
2476 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2477 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2478 freeAsmop (result, NULL, ic, TRUE);
2481 /*-----------------------------------------------------------------*/
2482 /* genCmpGt :- greater than comparison */
2483 /*-----------------------------------------------------------------*/
2485 genCmpGt (iCode * ic, iCode * ifx)
2487 /* should have transformed by the parser */
2491 /*-----------------------------------------------------------------*/
2492 /* genCmpLt - less than comparisons */
2493 /*-----------------------------------------------------------------*/
2495 genCmpLt (iCode * ic, iCode * ifx)
2497 genCmp (ic, ifx, AVR_LT);
2500 /*-----------------------------------------------------------------*/
2501 /* genCmpEq - generates code for equal to */
2502 /*-----------------------------------------------------------------*/
2504 genCmpEq (iCode * ic, iCode * ifx)
2506 genCmp (ic, ifx, AVR_EQ);
2509 /*-----------------------------------------------------------------*/
2510 /* genCmpNe - generates code for not equal to */
2511 /*-----------------------------------------------------------------*/
2513 genCmpNe (iCode * ic, iCode * ifx)
2515 genCmp (ic, ifx, AVR_NE);
2518 /*-----------------------------------------------------------------*/
2519 /* genCmpGe - generates code for greater than equal to */
2520 /*-----------------------------------------------------------------*/
2522 genCmpGe (iCode * ic, iCode * ifx)
2524 genCmp (ic, ifx, AVR_GE);
2527 /*-----------------------------------------------------------------*/
2528 /* genCmpLe - generates code for less than equal to */
2529 /*-----------------------------------------------------------------*/
2531 genCmpLe (iCode * ic, iCode * ifx)
2533 operand *left = IC_LEFT (ic);
2534 operand *right = IC_RIGHT (ic);
2536 IC_RIGHT (ic) = left;
2537 IC_LEFT (ic) = right;
2538 genCmp (ic, ifx, AVR_GE);
2541 /*-----------------------------------------------------------------*/
2542 /* ifxForOp - returns the icode containing the ifx for operand */
2543 /*-----------------------------------------------------------------*/
2545 ifxForOp (operand * op, iCode * ic)
2547 /* if true symbol then needs to be assigned */
2548 if (IS_TRUE_SYMOP (op))
2551 /* if this has register type condition and
2552 the next instruction is ifx with the same operand
2553 and live to of the operand is upto the ifx only then */
2555 ic->next->op == IFX &&
2556 IC_COND (ic->next)->key == op->key &&
2557 OP_SYMBOL (op)->liveTo <= ic->next->seq)
2562 /*-----------------------------------------------------------------*/
2563 /* genAndOp - for && operation */
2564 /*-----------------------------------------------------------------*/
2566 genAndOp (iCode * ic)
2568 operand *left, *right, *result;
2572 /* note here that && operations that are in an
2573 if statement are taken away by backPatchLabels
2574 only those used in arthmetic operations remain */
2575 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2576 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2577 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2579 tlbl = newiTempLabel (NULL);
2580 toBoolean (left, "r0", TRUE);
2581 toBoolean (right, "r1", TRUE);
2582 emitcode ("and", "r0,r1");
2583 emitcode ("ldi", "r24,1");
2584 emitcode ("breq", "L%05d", tlbl->key);
2585 emitcode ("dec", "r24");
2586 emitcode ("", "L%05d:", tlbl->key);
2587 aopPut (AOP (result), "r24", 0);
2588 size = AOP_SIZE (result) - 1;
2591 aopPut (AOP (result), zero, offset++);
2593 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2594 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2595 freeAsmop (result, NULL, ic, TRUE);
2599 /*-----------------------------------------------------------------*/
2600 /* genOrOp - for || operation */
2601 /*-----------------------------------------------------------------*/
2603 genOrOp (iCode * ic)
2605 operand *left, *right, *result;
2609 /* note here that || operations that are in an
2610 if statement are taken away by backPatchLabels
2611 only those used in arthmetic operations remain */
2612 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2613 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2614 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2616 tlbl = newiTempLabel (NULL);
2617 toBoolean (left, "r0", TRUE);
2618 toBoolean (right, "r0", FALSE);
2619 emitcode ("ldi", "r24,1");
2620 emitcode ("breq", "L%05d", tlbl->key);
2621 emitcode ("dec", "r24");
2622 emitcode ("", "L%05d:", tlbl->key);
2623 aopPut (AOP (result), "r24", 0);
2624 size = AOP_SIZE (result) - 1;
2627 aopPut (AOP (result), zero, offset++);
2629 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2630 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2631 freeAsmop (result, NULL, ic, TRUE);
2634 /*-----------------------------------------------------------------*/
2635 /* isLiteralBit - test if lit == 2^n */
2636 /*-----------------------------------------------------------------*/
2638 isLiteralBit (unsigned long lit)
2640 unsigned long pw[32] =
2641 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
2642 0x100L, 0x200L, 0x400L, 0x800L,
2643 0x1000L, 0x2000L, 0x4000L, 0x8000L,
2644 0x10000L, 0x20000L, 0x40000L, 0x80000L,
2645 0x100000L, 0x200000L, 0x400000L, 0x800000L,
2646 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
2647 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
2650 for (idx = 0; idx < 32; idx++)
2658 AVR_AND = 0, AVR_OR, AVR_XOR
2660 static char *bopnames_lit[] =
2662 static char *bopnames[] =
2663 {"and", "or", "eor"};
2664 /*-----------------------------------------------------------------*/
2665 /* genBitWise - generate bitwise operations */
2666 /*-----------------------------------------------------------------*/
2668 genBitWise (iCode * ic, iCode * ifx, int bitop)
2670 operand *left, *right, *result;
2671 int size, offset = 0;
2676 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2677 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2678 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2680 size = AOP_SIZE (left);
2683 { /* used only for jumps */
2684 if (AOP_TYPE (right) == AOP_LIT &&
2685 (bitop == AVR_AND || bitop == AVR_OR))
2687 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
2688 int p2 = powof2 (lit);
2689 if (bitop == AVR_AND && p2)
2690 { /* right side is a power of 2 */
2691 l = aopGet (AOP (left), p2 / 8);
2694 emitcode ("sbrc", "%s,%d", l, (p2 % 8));
2695 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2699 emitcode ("sbrs", "%s,%d", l, (p2 % 8));
2700 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2704 { /* right not power of two */
2705 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2710 emitcode (bopnames_lit[bitop], "%s,lo8(%d)",
2711 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2715 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2716 emitcode (bopnames_lit[bitop], "r0,lo8(%d)", lit);
2718 lbl = newiTempLabel (NULL);
2721 emitcode ("breq", "L%05d", lbl->key);
2722 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2726 emitcode ("brne", "L%05d", lbl->key);
2727 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2729 emitcode ("", "L%05d:", lbl->key);
2733 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2734 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2735 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2736 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2737 emitcode ("sbiw", "r24,0");
2738 lbl = newiTempLabel (NULL);
2741 emitcode ("breq", "L%05d", lbl->key);
2742 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2746 emitcode ("brne", "L%05d", lbl->key);
2747 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2749 emitcode ("", "L%05d:", lbl->key);
2753 lbl = newiTempLabel (NULL);
2754 lbl1 = newiTempLabel (NULL);
2759 emitcode (bopnames_lit[bitop], "%s,lo8(%d)",
2760 aopGet (AOP (IC_LEFT (ic)), offset), lit);
2764 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2765 emitcode ("andi", "r0,lo8(%d)", lit);
2767 emitcode ("brne", "L%05d", lbl->key);
2772 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2774 emitcode ("rjmp", "L%05d", lbl1->key);
2775 emitcode ("", "L%05d:", lbl->key);
2778 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2779 emitcode ("", "L%05d:", lbl1->key);
2785 { /* right is not a literal */
2786 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2787 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2792 emitcode (bopnames[bitop], "%s,%s",
2793 aopGet (AOP (IC_LEFT (ic)), 0),
2794 aopGet (AOP (IC_RIGHT (ic)), 0));
2798 emitcode (bopnames[bitop], "%s,%s",
2799 aopGet (AOP (IC_RIGHT (ic)), 0),
2800 aopGet (AOP (IC_LEFT (ic)), 0));
2804 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2805 emitcode (bopnames[bitop], "r0,%s", aopGet (AOP (IC_RIGHT (ic)), 0));
2807 lbl = newiTempLabel (NULL);
2810 emitcode ("breq", "L%05d", lbl->key);
2811 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2815 emitcode ("brne", "L%05d", lbl->key);
2816 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2818 emitcode ("", "L%05d:", lbl->key);
2822 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2823 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2824 emitcode (bopnames[bitop], "r24,%s", aopGet (AOP (IC_RIGHT (ic)), 0));
2825 emitcode (bopnames[bitop], "r25,%s", aopGet (AOP (IC_RIGHT (ic)), 1));
2826 emitcode ("sbiw", "r24,0");
2827 lbl = newiTempLabel (NULL);
2830 emitcode ("breq", "L%05d", lbl->key);
2831 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2835 emitcode ("brne", "L%05d", lbl->key);
2836 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2838 emitcode ("", "L%05d:", lbl->key);
2842 lbl = newiTempLabel (NULL);
2843 lbl1 = newiTempLabel (NULL);
2848 emitcode (bopnames[bitop], "%s,%s",
2849 aopGet (AOP (IC_LEFT (ic)), offset),
2850 aopGet (AOP (IC_RIGHT (ic)), offset));
2854 emitcode (bopnames[bitop], "%s,%s",
2855 aopGet (AOP (IC_RIGHT (ic)), offset),
2856 aopGet (AOP (IC_LEFT (ic)), offset));
2860 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2861 emitcode (bopnames[bitop], "r0,%s", aopGet (AOP (IC_RIGHT (ic)), offset));
2863 emitcode ("brne", "L%05d", lbl->key);
2868 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2870 emitcode ("rjmp", "L%05d", lbl1->key);
2871 emitcode ("", "L%05d:", lbl->key);
2874 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2875 emitcode ("", "L%05d:", lbl1->key);
2882 /* result needs to go a register */
2883 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2884 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2887 if (AOP_TYPE (right) == AOP_LIT)
2889 unsigned int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
2890 if (((lit >> (8 * offset)) & 0xff) == 0)
2892 if (bitop == AVR_AND)
2894 aopPut (AOP (result), zero, offset++);
2897 else if (bitop == AVR_OR)
2900 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
2908 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && (bitop == AVR_AND || bitop == AVR_OR))
2910 emitcode (bopnames_lit[bitop], "%s,%s(%d)", aopGet (AOP (IC_LEFT (ic)), offset),
2911 larray[offset], (int) floatFromVal (AOP (right)->aopu.aop_lit));
2915 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), offset),
2916 aopGet (AOP (IC_RIGHT (ic)), offset));
2921 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_RIGHT (ic)), offset),
2922 aopGet (AOP (IC_LEFT (ic)), offset));
2926 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), offset), offset);
2927 emitcode (bopnames[bitop], aopGet (AOP (IC_RESULT (ic)), offset),
2928 aopGet (AOP (IC_RIGHT (ic)), offset));
2933 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2934 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2935 freeAsmop (result, NULL, ic, TRUE);
2938 /*-----------------------------------------------------------------*/
2939 /* genAnd - code for and */
2940 /*-----------------------------------------------------------------*/
2942 genAnd (iCode * ic, iCode * ifx)
2944 genBitWise (ic, ifx, AVR_AND);
2947 /*-----------------------------------------------------------------*/
2948 /* genOr - code for or */
2949 /*-----------------------------------------------------------------*/
2951 genOr (iCode * ic, iCode * ifx)
2953 genBitWise (ic, ifx, AVR_OR);
2956 /*-----------------------------------------------------------------*/
2957 /* genXor - code for xclusive or */
2958 /*-----------------------------------------------------------------*/
2960 genXor (iCode * ic, iCode * ifx)
2962 genBitWise (ic, ifx, AVR_XOR);
2965 /*-----------------------------------------------------------------*/
2966 /* genInline - write the inline code out */
2967 /*-----------------------------------------------------------------*/
2969 genInline (iCode * ic)
2971 char buffer[MAX_INLINEASM];
2975 _G.inLine += (!options.asmpeep);
2976 strcpy (buffer, IC_INLINE (ic));
2978 /* emit each line as a code */
3003 /* emitcode("",buffer); */
3004 _G.inLine -= (!options.asmpeep);
3007 /*-----------------------------------------------------------------*/
3008 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
3009 /*-----------------------------------------------------------------*/
3011 genRotC (iCode * ic, int lr)
3013 operand *left, *result;
3014 int size, offset = 0;
3016 /* rotate right with carry */
3017 left = IC_LEFT (ic);
3018 result = IC_RESULT (ic);
3019 aopOp (left, ic, FALSE);
3020 aopOp (result, ic, FALSE);
3022 /* move it to the result */
3023 size = AOP_SIZE (result);
3024 if (!sameRegs (AOP (left), AOP (result)))
3029 aopPut (AOP (result),
3030 aopGet (AOP (left), offset),
3034 size = AOP_SIZE (result);
3042 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3044 emitcode ("sec", "");
3048 emitcode ((lr ? "ror" : "rol"), "%s", aopGet (AOP (result), offset));
3054 freeAsmop (left, NULL, ic, TRUE);
3055 freeAsmop (result, NULL, ic, TRUE);
3058 /*-----------------------------------------------------------------*/
3059 /* genRRC - rotate right with carry */
3060 /*-----------------------------------------------------------------*/
3067 /*-----------------------------------------------------------------*/
3068 /* genRLC - generate code for rotate left with carry */
3069 /*-----------------------------------------------------------------*/
3076 /*-----------------------------------------------------------------*/
3077 /* genGetHbit - generates code get highest order bit */
3078 /*-----------------------------------------------------------------*/
3080 genGetHbit (iCode * ic)
3082 operand *left, *result;
3085 left = IC_LEFT (ic);
3086 result = IC_RESULT (ic);
3087 aopOp (left, ic, FALSE);
3088 aopOp (result, ic, FALSE);
3090 size = AOP_SIZE (result);
3091 if (!sameRegs (AOP (left), AOP (result)))
3093 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3094 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3095 emitcode ("subi", "%s,lo8(-1)", aopGet (AOP (result), size - 1));
3099 emitcode ("clr", "r0");
3100 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3101 emitcode ("subi", "r0,lo8(-1)");
3102 aopPut (AOP (result), "r0", 0);
3108 emitcode ("clr", aopGet (AOP (result), offset++));
3110 freeAsmop (left, NULL, ic, TRUE);
3111 freeAsmop (result, NULL, ic, TRUE);
3114 /*-----------------------------------------------------------------*/
3115 /* genShiftLeftLit - shift left by a known amount */
3116 /*-----------------------------------------------------------------*/
3118 genShiftLeftLit (iCode * ic)
3120 operand *left, *right, *result;
3121 int size, shCount, offset = 0;
3124 right = IC_RIGHT (ic);
3125 left = IC_LEFT (ic);
3126 result = IC_RESULT (ic);
3128 aopOp (left, ic, FALSE);
3129 aopOp (result, ic, FALSE);
3130 size = AOP_SIZE (result);
3131 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3133 if (shCount > (size * 8 - 1))
3136 aopPut (AOP (result), zero, offset++);
3142 if (!sameRegs (AOP (left), AOP (result)))
3143 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3146 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3147 emitcode ("andi", "%s,0xf0");
3152 emitcode ("add", "%s,%s", aopGet (AOP (result), 0), aopGet (AOP (result), 0));
3156 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3161 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3162 aopPut (AOP (result), zero, 0);
3163 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3164 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3170 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3171 aopPut (AOP (result), zero, 0);
3178 if (!sameRegs (AOP (left), AOP (result)))
3180 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3181 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3183 emitcode ("mov", "r1,%s", aopGet (AOP (result), 0));
3184 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3185 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3186 emitcode ("andi", "r1,0x0f");
3187 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3188 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3189 emitcode ("or", "%s,r1", aopGet (AOP (result), 1));
3192 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3193 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3196 if (!lByteZ && !sameRegs (AOP (result), AOP (left)) && shCount)
3201 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3209 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3213 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3214 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3219 assert ("shifting generic pointer ?\n");
3222 /* 32 bits we do only byte boundaries */
3225 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3226 aopPut (AOP (result), zero, 2);
3227 aopPut (AOP (result), zero, 1);
3228 aopPut (AOP (result), zero, 0);
3234 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3235 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3236 aopPut (AOP (result), zero, 1);
3237 aopPut (AOP (result), zero, 0);
3243 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3244 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3245 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3246 aopPut (AOP (result), zero, 0);
3250 if (!lByteZ && !sameRegs (AOP (left), AOP (right)))
3255 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3259 size = AOP_SIZE (result);
3268 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3269 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3270 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3271 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3277 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3278 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3279 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3285 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3286 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3292 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3300 freeAsmop (left, NULL, ic, TRUE);
3301 freeAsmop (right, NULL, ic, TRUE);
3302 freeAsmop (result, NULL, ic, TRUE);
3305 /*-----------------------------------------------------------------*/
3306 /* genLeftShift - generates code for left shifting */
3307 /*-----------------------------------------------------------------*/
3309 genLeftShift (iCode * ic)
3311 operand *left, *right, *result;
3315 right = IC_RIGHT (ic);
3316 left = IC_LEFT (ic);
3317 result = IC_RESULT (ic);
3319 aopOp (right, ic, FALSE);
3321 if (AOP_TYPE (right) == AOP_LIT)
3323 genShiftLeftLit (ic);
3328 aopOp (left, ic, FALSE);
3329 aopOp (result, ic, FALSE);
3330 size = AOP_SIZE (result);
3332 if (AOP_SIZE (right) > 1)
3334 if (isRegPair (AOP (right)))
3336 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3340 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3341 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3346 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3348 if (!sameRegs (AOP (left), AOP (result)))
3352 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3355 size = AOP_SIZE (result);
3357 tlbl = newiTempLabel (NULL);
3358 emitcode ("", "L%05d:", tlbl->key);
3363 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3365 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3368 if (AOP_SIZE (right) > 1)
3369 emitcode ("sbiw", "r24,1");
3371 emitcode ("dec", "r24");
3372 emitcode ("brne", "L%05d", tlbl->key);
3374 freeAsmop (left, NULL, ic, TRUE);
3375 freeAsmop (right, NULL, ic, TRUE);
3376 freeAsmop (result, NULL, ic, TRUE);
3379 /*-----------------------------------------------------------------*/
3380 /* genShiftRightLit - generate for right shift with known count */
3381 /*-----------------------------------------------------------------*/
3383 genShiftRightLit (iCode * ic)
3385 operand *left = IC_LEFT (ic)
3386 ,*right = IC_RIGHT (ic)
3387 ,*result = IC_RESULT (ic);
3388 int size, shCount, offset = 0;
3390 sym_link *letype = getSpec (operandType (left));
3391 int sign = !SPEC_USIGN (letype);
3393 right = IC_RIGHT (ic);
3394 left = IC_LEFT (ic);
3395 result = IC_RESULT (ic);
3397 aopOp (left, ic, FALSE);
3398 aopOp (result, ic, FALSE);
3399 size = AOP_SIZE (result);
3400 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3402 /* if signed then give up and use a loop to shift */
3406 if (!sameRegs (AOP (left), AOP (result)))
3410 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3413 size = size = AOP_SIZE (result);
3416 /* be as economical as possible */
3423 size = AOP_SIZE (result);
3426 if (offset == (size - 1))
3427 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3429 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3436 emitcode ("ldi", "r24,lo8(%d)", shCount);
3437 tlbl = newiTempLabel (NULL);
3438 emitcode ("", "L%05d:", tlbl->key);
3442 if (offset == (size - 1))
3443 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3445 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3448 emitcode ("dec", "r24");
3449 emitcode ("brne", "L%05d", tlbl->key);
3453 if (shCount > (size * 8 - 1))
3456 aopPut (AOP (result), zero, offset++);
3459 /* for unsigned we can much more efficient */
3463 if (!sameRegs (AOP (left), AOP (result)))
3464 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3467 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3468 emitcode ("andi", "%s,0x0f");
3472 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3477 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3478 aopPut (AOP (result), zero, 1);
3479 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3480 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3486 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3487 aopPut (AOP (result), zero, 1);
3494 if (!sameRegs (AOP (left), AOP (result)))
3496 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3497 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3499 emitcode ("mov", "r1,%s", aopGet (AOP (result), 1));
3500 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3501 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3502 emitcode ("andi", "r1,0xf0");
3503 emitcode ("or", "%s,r1", aopGet (AOP (result), 0));
3504 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3505 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3508 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3509 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3513 if (!hByteZ && !sameRegs (AOP (result), AOP (left)) && shCount)
3518 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3526 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3530 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3531 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3537 assert ("shifting generic pointer ?\n");
3540 /* 32 bits we do only byte boundaries */
3543 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3544 aopPut (AOP (result), zero, 1);
3545 aopPut (AOP (result), zero, 2);
3546 aopPut (AOP (result), zero, 3);
3552 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3553 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3554 aopPut (AOP (result), zero, 2);
3555 aopPut (AOP (result), zero, 3);
3561 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3562 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3563 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3564 aopPut (AOP (result), zero, 3);
3568 if (!hByteZ && !sameRegs (AOP (left), AOP (right)))
3573 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3577 size = AOP_SIZE (result);
3586 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3587 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3588 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3589 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3595 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3596 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3597 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3603 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3604 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3610 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3617 freeAsmop (left, NULL, ic, TRUE);
3618 freeAsmop (right, NULL, ic, TRUE);
3619 freeAsmop (result, NULL, ic, TRUE);
3622 /*-----------------------------------------------------------------*/
3623 /* genRightShift - generate code for right shifting */
3624 /*-----------------------------------------------------------------*/
3626 genRightShift (iCode * ic)
3628 operand *right, *left, *result;
3631 int sign = 0, first = 1;
3634 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3635 if (AOP_TYPE (right) == AOP_LIT)
3637 genShiftRightLit (ic);
3641 if (AOP_SIZE (right) > 1)
3643 if (isRegPair (AOP (right)))
3645 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3649 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3650 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3655 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3657 aopOp (left = IC_LEFT (ic), ic, FALSE);
3658 aopOp (result = IC_RESULT (ic), ic, FALSE);
3659 size = AOP_SIZE (result);
3660 tlbl = newiTempLabel (NULL);
3661 emitcode ("", "L%05d:", tlbl->key);
3663 letype = getSpec (operandType (left));
3664 sign = !SPEC_USIGN (letype);
3665 if (!sameRegs (AOP (left), AOP (result)))
3669 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3672 size = AOP_SIZE (result);
3674 size = AOP_SIZE (result);
3680 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3682 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3686 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3689 if (AOP_SIZE (right) > 1)
3690 emitcode ("sbiw", "r24,1");
3692 emitcode ("dec", "r24");
3693 emitcode ("brne", "L%05d", tlbl->key);
3695 freeAsmop (left, NULL, ic, TRUE);
3696 freeAsmop (result, NULL, ic, TRUE);
3699 /*-----------------------------------------------------------------*/
3700 /* R0Rsh - shift right r0 by known count */
3701 /*-----------------------------------------------------------------*/
3705 shCount &= 0x0007; // shCount : 0..7
3712 emitcode ("lsr", "r0");
3715 emitcode ("lsr", "r0");
3716 emitcode ("lsr", "r0");
3719 emitcode ("swap", "r0");
3720 emitcode ("lsl", "r0");
3723 emitcode ("swap", "r0");
3726 emitcode ("swap", "r0");
3727 emitcode ("lsr", "r0");
3730 emitcode ("swap", "r0");
3731 emitcode ("lsr", "r0");
3732 emitcode ("lsr", "r0");
3735 emitcode ("swap", "r0");
3736 emitcode ("lsr", "r0");
3737 emitcode ("lsr", "r0");
3738 emitcode ("lsr", "r0");
3743 /*-----------------------------------------------------------------*/
3744 /* genUnpackBits - generates code for unpacking bits */
3745 /*-----------------------------------------------------------------*/
3747 genUnpackBits (operand * result, char *rname, int ptype)
3754 etype = getSpec (operandType (result));
3756 /* read the first byte */
3764 emitcode ("ld", "r0,%s+", rname);
3768 emitcode ("ldm", "r0,%s+", rname);
3772 emitcode ("call", "__gptrget_pi");
3776 /* if we have bitdisplacement then it fits */
3777 /* into this byte completely or if length is */
3778 /* less than a byte */
3779 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8))
3782 /* shift right r0 */
3784 emitcode ("andi", "r0,0x%02x",
3785 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3787 aopPut (AOP (result), "r0", offset);
3791 /* bit field did not fit in a byte */
3792 rlen = SPEC_BLEN (etype) - 8;
3793 aopPut (AOP (result), "a", offset++);
3804 emitcode ("ld", "r0,%s+", rname);
3808 emitcode ("ldm", "r0,%s+", rname);
3812 emitcode ("lcall", "__gptrget_pi");
3817 /* if we are done */
3821 aopPut (AOP (result), "r0", offset++);
3827 emitcode ("andi", "r0,#0x%02x", ((unsigned char) -1) >> (-rlen));
3828 aopPut (AOP (result), "r0", offset);
3835 /*-----------------------------------------------------------------*/
3836 /* genDataPointerGet - generates code when ptr offset is known */
3837 /*-----------------------------------------------------------------*/
3839 genDataPointerGet (operand * left,
3845 int size, offset = 0;
3846 aopOp (result, ic, TRUE);
3848 /* get the string representation of the name */
3849 l = aopGet (AOP (left), 0);
3850 size = AOP_SIZE (result);
3854 sprintf (buffer, "(%s + %d)", l + 1, offset);
3856 sprintf (buffer, "%s", l + 1);
3857 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++), buffer);
3860 freeAsmop (left, NULL, ic, TRUE);
3861 freeAsmop (result, NULL, ic, TRUE);
3864 /*-----------------------------------------------------------------*/
3865 /* genNearPointerGet - emitcode for near pointer fetch */
3866 /*-----------------------------------------------------------------*/
3868 genNearPointerGet (operand * left,
3875 sym_link *rtype, *retype;
3876 sym_link *ltype = operandType (left);
3879 rtype = operandType (result);
3880 retype = getSpec (rtype);
3882 aopOp (left, ic, FALSE);
3884 /* if left is rematerialisable and
3885 result is not bit variable type and
3886 the left is pointer to data space i.e
3887 lower 128 bytes of space */
3888 if (AOP_TYPE (left) == AOP_IMMD &&
3889 !IS_BITVAR (retype) &&
3890 DCL_TYPE (ltype) == POINTER)
3892 genDataPointerGet (left, result, ic);
3896 /* if the value is already in a pointer register
3897 then don't need anything more */
3898 if (!AOP_INPREG (AOP (left)))
3900 /* otherwise get a free pointer register */
3902 preg = getFreePtr (ic, &aop, FALSE, 0);
3903 emitcode ("mov", "%s,%s",
3905 aopGet (AOP (left), 0));
3909 rname = aopGet (AOP (left), 0);
3911 freeAsmop (left, NULL, ic, TRUE);
3912 aopOp (result, ic, FALSE);
3914 /* if bitfield then unpack the bits */
3915 if (IS_BITVAR (retype))
3916 genUnpackBits (result, rname, POINTER);
3919 /* we have can just get the values */
3920 int size = AOP_SIZE (result);
3925 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
3928 emitcode ("mov", "a,@%s", rname);
3929 aopPut (AOP (result), "a", offset);
3933 sprintf (buffer, "@%s", rname);
3934 aopPut (AOP (result), buffer, offset);
3938 emitcode ("inc", "%s", rname);
3942 /* now some housekeeping stuff */
3945 /* we had to allocate for this iCode */
3946 freeAsmop (NULL, aop, ic, TRUE);
3950 /* we did not allocate which means left
3951 already in a pointer register, then
3952 if size > 0 && this could be used again
3953 we have to point it back to where it
3955 if (AOP_SIZE (result) > 1 &&
3956 !OP_SYMBOL (left)->remat &&
3957 (OP_SYMBOL (left)->liveTo > ic->seq ||
3960 int size = AOP_SIZE (result) - 1;
3962 emitcode ("dec", "%s", rname);
3967 freeAsmop (result, NULL, ic, TRUE);
3971 /*-----------------------------------------------------------------*/
3972 /* genPagedPointerGet - emitcode for paged pointer fetch */
3973 /*-----------------------------------------------------------------*/
3975 genPagedPointerGet (operand * left,
3982 sym_link *rtype, *retype;
3984 rtype = operandType (result);
3985 retype = getSpec (rtype);
3987 aopOp (left, ic, FALSE);
3989 /* if the value is already in a pointer register
3990 then don't need anything more */
3991 if (!AOP_INPREG (AOP (left)))
3993 /* otherwise get a free pointer register */
3995 preg = getFreePtr (ic, &aop, FALSE, 0);
3996 emitcode ("mov", "%s,%s",
3998 aopGet (AOP (left), 0));
4002 rname = aopGet (AOP (left), 0);
4004 freeAsmop (left, NULL, ic, TRUE);
4005 aopOp (result, ic, FALSE);
4007 /* if bitfield then unpack the bits */
4008 if (IS_BITVAR (retype))
4009 genUnpackBits (result, rname, PPOINTER);
4012 /* we have can just get the values */
4013 int size = AOP_SIZE (result);
4019 emitcode ("movx", "a,@%s", rname);
4020 aopPut (AOP (result), "a", offset);
4025 emitcode ("inc", "%s", rname);
4029 /* now some housekeeping stuff */
4032 /* we had to allocate for this iCode */
4033 freeAsmop (NULL, aop, ic, TRUE);
4037 /* we did not allocate which means left
4038 already in a pointer register, then
4039 if size > 0 && this could be used again
4040 we have to point it back to where it
4042 if (AOP_SIZE (result) > 1 &&
4043 !OP_SYMBOL (left)->remat &&
4044 (OP_SYMBOL (left)->liveTo > ic->seq ||
4047 int size = AOP_SIZE (result) - 1;
4049 emitcode ("dec", "%s", rname);
4054 freeAsmop (result, NULL, ic, TRUE);
4059 /*-----------------------------------------------------------------*/
4060 /* genFarPointerGet - gget value from far space */
4061 /*-----------------------------------------------------------------*/
4063 genFarPointerGet (operand * left,
4064 operand * result, iCode * ic)
4067 sym_link *retype = getSpec (operandType (result));
4069 aopOp (left, ic, FALSE);
4071 /* if the operand is already in dptr
4072 then we do nothing else we move the value to dptr */
4073 if (AOP_TYPE (left) != AOP_STR)
4075 /* if this is remateriazable */
4076 if (AOP_TYPE (left) == AOP_IMMD)
4077 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4079 { /* we need to get it byte by byte */
4080 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4081 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4082 if (options.model == MODEL_FLAT24)
4084 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4088 /* so dptr know contains the address */
4089 freeAsmop (left, NULL, ic, TRUE);
4090 aopOp (result, ic, FALSE);
4092 /* if bit then unpack */
4093 if (IS_BITVAR (retype))
4094 genUnpackBits (result, "dptr", FPOINTER);
4097 size = AOP_SIZE (result);
4102 emitcode ("movx", "a,@dptr");
4103 aopPut (AOP (result), "a", offset++);
4105 emitcode ("inc", "dptr");
4109 freeAsmop (result, NULL, ic, TRUE);
4112 /*-----------------------------------------------------------------*/
4113 /* emitcodePointerGet - gget value from code space */
4114 /*-----------------------------------------------------------------*/
4116 emitcodePointerGet (operand * left,
4117 operand * result, iCode * ic)
4120 sym_link *retype = getSpec (operandType (result));
4122 aopOp (left, ic, FALSE);
4124 /* if the operand is already in dptr
4125 then we do nothing else we move the value to dptr */
4126 if (AOP_TYPE (left) != AOP_STR)
4128 /* if this is remateriazable */
4129 if (AOP_TYPE (left) == AOP_IMMD)
4130 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4132 { /* we need to get it byte by byte */
4133 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4134 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4135 if (options.model == MODEL_FLAT24)
4137 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4141 /* so dptr know contains the address */
4142 freeAsmop (left, NULL, ic, TRUE);
4143 aopOp (result, ic, FALSE);
4145 /* if bit then unpack */
4146 if (IS_BITVAR (retype))
4147 genUnpackBits (result, "dptr", CPOINTER);
4150 size = AOP_SIZE (result);
4155 emitcode ("clr", "a");
4156 emitcode ("movc", "a,@a+dptr");
4157 aopPut (AOP (result), "a", offset++);
4159 emitcode ("inc", "dptr");
4163 freeAsmop (result, NULL, ic, TRUE);
4166 /*-----------------------------------------------------------------*/
4167 /* genGenPointerGet - gget value from generic pointer space */
4168 /*-----------------------------------------------------------------*/
4170 genGenPointerGet (operand * left,
4171 operand * result, iCode * ic)
4174 sym_link *retype = getSpec (operandType (result));
4176 aopOp (left, ic, FALSE);
4178 /* if the operand is already in dptr
4179 then we do nothing else we move the value to dptr */
4180 if (AOP_TYPE (left) != AOP_STR)
4182 /* if this is remateriazable */
4183 if (AOP_TYPE (left) == AOP_IMMD)
4185 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4186 emitcode ("mov", "b,#%d", pointerCode (retype));
4189 { /* we need to get it byte by byte */
4190 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4191 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4192 if (options.model == MODEL_FLAT24)
4194 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4195 emitcode ("mov", "b,%s", aopGet (AOP (left), 3));
4199 emitcode ("mov", "b,%s", aopGet (AOP (left), 2));
4203 /* so dptr know contains the address */
4204 freeAsmop (left, NULL, ic, TRUE);
4205 aopOp (result, ic, FALSE);
4207 /* if bit then unpack */
4208 if (IS_BITVAR (retype))
4209 genUnpackBits (result, "dptr", GPOINTER);
4212 size = AOP_SIZE (result);
4217 emitcode ("lcall", "__gptrget");
4218 aopPut (AOP (result), "a", offset++);
4220 emitcode ("inc", "dptr");
4224 freeAsmop (result, NULL, ic, TRUE);
4227 /*-----------------------------------------------------------------*/
4228 /* genPointerGet - generate code for pointer get */
4229 /*-----------------------------------------------------------------*/
4231 genPointerGet (iCode * ic)
4233 operand *left, *result;
4234 sym_link *type, *etype;
4237 left = IC_LEFT (ic);
4238 result = IC_RESULT (ic);
4240 /* depending on the type of pointer we need to
4241 move it to the correct pointer register */
4242 type = operandType (left);
4243 etype = getSpec (type);
4244 /* if left is of type of pointer then it is simple */
4245 if (IS_PTR (type) && !IS_FUNC (type->next))
4246 p_type = DCL_TYPE (type);
4249 /* we have to go by the storage class */
4250 p_type = PTR_TYPE (SPEC_OCLS (etype));
4252 /* if (SPEC_OCLS(etype)->codesp ) { */
4253 /* p_type = CPOINTER ; */
4256 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4257 /* p_type = FPOINTER ; */
4259 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4260 /* p_type = PPOINTER; */
4262 /* if (SPEC_OCLS(etype) == idata ) */
4263 /* p_type = IPOINTER; */
4265 /* p_type = POINTER ; */
4268 /* now that we have the pointer type we assign
4269 the pointer values */
4275 genNearPointerGet (left, result, ic);
4279 genPagedPointerGet (left, result, ic);
4283 genFarPointerGet (left, result, ic);
4287 emitcodePointerGet (left, result, ic);
4291 genGenPointerGet (left, result, ic);
4297 /*-----------------------------------------------------------------*/
4298 /* genPackBits - generates code for packed bit storage */
4299 /*-----------------------------------------------------------------*/
4301 genPackBits (sym_link * etype,
4303 char *rname, int p_type)
4311 blen = SPEC_BLEN (etype);
4312 bstr = SPEC_BSTR (etype);
4314 l = aopGet (AOP (right), offset++);
4317 /* if the bit lenth is less than or */
4318 /* it exactly fits a byte then */
4319 if (SPEC_BLEN (etype) <= 8)
4321 shCount = SPEC_BSTR (etype);
4323 /* shift left acc */
4326 if (SPEC_BLEN (etype) < 8)
4327 { /* if smaller than a byte */
4333 emitcode ("mov", "b,a");
4334 emitcode ("mov", "a,@%s", rname);
4338 emitcode ("mov", "b,a");
4339 emitcode ("movx", "a,@dptr");
4343 emitcode ("push", "b");
4344 emitcode ("push", "acc");
4345 emitcode ("lcall", "__gptrget");
4346 emitcode ("pop", "b");
4350 emitcode ("anl", "a,#0x%02x", (unsigned char)
4351 ((unsigned char) (0xFF << (blen + bstr)) |
4352 (unsigned char) (0xFF >> (8 - bstr))));
4353 emitcode ("orl", "a,b");
4354 if (p_type == GPOINTER)
4355 emitcode ("pop", "b");
4362 emitcode ("mov", "@%s,a", rname);
4366 emitcode ("movx", "@dptr,a");
4370 emitcode ("lcall", "__gptrput");
4375 if (SPEC_BLEN (etype) <= 8)
4378 emitcode ("inc", "%s", rname);
4379 rLen = SPEC_BLEN (etype);
4381 /* now generate for lengths greater than one byte */
4385 l = aopGet (AOP (right), offset++);
4397 emitcode ("mov", "@%s,a", rname);
4400 emitcode ("mov", "@%s,%s", rname, l);
4405 emitcode ("movx", "@dptr,a");
4410 emitcode ("lcall", "__gptrput");
4413 emitcode ("inc", "%s", rname);
4418 /* last last was not complete */
4421 /* save the byte & read byte */
4425 emitcode ("mov", "b,a");
4426 emitcode ("mov", "a,@%s", rname);
4430 emitcode ("mov", "b,a");
4431 emitcode ("movx", "a,@dptr");
4435 emitcode ("push", "b");
4436 emitcode ("push", "acc");
4437 emitcode ("lcall", "__gptrget");
4438 emitcode ("pop", "b");
4442 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << -rLen));
4443 emitcode ("orl", "a,b");
4446 if (p_type == GPOINTER)
4447 emitcode ("pop", "b");
4453 emitcode ("mov", "@%s,a", rname);
4457 emitcode ("movx", "@dptr,a");
4461 emitcode ("lcall", "__gptrput");
4465 /*-----------------------------------------------------------------*/
4466 /* genDataPointerSet - remat pointer to data space */
4467 /*-----------------------------------------------------------------*/
4469 genDataPointerSet (operand * right,
4473 int size, offset = 0;
4474 char *l, buffer[256];
4476 aopOp (right, ic, FALSE);
4478 l = aopGet (AOP (result), 0);
4479 size = AOP_SIZE (right);
4483 sprintf (buffer, "(%s + %d)", l + 1, offset);
4485 sprintf (buffer, "%s", l + 1);
4486 emitcode ("mov", "%s,%s", buffer,
4487 aopGet (AOP (right), offset++));
4490 freeAsmop (right, NULL, ic, TRUE);
4491 freeAsmop (result, NULL, ic, TRUE);
4494 /*-----------------------------------------------------------------*/
4495 /* genNearPointerSet - emitcode for near pointer put */
4496 /*-----------------------------------------------------------------*/
4498 genNearPointerSet (operand * right,
4506 sym_link *ptype = operandType (result);
4508 retype = getSpec (operandType (right));
4510 aopOp (result, ic, FALSE);
4512 /* if the result is rematerializable &
4513 in data space & not a bit variable */
4514 if (AOP_TYPE (result) == AOP_IMMD &&
4515 DCL_TYPE (ptype) == POINTER &&
4516 !IS_BITVAR (retype))
4518 genDataPointerSet (right, result, ic);
4522 /* if the value is already in a pointer register
4523 then don't need anything more */
4524 if (!AOP_INPREG (AOP (result)))
4526 /* otherwise get a free pointer register */
4528 preg = getFreePtr (ic, &aop, FALSE, 0);
4529 emitcode ("mov", "%s,%s",
4531 aopGet (AOP (result), 0));
4535 rname = aopGet (AOP (result), 0);
4537 freeAsmop (result, NULL, ic, TRUE);
4538 aopOp (right, ic, FALSE);
4540 /* if bitfield then unpack the bits */
4541 if (IS_BITVAR (retype))
4542 genPackBits (retype, right, rname, POINTER);
4545 /* we have can just get the values */
4546 int size = AOP_SIZE (right);
4551 l = aopGet (AOP (right), offset);
4555 emitcode ("mov", "@%s,a", rname);
4558 emitcode ("mov", "@%s,%s", rname, l);
4560 emitcode ("inc", "%s", rname);
4565 /* now some housekeeping stuff */
4568 /* we had to allocate for this iCode */
4569 freeAsmop (NULL, aop, ic, TRUE);
4573 /* we did not allocate which means left
4574 already in a pointer register, then
4575 if size > 0 && this could be used again
4576 we have to point it back to where it
4578 if (AOP_SIZE (right) > 1 &&
4579 !OP_SYMBOL (result)->remat &&
4580 (OP_SYMBOL (result)->liveTo > ic->seq ||
4583 int size = AOP_SIZE (right) - 1;
4585 emitcode ("dec", "%s", rname);
4590 freeAsmop (right, NULL, ic, TRUE);
4595 /*-----------------------------------------------------------------*/
4596 /* genPagedPointerSet - emitcode for Paged pointer put */
4597 /*-----------------------------------------------------------------*/
4599 genPagedPointerSet (operand * right,
4608 retype = getSpec (operandType (right));
4610 aopOp (result, ic, FALSE);
4612 /* if the value is already in a pointer register
4613 then don't need anything more */
4614 if (!AOP_INPREG (AOP (result)))
4616 /* otherwise get a free pointer register */
4618 preg = getFreePtr (ic, &aop, FALSE, 0);
4619 emitcode ("mov", "%s,%s",
4621 aopGet (AOP (result), 0));
4625 rname = aopGet (AOP (result), 0);
4627 freeAsmop (result, NULL, ic, TRUE);
4628 aopOp (right, ic, FALSE);
4630 /* if bitfield then unpack the bits */
4631 if (IS_BITVAR (retype))
4632 genPackBits (retype, right, rname, PPOINTER);
4635 /* we have can just get the values */
4636 int size = AOP_SIZE (right);
4641 l = aopGet (AOP (right), offset);
4644 emitcode ("movx", "@%s,a", rname);
4647 emitcode ("inc", "%s", rname);
4653 /* now some housekeeping stuff */
4656 /* we had to allocate for this iCode */
4657 freeAsmop (NULL, aop, ic, TRUE);
4661 /* we did not allocate which means left
4662 already in a pointer register, then
4663 if size > 0 && this could be used again
4664 we have to point it back to where it
4666 if (AOP_SIZE (right) > 1 &&
4667 !OP_SYMBOL (result)->remat &&
4668 (OP_SYMBOL (result)->liveTo > ic->seq ||
4671 int size = AOP_SIZE (right) - 1;
4673 emitcode ("dec", "%s", rname);
4678 freeAsmop (right, NULL, ic, TRUE);
4683 /*-----------------------------------------------------------------*/
4684 /* genFarPointerSet - set value from far space */
4685 /*-----------------------------------------------------------------*/
4687 genFarPointerSet (operand * right,
4688 operand * result, iCode * ic)
4691 sym_link *retype = getSpec (operandType (right));
4693 aopOp (result, ic, FALSE);
4695 /* if the operand is already in dptr
4696 then we do nothing else we move the value to dptr */
4697 if (AOP_TYPE (result) != AOP_STR)
4699 /* if this is remateriazable */
4700 if (AOP_TYPE (result) == AOP_IMMD)
4701 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4703 { /* we need to get it byte by byte */
4704 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4705 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4706 if (options.model == MODEL_FLAT24)
4708 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4712 /* so dptr know contains the address */
4713 freeAsmop (result, NULL, ic, TRUE);
4714 aopOp (right, ic, FALSE);
4716 /* if bit then unpack */
4717 if (IS_BITVAR (retype))
4718 genPackBits (retype, right, "dptr", FPOINTER);
4721 size = AOP_SIZE (right);
4726 char *l = aopGet (AOP (right), offset++);
4728 emitcode ("movx", "@dptr,a");
4730 emitcode ("inc", "dptr");
4734 freeAsmop (right, NULL, ic, TRUE);
4737 /*-----------------------------------------------------------------*/
4738 /* genGenPointerSet - set value from generic pointer space */
4739 /*-----------------------------------------------------------------*/
4741 genGenPointerSet (operand * right,
4742 operand * result, iCode * ic)
4745 sym_link *retype = getSpec (operandType (right));
4747 aopOp (result, ic, FALSE);
4749 /* if the operand is already in dptr
4750 then we do nothing else we move the value to dptr */
4751 if (AOP_TYPE (result) != AOP_STR)
4753 /* if this is remateriazable */
4754 if (AOP_TYPE (result) == AOP_IMMD)
4756 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4757 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0));
4760 { /* we need to get it byte by byte */
4761 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4762 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4763 if (options.model == MODEL_FLAT24)
4765 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4766 emitcode ("mov", "b,%s", aopGet (AOP (result), 3));
4770 emitcode ("mov", "b,%s", aopGet (AOP (result), 2));
4774 /* so dptr know contains the address */
4775 freeAsmop (result, NULL, ic, TRUE);
4776 aopOp (right, ic, FALSE);
4778 /* if bit then unpack */
4779 if (IS_BITVAR (retype))
4780 genPackBits (retype, right, "dptr", GPOINTER);
4783 size = AOP_SIZE (right);
4788 char *l = aopGet (AOP (right), offset++);
4790 emitcode ("lcall", "__gptrput");
4792 emitcode ("inc", "dptr");
4796 freeAsmop (right, NULL, ic, TRUE);
4799 /*-----------------------------------------------------------------*/
4800 /* genPointerSet - stores the value into a pointer location */
4801 /*-----------------------------------------------------------------*/
4803 genPointerSet (iCode * ic)
4805 operand *right, *result;
4806 sym_link *type, *etype;
4809 right = IC_RIGHT (ic);
4810 result = IC_RESULT (ic);
4812 /* depending on the type of pointer we need to
4813 move it to the correct pointer register */
4814 type = operandType (result);
4815 etype = getSpec (type);
4816 /* if left is of type of pointer then it is simple */
4817 if (IS_PTR (type) && !IS_FUNC (type->next))
4819 p_type = DCL_TYPE (type);
4823 /* we have to go by the storage class */
4824 p_type = PTR_TYPE (SPEC_OCLS (etype));
4826 /* if (SPEC_OCLS(etype)->codesp ) { */
4827 /* p_type = CPOINTER ; */
4830 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4831 /* p_type = FPOINTER ; */
4833 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4834 /* p_type = PPOINTER ; */
4836 /* if (SPEC_OCLS(etype) == idata ) */
4837 /* p_type = IPOINTER ; */
4839 /* p_type = POINTER ; */
4842 /* now that we have the pointer type we assign
4843 the pointer values */
4849 genNearPointerSet (right, result, ic);
4853 genPagedPointerSet (right, result, ic);
4857 genFarPointerSet (right, result, ic);
4861 genGenPointerSet (right, result, ic);
4867 /*-----------------------------------------------------------------*/
4868 /* genIfx - generate code for Ifx statement */
4869 /*-----------------------------------------------------------------*/
4871 genIfx (iCode * ic, iCode * popIc)
4873 operand *cond = IC_COND (ic);
4876 aopOp (cond, ic, FALSE);
4878 /* get the value into acc */
4879 if (AOP_TYPE (cond) != AOP_CRY)
4880 toBoolean (cond, "", 0);
4883 /* the result is now in the accumulator */
4884 freeAsmop (cond, NULL, ic, TRUE);
4886 /* if there was something to be popped then do it */
4890 /* if the condition is a bit variable */
4891 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4892 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4895 /* if (isbit && !IS_ITEMP(cond)) */
4896 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4898 /* // genIfxJump(ic,"a"); */
4903 /*-----------------------------------------------------------------*/
4904 /* genAddrOf - generates code for address of */
4905 /*-----------------------------------------------------------------*/
4907 genAddrOf (iCode * ic)
4909 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4912 aopOp (IC_RESULT (ic), ic, FALSE);
4914 /* if the operand is on the stack then we
4915 need to get the stack offset of this
4919 /* if it has an offset then we need to compute
4923 emitcode ("mov", "a,_bp");
4924 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
4925 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4929 /* we can just move _bp */
4930 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4932 /* fill the result with zero */
4933 size = AOP_SIZE (IC_RESULT (ic)) - 1;
4936 if (options.stack10bit && size < (FPTRSIZE - 1))
4939 "*** warning: pointer to stack var truncated.\n");
4946 if (options.stack10bit && offset == 2)
4948 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
4952 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4959 /* object not on stack then we need the name */
4960 size = AOP_SIZE (IC_RESULT (ic));
4965 char s[SDCC_NAME_MAX];
4967 sprintf (s, "#(%s >> %d)",
4971 sprintf (s, "#%s", sym->rname);
4972 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4976 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4980 /*-----------------------------------------------------------------*/
4981 /* genFarFarAssign - assignment when both are in far space */
4982 /*-----------------------------------------------------------------*/
4984 genFarFarAssign (operand * result, operand * right, iCode * ic)
4986 int size = AOP_SIZE (right);
4989 /* first push the right side on to the stack */
4992 l = aopGet (AOP (right), offset++);
4994 emitcode ("push", "acc");
4997 freeAsmop (right, NULL, ic, FALSE);
4998 /* now assign DPTR to result */
4999 aopOp (result, ic, FALSE);
5000 size = AOP_SIZE (result);
5003 emitcode ("pop", "acc");
5004 aopPut (AOP (result), "a", --offset);
5006 freeAsmop (result, NULL, ic, FALSE);
5010 /*-----------------------------------------------------------------*/
5011 /* genAssign - generate code for assignment */
5012 /*-----------------------------------------------------------------*/
5014 genAssign (iCode * ic)
5016 operand *result, *right;
5018 unsigned long lit = 0L;
5020 result = IC_RESULT (ic);
5021 right = IC_RIGHT (ic);
5023 /* if they are the same */
5024 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5027 aopOp (right, ic, FALSE);
5029 /* special case both in far space */
5030 if (AOP_TYPE (right) == AOP_DPTR &&
5031 IS_TRUE_SYMOP (result) &&
5032 isOperandInFarSpace (result))
5035 genFarFarAssign (result, right, ic);
5039 aopOp (result, ic, TRUE);
5041 /* if they are the same registers */
5042 if (sameRegs (AOP (right), AOP (result)))
5045 /* if the result is a bit */
5046 if (AOP_TYPE (result) == AOP_CRY)
5049 /* if the right size is a literal then
5050 we know what the value is */
5051 if (AOP_TYPE (right) == AOP_LIT)
5053 if (((int) operandLitValue (right)))
5054 aopPut (AOP (result), one, 0);
5056 aopPut (AOP (result), zero, 0);
5060 /* the right is also a bit variable */
5061 if (AOP_TYPE (right) == AOP_CRY)
5063 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5064 aopPut (AOP (result), "c", 0);
5069 toBoolean (right, "", 0);
5070 aopPut (AOP (result), "a", 0);
5074 /* bit variables done */
5076 size = AOP_SIZE (result);
5078 if (AOP_TYPE (right) == AOP_LIT)
5079 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5081 (AOP_TYPE (result) != AOP_REG) &&
5082 (AOP_TYPE (right) == AOP_LIT) &&
5083 !IS_FLOAT (operandType (right)) &&
5086 emitcode ("clr", "a");
5089 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
5090 aopPut (AOP (result), "a", size);
5092 aopPut (AOP (result),
5093 aopGet (AOP (right), size),
5101 aopPut (AOP (result),
5102 aopGet (AOP (right), offset),
5109 freeAsmop (right, NULL, ic, FALSE);
5110 freeAsmop (result, NULL, ic, TRUE);
5113 /*-----------------------------------------------------------------*/
5114 /* genJumpTab - genrates code for jump table */
5115 /*-----------------------------------------------------------------*/
5117 genJumpTab (iCode * ic)
5122 aopOp (IC_JTCOND (ic), ic, FALSE);
5123 /* get the condition into accumulator */
5124 l = aopGet (AOP (IC_JTCOND (ic)), 0);
5126 /* multiply by three */
5127 emitcode ("add", "a,acc");
5128 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
5129 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
5131 jtab = newiTempLabel (NULL);
5132 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
5133 emitcode ("jmp", "@a+dptr");
5134 emitcode ("", "%05d$:", jtab->key + 100);
5135 /* now generate the jump labels */
5136 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5137 jtab = setNextItem (IC_JTLABELS (ic)))
5138 emitcode ("ljmp", "%05d$", jtab->key + 100);
5142 /*-----------------------------------------------------------------*/
5143 /* genCast - gen code for casting */
5144 /*-----------------------------------------------------------------*/
5146 genCast (iCode * ic)
5148 operand *result = IC_RESULT (ic);
5149 sym_link *ctype = operandType (IC_LEFT (ic));
5150 sym_link *rtype = operandType (IC_RIGHT (ic));
5151 operand *right = IC_RIGHT (ic);
5154 /* if they are equivalent then do nothing */
5155 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5158 aopOp (right, ic, FALSE);
5159 aopOp (result, ic, FALSE);
5161 /* if the result is a bit */
5162 if (AOP_TYPE (result) == AOP_CRY)
5164 /* if the right size is a literal then
5165 we know what the value is */
5166 if (AOP_TYPE (right) == AOP_LIT)
5168 if (((int) operandLitValue (right)))
5169 aopPut (AOP (result), one, 0);
5171 aopPut (AOP (result), zero, 0);
5176 /* the right is also a bit variable */
5177 if (AOP_TYPE (right) == AOP_CRY)
5179 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5180 aopPut (AOP (result), "c", 0);
5185 toBoolean (right, "", 0);
5186 aopPut (AOP (result), "a", 0);
5190 /* if they are the same size : or less */
5191 if (AOP_SIZE (result) <= AOP_SIZE (right))
5194 /* if they are in the same place */
5195 if (sameRegs (AOP (right), AOP (result)))
5198 /* if they in different places then copy */
5199 size = AOP_SIZE (result);
5203 aopPut (AOP (result),
5204 aopGet (AOP (right), offset),
5212 /* if the result is of type pointer */
5217 sym_link *type = operandType (right);
5218 sym_link *etype = getSpec (type);
5220 /* pointer to generic pointer */
5221 if (IS_GENPTR (ctype))
5226 p_type = DCL_TYPE (type);
5229 /* we have to go by the storage class */
5230 p_type = PTR_TYPE (SPEC_OCLS (etype));
5233 /* the first two bytes are known */
5234 size = GPTRSIZE - 1;
5238 aopPut (AOP (result),
5239 aopGet (AOP (right), offset),
5243 /* the last byte depending on type */
5261 /* this should never happen */
5262 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5263 "got unknown pointer type");
5266 aopPut (AOP (result), l, GPTRSIZE - 1);
5270 /* just copy the pointers */
5271 size = AOP_SIZE (result);
5275 aopPut (AOP (result),
5276 aopGet (AOP (right), offset),
5283 /* so we now know that the size of destination is greater
5284 than the size of the source */
5285 /* we move to result for the size of source */
5286 size = AOP_SIZE (right);
5290 aopPut (AOP (result),
5291 aopGet (AOP (right), offset),
5296 /* now depending on the sign of the source && destination */
5297 size = AOP_SIZE (result) - AOP_SIZE (right);
5298 /* if unsigned or not an integral type */
5299 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
5302 aopPut (AOP (result), zero, offset++);
5306 /* we need to extend the sign :{ */
5307 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5309 emitcode ("rlc", "a");
5310 emitcode ("subb", "a,acc");
5312 aopPut (AOP (result), "a", offset++);
5315 /* we are done hurray !!!! */
5318 freeAsmop (right, NULL, ic, TRUE);
5319 freeAsmop (result, NULL, ic, TRUE);
5323 /*-----------------------------------------------------------------*/
5324 /* genDjnz - generate decrement & jump if not zero instrucion */
5325 /*-----------------------------------------------------------------*/
5327 genDjnz (iCode * ic, iCode * ifx)
5333 /* if the if condition has a false label
5334 then we cannot save */
5338 /* if the minus is not of the form
5340 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5341 !IS_OP_LITERAL (IC_RIGHT (ic)))
5344 if (operandLitValue (IC_RIGHT (ic)) != 1)
5347 /* if the size of this greater than one then no
5349 if (getSize (operandType (IC_RESULT (ic))) > 1)
5352 /* otherwise we can save BIG */
5353 lbl = newiTempLabel (NULL);
5354 lbl1 = newiTempLabel (NULL);
5356 aopOp (IC_RESULT (ic), ic, FALSE);
5358 if (IS_AOP_PREG (IC_RESULT (ic)))
5360 emitcode ("dec", "%s",
5361 aopGet (AOP (IC_RESULT (ic)), 0));
5362 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5363 emitcode ("jnz", "%05d$", lbl->key + 100);
5367 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0),
5370 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5371 emitcode ("", "%05d$:", lbl->key + 100);
5372 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5373 emitcode ("", "%05d$:", lbl1->key + 100);
5375 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5380 static char *recvregs[8] =
5382 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5386 /*-----------------------------------------------------------------*/
5387 /* genReceive - generate code for a receive iCode */
5388 /*-----------------------------------------------------------------*/
5390 genReceive (iCode * ic)
5392 int size, offset = 0;
5393 aopOp (IC_RESULT (ic), ic, FALSE);
5394 size = AOP_SIZE (IC_RESULT (ic));
5397 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5400 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5403 /*-----------------------------------------------------------------*/
5404 /* gen51Code - generate code for 8051 based controllers */
5405 /*-----------------------------------------------------------------*/
5407 genAVRCode (iCode * lic)
5412 lineHead = lineCurr = NULL;
5414 /* print the allocation information */
5416 printAllocInfo (currFunc, codeOutFile);
5417 /* if debug information required */
5418 /* if (options.debug && currFunc) { */
5421 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5423 if (IS_STATIC (currFunc->etype))
5424 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
5426 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
5429 /* stack pointer name */
5430 if (options.useXstack)
5436 for (ic = lic; ic; ic = ic->next)
5439 if (cln != ic->lineno)
5444 emitcode ("", "C$%s$%d$%d$%d ==.",
5445 FileBaseName (ic->filename), ic->lineno,
5446 ic->level, ic->block);
5449 emitcode (";", "%s %d", ic->filename, ic->lineno);
5452 /* if the result is marked as
5453 spilt and rematerializable or code for
5454 this has already been generated then
5456 if (resultRemat (ic) || ic->generated)
5459 /* depending on the operation */
5479 /* IPOP happens only when trying to restore a
5480 spilt live range, if there is an ifx statement
5481 following this pop then the if statement might
5482 be using some of the registers being popped which
5483 would destory the contents of the register so
5484 we need to check for this condition and handle it */
5486 ic->next->op == IFX &&
5487 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5488 genIfx (ic->next, ic);
5506 genEndFunction (ic);
5526 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5543 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5547 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5551 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5555 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5559 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5563 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5575 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5579 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5583 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5610 case GET_VALUE_AT_ADDRESS:
5615 if (POINTER_SET (ic))
5642 addSet (&_G.sendSet, ic);
5647 /* piCode(ic,stdout); */
5653 /* now we are ready to call the
5654 peep hole optimizer */
5655 if (!options.nopeep)
5656 peepHole (&lineHead);
5658 /* now do the actual printing */
5659 printLine (lineHead, codeOutFile);