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";
64 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
65 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
66 char **fAVRReturn = fReturnAVR;
67 static short rbank = -1;
68 static char *larray[4] = { "lo8", "hi8", "hlo8", "hhi8" };
69 static char *tscr[4] = { "r0", "r1", "r24", "r25" };
80 extern int avr_ptrRegReq;
82 extern FILE *codeOutFile;
83 static void saverbank (int, iCode *, bool);
84 #define RESULTONSTACK(x) \
85 (IC_RESULT(x) && IC_RESULT(x)->aop && \
86 IC_RESULT(x)->aop->type == AOP_STK )
88 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
89 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
90 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
91 #define CLRC emitcode("clc","")
92 #define SETC emitcode("stc","")
94 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00
102 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, char *fmt, ...)
118 char lb[MAX_INLINEASM];
125 sprintf (lb, "%s\t", inst);
127 sprintf (lb, "%s", inst);
128 vsprintf (lb + (strlen (lb)), fmt, ap);
131 vsprintf (lb, fmt, ap);
133 while (isspace (*lbp))
137 lineCurr = (lineCurr ?
138 connectLine (lineCurr, newLineNode (lb)) :
139 (lineHead = newLineNode (lb)));
140 lineCurr->isInline = _G.inLine;
141 lineCurr->isDebug = _G.debugLine;
145 /*-----------------------------------------------------------------*/
146 /* getFreePtr - returns X or Z whichever is free or can be pushed */
147 /*-----------------------------------------------------------------*/
149 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
151 bool xiu = FALSE, ziu = FALSE;
152 bool xou = FALSE, zou = FALSE;
154 /* the logic: if x & z used in the instruction
155 then we are in trouble otherwise */
157 /* first check if x & z are used by this
158 instruction, in which case we are in trouble */
159 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
160 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
164 xou = bitVectBitValue (ic->rMask, X_IDX);
165 zou = bitVectBitValue (ic->rMask, Z_IDX);
167 /* if no usage of Z then return it */
169 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
170 (*aopp)->type = AOP_Z;
172 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
173 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
176 /* if no usage of X then return it */
177 if (!xiu && !xou && !zonly) {
178 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
179 (*aopp)->type = AOP_X;
181 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
182 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
185 /* if z not used then */
188 /* push it if not already pushed */
190 emitcode ("push", "%s",
191 avr_regWithIdx (R30_IDX)->dname);
192 emitcode ("push", "%s",
193 avr_regWithIdx (R31_IDX)->dname);
197 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
198 (*aopp)->type = AOP_Z;
199 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
200 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
203 /* now we know they both have usage */
204 /* if x not used in this instruction */
205 if (!xiu && !zonly) {
206 /* push it if not already pushed */
208 emitcode ("push", "%s",
209 avr_regWithIdx (R26_IDX)->dname);
210 emitcode ("push", "%s",
211 avr_regWithIdx (R27_IDX)->dname);
215 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
216 (*aopp)->type = AOP_X;
218 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
219 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
224 /* I said end of world but not quite end of world yet */
225 /* if this is a result then we can push it on the stack */
227 (*aopp)->type = AOP_STK;
232 /* other wise this is true end of the world */
233 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
234 "getFreePtr should never reach here");
238 /*-----------------------------------------------------------------*/
239 /* newAsmop - creates a new asmOp */
240 /*-----------------------------------------------------------------*/
242 newAsmop (short type)
246 aop = Safe_calloc (1, sizeof (asmop));
251 /*-----------------------------------------------------------------*/
252 /* pointerCode - returns the code for a pointer type */
253 /*-----------------------------------------------------------------*/
255 pointerCode (sym_link * etype)
258 return PTR_TYPE (SPEC_OCLS (etype));
262 /*-----------------------------------------------------------------*/
263 /* aopForSym - for a true symbol */
264 /*-----------------------------------------------------------------*/
266 aopForSym (iCode * ic, symbol * sym, bool result)
269 memmap *space = SPEC_OCLS (sym->etype);
271 /* if already has one */
275 /* assign depending on the storage class */
276 /* if it is on the stack */
278 sym->aop = aop = newAsmop (0);
279 aop->size = getSize (sym->type);
281 /* we can use std / ldd instruction */
283 && (sym->stack + getSize (sym->type) - 1) <= 63) {
284 aop->type = AOP_STK_D;
285 aop->aopu.aop_stk = sym->stack;
289 /* otherwise get a free pointer register X/Z */
290 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
292 /* now assign the address of the variable to
293 the pointer register */
294 if (aop->type != AOP_STK) {
295 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
296 if (sym->stack < 0) {
297 if ((sym->stack - _G.nRegsSaved) > -63) {
298 emitcode ("sbiw", "%s,0x%02x",
299 aop->aopu.aop_ptr->name,
304 emitcode ("subi", "%s,lo8(%d)",
305 aop->aopu.aop_ptr->name,
306 sym->stack - _G.nRegsSaved);
307 emitcode ("sbci", "%s,hi8(%d)",
309 sym->stack - _G.nRegsSaved);
313 if (sym->stack <= 63) {
314 emitcode ("adiw", "%s,0x%02x",
315 aop->aopu.aop_ptr->name,
319 emitcode ("subi", "%s,lo8(-%d)",
320 aop->aopu.aop_ptr->name,
322 emitcode ("sbci", "%s,hi8(-%d)",
331 /* if in bit space */
332 if (IN_BITSPACE (space)) {
333 sym->aop = aop = newAsmop (AOP_CRY);
334 aop->aopu.aop_dir = sym->rname;
335 aop->size = getSize (sym->type);
338 /* if it is in direct space */
339 if (IN_DIRSPACE (space)) {
340 sym->aop = aop = newAsmop (AOP_DIR);
341 aop->aopu.aop_dir = sym->rname;
342 aop->size = getSize (sym->type);
346 /* special case for a function */
347 if (IS_FUNC (sym->type)) {
348 sym->aop = aop = newAsmop (AOP_IMMD);
349 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
350 strcpy (aop->aopu.aop_immd, sym->rname);
351 aop->size = FPTRSIZE;
355 /* only remaining is code / eeprom which will need pointer reg */
356 /* if it is in code space */
358 sym->aop = aop = newAsmop (0);
360 if (IN_CODESPACE (space))
363 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
364 aop->size = getSize (sym->type);
365 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
366 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
371 /*-----------------------------------------------------------------*/
372 /* aopForRemat - rematerialzes an object */
373 /*-----------------------------------------------------------------*/
375 aopForRemat (symbol * sym)
377 iCode *ic = sym->rematiCode;
378 asmop *aop = newAsmop (AOP_IMMD);
383 val += (int) operandLitValue (IC_RIGHT (ic));
384 else if (ic->op == '-')
385 val -= (int) operandLitValue (IC_RIGHT (ic));
389 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
393 sprintf (buffer, "(%s %c 0x%04x)",
394 OP_SYMBOL (IC_LEFT (ic))->rname,
395 val >= 0 ? '+' : '-', abs (val) & 0xffff);
397 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
399 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
400 strcpy (aop->aopu.aop_immd, buffer);
404 /*-----------------------------------------------------------------*/
405 /* regsInCommon - two operands have some registers in common */
406 /*-----------------------------------------------------------------*/
408 regsInCommon (operand * op1, operand * op2)
413 /* if they have registers in common */
414 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
417 sym1 = OP_SYMBOL (op1);
418 sym2 = OP_SYMBOL (op2);
420 if (sym1->nRegs == 0 || sym2->nRegs == 0)
423 for (i = 0; i < sym1->nRegs; i++) {
428 for (j = 0; j < sym2->nRegs; j++) {
432 if (sym2->regs[j] == sym1->regs[i])
440 /*-----------------------------------------------------------------*/
441 /* operandsEqu - equivalent */
442 /*-----------------------------------------------------------------*/
444 operandsEqu (operand * op1, operand * op2)
448 /* if they not symbols */
449 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
452 sym1 = OP_SYMBOL (op1);
453 sym2 = OP_SYMBOL (op2);
455 /* if both are itemps & one is spilt
456 and the other is not then false */
457 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
458 sym1->isspilt != sym2->isspilt) return FALSE;
460 /* if they are the same */
464 if (strcmp (sym1->rname, sym2->rname) == 0)
468 /* if left is a tmp & right is not */
469 if (IS_ITEMP (op1) &&
470 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
473 if (IS_ITEMP (op2) &&
475 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
481 /*-----------------------------------------------------------------*/
482 /* sameRegs - two asmops have the same registers */
483 /*-----------------------------------------------------------------*/
485 sameRegs (asmop * aop1, asmop * aop2)
492 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
495 if (aop1->size != aop2->size)
498 for (i = 0; i < aop1->size; i++)
499 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
505 /*-----------------------------------------------------------------*/
506 /* isRegPair - for size 2 if this operand has a register pair */
507 /*-----------------------------------------------------------------*/
509 isRegPair (asmop * aop)
511 if (!aop || aop->size != 2)
513 if (aop->type == AOP_X || aop->type == AOP_Z)
515 if (aop->type != AOP_REG)
517 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
518 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
524 /*-----------------------------------------------------------------*/
525 /* aopOp - allocates an asmop for an operand : */
526 /*-----------------------------------------------------------------*/
528 aopOp (operand * op, iCode * ic, bool result)
537 /* if this a literal */
538 if (IS_OP_LITERAL (op)) {
539 op->aop = aop = newAsmop (AOP_LIT);
540 aop->aopu.aop_lit = op->operand.valOperand;
541 aop->size = getSize (operandType (op));
545 /* if already has a asmop then continue */
549 /* if the underlying symbol has a aop */
550 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
551 op->aop = OP_SYMBOL (op)->aop;
555 /* if this is a true symbol */
556 if (IS_TRUE_SYMOP (op)) {
557 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
561 /* this is a temporary : this has
567 e) can be a return use only */
569 sym = OP_SYMBOL (op);
572 /* if the type is a conditional */
573 if (sym->regType == REG_CND) {
574 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
579 /* if it is spilt then two situations
581 b) has a spill location */
582 if (sym->isspilt || sym->nRegs == 0) {
584 /* rematerialize it NOW */
586 sym->aop = op->aop = aop = aopForRemat (sym);
587 aop->size = getSize (sym->type);
592 assert ("ACC_USE cannot happen in AVR\n");
597 aop = op->aop = sym->aop = newAsmop (AOP_STR);
598 aop->size = getSize (sym->type);
599 for (i = 0; i < (int) fAVRReturnSize; i++)
600 aop->aopu.aop_str[i] = fAVRReturn[i];
604 /* else spill location */
605 sym->aop = op->aop = aop =
606 aopForSym (ic, sym->usl.spillLoc, result);
607 aop->size = getSize (sym->type);
611 /* must be in a register */
612 sym->aop = op->aop = aop = newAsmop (AOP_REG);
613 aop->size = sym->nRegs;
614 for (i = 0; i < sym->nRegs; i++)
615 aop->aopu.aop_reg[i] = sym->regs[i];
618 /*-----------------------------------------------------------------*/
619 /* freeAsmop - free up the asmop given to an operand */
620 /*----------------------------------------------------------------*/
622 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
639 /* depending on the asmop type only three cases need work AOP_RO
640 , AOP_R1 && AOP_STK */
645 emitcode ("pop", "r26");
646 emitcode ("pop", "r27");
650 bitVectUnSetBit (ic->rUsed, X_IDX);
656 emitcode ("pop", "r30");
657 emitcode ("pop", "r31");
661 bitVectUnSetBit (ic->rUsed, Z_IDX);
667 int stk = aop->aopu.aop_stk + aop->size;
668 bitVectUnSetBit (ic->rUsed, X_IDX);
669 bitVectUnSetBit (ic->rUsed, Z_IDX);
671 getFreePtr (ic, &aop, FALSE, 0);
673 emitcode ("movw", "%s,r28");
675 if (stk <= 63 && stk > 0) {
676 emitcode ("adiw", "%s,0x%02x",
677 aop->aopu.aop_ptr->name,
681 emitcode ("subi", "%s,lo8(%d)",
682 aop->aopu.aop_ptr->name,
684 emitcode ("sbci", "%s,hi8(%d)",
691 emitcode ("pop", "r24");
692 emitcode ("st", "-%s,r24",
693 aop->type == AOP_X ? "X" : "Z");
698 freeAsmop (op, NULL, ic, TRUE);
700 emitcode ("pop", "r26");
701 emitcode ("pop", "r27");
706 emitcode ("pop", "r30");
707 emitcode ("pop", "r31");
714 /* all other cases just dealloc */
718 OP_SYMBOL (op)->aop = NULL;
719 /* if the symbol has a spill */
721 SPIL_LOC (op)->aop = NULL;
726 /*-----------------------------------------------------------------*/
727 /* aopGet - for fetching value of the aop */
728 /*-----------------------------------------------------------------*/
730 aopGet (asmop * aop, int offset)
735 /* offset is greater than
737 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
740 /* depending on type */
744 if (offset > aop->coff) {
745 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
749 if (offset < aop->coff) {
750 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
755 emitcode ("ld", "%s,x",
756 (rs = ((offset & 1) ? "r25" : "r24")));
761 if (offset > aop->coff) {
762 emitcode ("adiw", "r30,%d",
766 emitcode ("sbiw", "r30,%d",
769 emitcode ("lpm", "%s,z",
770 (rs = ((offset & 1) ? "r25" : "r24")));
774 if (offset > aop->coff) {
775 emitcode ("ldd", "%s,z+%d",
777 ((offset & 1) ? "r25" : "r24")),
781 emitcode ("sbiw", "%s,%d",
782 aop->aopu.aop_ptr->name,
785 emitcode ("ld", "%s,z",
787 ((offset & 1) ? "r25" : "r24")));
794 emitcode ("lds", "%s,(%s)+%d",
795 (rs = ((offset & 1) ? "r25" : "r24")),
796 aop->aopu.aop_immd, offset);
800 emitcode ("lds", "%s,(%s)+%d",
801 (rs = ((offset & 1) ? "r25" : "r24")),
802 aop->aopu.aop_dir, offset);
806 return aop->aopu.aop_reg[offset]->name;
809 assert ("cannot be in bit space AOP_CRY\n");
813 s = aopLiteral (aop->aopu.aop_lit, offset);
814 emitcode ("ldi", "%s,lo8(%s)",
815 (rs = ((offset & 1) ? "r24" : "r25")), s);
820 return aop->aopu.aop_str[offset];
823 emitcode ("ldd", "%s,Y+%d",
824 (rs = ((offset & 1) ? "r25" : "r24")),
825 aop->aopu.aop_stk + offset);
829 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
830 "aopget got unsupported aop->type");
834 /*-----------------------------------------------------------------*/
835 /* aopPut - puts a string for a aop */
836 /*-----------------------------------------------------------------*/
838 aopPut (asmop * aop, char *s, int offset)
842 if (aop->size && offset > (aop->size - 1)) {
843 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
844 "aopPut got offset > aop->size");
848 /* will assign value to value */
849 /* depending on where it is ofcourse */
853 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
856 sprintf (d, "%s", aop->aopu.aop_dir);
859 emitcode ("sts", "%s,%s", d, s);
863 if (toupper (*s) != 'R') {
865 emitcode ("clr", "%s",
866 aop->aopu.aop_reg[offset]->name);
869 emitcode ("ldi", "r25,%s", s);
870 emitcode ("mov", "%s,r35",
871 aop->aopu.aop_reg[offset]->name);
875 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
876 emitcode ("mov", "%s,%s",
877 aop->aopu.aop_reg[offset]->name, s);
883 if (offset > aop->coff) {
884 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
888 if (offset < aop->coff) {
889 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
894 emitcode ("st", "x,%s", s);
899 if (offset > aop->coff) {
900 emitcode ("adiw", "r30,%d",
904 emitcode ("sbiw", "r30,%d",
907 emitcode ("lpm", "%s,z", s);
911 if (offset > aop->coff) {
912 emitcode ("sdd", "z+%d,%s",
913 offset - aop->coff, s);
916 emitcode ("sbiw", "%s,%d",
917 aop->aopu.aop_ptr->name,
920 emitcode ("ld", "%s,z", s);
926 emitcode ("push", "%s", s);
930 /* if used only for a condition code check */
931 assert (toupper (*s) == 'R');
933 emitcode ("xrl", "r0,r0");
934 emitcode ("cpi", "%s,0", s);
937 emitcode ("cpc", "r0,%s", s);
943 if (strcmp (aop->aopu.aop_str[offset], s))
944 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
949 emitcode ("std", "y+%d,%s", offset, s);
953 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
954 "aopPut got unsupported aop->type");
960 /*-----------------------------------------------------------------*/
961 /* reAdjustPreg - points a register back to where it should */
962 /*-----------------------------------------------------------------*/
964 reAdjustPreg (asmop * aop)
969 if ((size = aop->size) <= 1)
975 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
981 #define AOP(op) op->aop
982 #define AOP_TYPE(op) AOP(op)->type
983 #define AOP_SIZE(op) AOP(op)->size
984 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
985 AOP_TYPE(x) == AOP_Z))
986 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
987 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
988 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
989 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
990 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
991 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
992 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
994 /*-----------------------------------------------------------------*/
995 /* genNotFloat - generates not for float operations */
996 /*-----------------------------------------------------------------*/
998 genNotFloat (operand * op, operand * res)
1004 /* we will put 127 in the first byte of
1006 aopPut (AOP (res), "127", 0);
1007 size = AOP_SIZE (op) - 1;
1010 l = aopGet (op->aop, offset++);
1014 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1016 tlbl = newiTempLabel (NULL);
1018 tlbl = newiTempLabel (NULL);
1019 aopPut (res->aop, zero, 1);
1020 emitcode ("cpi", "r0,0");
1021 emitcode ("breq", "L%05d", tlbl->key);
1022 aopPut (res->aop, one, 1);
1023 emitcode ("", "L%05d:", tlbl->key);
1025 size = res->aop->size - 2;
1027 /* put zeros in the rest */
1029 aopPut (res->aop, zero, offset++);
1032 /*-----------------------------------------------------------------*/
1033 /* opIsGptr: returns non-zero if the passed operand is */
1034 /* a generic pointer type. */
1035 /*-----------------------------------------------------------------*/
1037 opIsGptr (operand * op)
1039 sym_link *type = operandType (op);
1041 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1047 /*-----------------------------------------------------------------*/
1048 /* getDataSize - get the operand data size */
1049 /*-----------------------------------------------------------------*/
1051 getDataSize (operand * op)
1054 size = AOP_SIZE (op);
1055 if (size == GPTRSIZE) {
1056 sym_link *type = operandType (op);
1057 if (IS_GENPTR (type)) {
1058 /* generic pointer; arithmetic operations
1059 * should ignore the high byte (pointer type).
1067 /*-----------------------------------------------------------------*/
1068 /* outAcc - output Acc */
1069 /*-----------------------------------------------------------------*/
1071 outAcc (operand * result)
1074 size = getDataSize (result);
1076 aopPut (AOP (result), "r0", 0);
1079 /* unsigned or positive */
1081 aopPut (AOP (result), zero, offset++);
1086 /*-----------------------------------------------------------------*/
1087 /* outBitC - output a bit C */
1088 /*-----------------------------------------------------------------*/
1090 outBitC (operand * result)
1092 emitcode ("clr", "r0");
1093 emitcode ("rol", "r0");
1097 /*-----------------------------------------------------------------*/
1098 /* toBoolean - emit code for orl a,operator(sizeop) */
1099 /*-----------------------------------------------------------------*/
1101 toBoolean (operand * oper, char *r, bool clr)
1103 int size = AOP_SIZE (oper);
1106 emitcode ("clr", "%s", r);
1108 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1112 /*-----------------------------------------------------------------*/
1113 /* genNot - generate code for ! operation */
1114 /*-----------------------------------------------------------------*/
1119 sym_link *optype = operandType (IC_LEFT (ic));
1120 int size, offset = 1;
1122 /* assign asmOps to operand & result */
1123 aopOp (IC_LEFT (ic), ic, FALSE);
1124 aopOp (IC_RESULT (ic), ic, TRUE);
1126 /* if type float then do float */
1127 if (IS_FLOAT (optype)) {
1128 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1131 emitcode ("clr", "r24");
1132 tlbl = newiTempLabel (NULL);
1133 size = AOP_SIZE (IC_LEFT (ic));
1136 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1141 emitcode ("cpc", "%s,r24",
1142 aopGet (AOP (IC_LEFT (ic)),
1145 emitcode ("cpi", "%s,0",
1146 aopGet (AOP (IC_LEFT (ic)),
1150 emitcode ("bne", "L%05d", tlbl->key);
1152 emitcode ("ldi", "r24,1");
1153 emitcode ("", "L%05d:", tlbl->key);
1154 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1155 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1158 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1162 /* release the aops */
1163 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1164 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1168 /*-----------------------------------------------------------------*/
1169 /* genCpl - generate code for complement */
1170 /*-----------------------------------------------------------------*/
1178 /* assign asmOps to operand & result */
1179 aopOp (IC_LEFT (ic), ic, FALSE);
1180 aopOp (IC_RESULT (ic), ic, TRUE);
1181 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1182 size = AOP_SIZE (IC_RESULT (ic));
1184 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1186 emitcode ("com", "%s", l);
1189 aopPut (AOP (IC_RESULT (ic)), l, offset);
1190 emitcode ("com", "%s",
1191 aopGet (AOP (IC_RESULT (ic)), offset));
1196 /* release the aops */
1197 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1198 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1201 /*-----------------------------------------------------------------*/
1202 /* genUminusFloat - unary minus for floating points */
1203 /*-----------------------------------------------------------------*/
1205 genUminusFloat (operand * op, operand * result)
1207 int size, offset = 0;
1209 /* for this we just need to flip the
1210 first it then copy the rest in place */
1211 size = AOP_SIZE (op) - 1;
1212 l = aopGet (AOP (op), 3);
1214 emitcode ("ldi", "r24,0x80");
1215 if (sameRegs (AOP (op), AOP (result))) {
1216 emitcode ("eor", "%s,r24", l);
1219 aopPut (AOP (result), l, 3);
1220 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1223 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1228 /*-----------------------------------------------------------------*/
1229 /* genUminus - unary minus code generation */
1230 /*-----------------------------------------------------------------*/
1232 genUminus (iCode * ic)
1235 sym_link *optype, *rtype;
1239 aopOp (IC_LEFT (ic), ic, FALSE);
1240 aopOp (IC_RESULT (ic), ic, TRUE);
1242 optype = operandType (IC_LEFT (ic));
1243 rtype = operandType (IC_RESULT (ic));
1245 /* if float then do float stuff */
1246 if (IS_FLOAT (optype)) {
1247 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1251 /* otherwise subtract from zero */
1252 size = AOP_SIZE (IC_LEFT (ic));
1254 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1257 emitcode ("neg", "%s",
1258 aopGet (AOP (IC_LEFT (ic)), 0));
1261 aopPut (AOP (IC_RESULT (ic)),
1262 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1263 emitcode ("neg", "%s",
1264 aopGet (AOP (IC_RESULT (ic)), 0));
1270 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1272 aopPut (AOP (IC_RESULT (ic)), l, offset);
1273 l = aopGet (AOP (IC_RESULT (ic)), offset);
1276 emitcode ("com", "%s", l);
1278 emitcode ("neg", "%s", l);
1281 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1284 emitcode ("sbci", "%s,lo8(-1)",
1285 aopGet (AOP (IC_RESULT (ic)), offset++));
1289 /* if any remaining bytes in the result */
1290 /* we just need to propagate the sign */
1291 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1292 symbol *tlbl = newiTempLabel (NULL);
1293 emitcode ("clr", "r0");
1294 emitcode ("brcc", "L%05d", tlbl->key);
1295 emitcode ("com", "r0");
1296 emitcode ("", "L%05d:", tlbl->key);
1298 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1302 /* release the aops */
1303 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1304 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1307 /*-----------------------------------------------------------------*/
1308 /* assignResultValue - */
1309 /*-----------------------------------------------------------------*/
1311 assignResultValue (operand * oper)
1314 int size = AOP_SIZE (oper);
1316 aopPut (AOP (oper), fAVRReturn[offset], offset);
1321 /*-----------------------------------------------------------------*/
1322 /* saveZreg - if indirect call then save z-pointer register */
1323 /*-----------------------------------------------------------------*/
1325 saveZreg (iCode * ic)
1327 /* only if live accross this call */
1328 if (ic->regsSaved == 0 &&
1329 (bitVectBitValue (ic->rMask, R30_IDX) ||
1330 bitVectBitValue (ic->rMask, R31_IDX))) {
1332 emitcode ("push", "r30");
1333 emitcode ("push", "r31");
1337 /*-----------------------------------------------------------------*/
1338 /* popZreg - restore values of zreg */
1339 /*-----------------------------------------------------------------*/
1341 popZreg (iCode * ic)
1343 if (ic->regsSaved) {
1344 emitcode ("pop", "r31");
1345 emitcode ("pop", "r30");
1349 /*-----------------------------------------------------------------*/
1350 /* genIpush - genrate code for pushing this gets a little complex */
1351 /*-----------------------------------------------------------------*/
1353 genIpush (iCode * ic)
1355 int size, offset = 0;
1359 if (!ic->parmPush) {
1360 /* and the item is spilt then do nothing */
1361 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1366 for (lic = ic->next; lic; lic = lic->next)
1367 if (lic->op == PCALL)
1373 /* this is a paramter push */
1374 aopOp (IC_LEFT (ic), ic, FALSE);
1375 size = AOP_SIZE (IC_LEFT (ic));
1377 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1378 emitcode ("push", "%s", l);
1381 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1384 /*-----------------------------------------------------------------*/
1385 /* genIpop - recover the registers: can happen only for spilling */
1386 /*-----------------------------------------------------------------*/
1388 genIpop (iCode * ic)
1393 /* if the temp was not pushed then */
1394 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1397 aopOp (IC_LEFT (ic), ic, FALSE);
1398 size = AOP_SIZE (IC_LEFT (ic));
1399 offset = (size - 1);
1401 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1403 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1406 /*-----------------------------------------------------------------*/
1407 /* genCall - generates a call statement */
1408 /*-----------------------------------------------------------------*/
1410 genCall (iCode * ic)
1413 /* if send set is not empty the assign */
1417 for (sic = setFirstItem (_G.sendSet); sic;
1418 sic = setNextItem (_G.sendSet)) {
1419 int size, offset = 0;
1420 aopOp (IC_LEFT (sic), sic, FALSE);
1421 size = AOP_SIZE (IC_LEFT (sic));
1424 aopGet (AOP (IC_LEFT (sic)), offset);
1426 sprintf (buffer, "r%d", rnum++);
1428 emitcode ("mov", "%s,%s", b, l);
1431 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1436 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1437 OP_SYMBOL (IC_LEFT (ic))->rname :
1438 OP_SYMBOL (IC_LEFT (ic))->name));
1440 /* if we need assign a result value */
1441 if ((IS_ITEMP (IC_RESULT (ic)) &&
1442 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1443 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1444 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1446 aopOp (IC_RESULT (ic), ic, FALSE);
1447 assignResultValue (IC_RESULT (ic));
1448 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1451 /* adjust the stack for parameters if required */
1452 if (ic->parmBytes) {
1453 if (ic->parmBytes > 63) {
1454 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1457 emitcode ("subi", "r28,lo8(%d)",
1459 emitcode ("sbci", "r29,hi8(%d)",
1466 /*-----------------------------------------------------------------*/
1467 /* genPcall - generates a call by pointer statement */
1468 /*-----------------------------------------------------------------*/
1470 genPcall (iCode * ic)
1476 aopOp (IC_LEFT (ic), ic, FALSE);
1477 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1478 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1479 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1481 /* if send set is not empty the assign */
1485 for (sic = setFirstItem (_G.sendSet); sic;
1486 sic = setNextItem (_G.sendSet)) {
1487 int size, offset = 0;
1488 aopOp (IC_LEFT (sic), sic, FALSE);
1489 size = AOP_SIZE (IC_LEFT (sic));
1492 aopGet (AOP (IC_LEFT (sic)), offset);
1494 sprintf (b, "r%d", rnum++);
1496 emitcode ("mov", "%s,%s", b, l);
1499 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1504 emitcode ("icall", "");
1506 /* if we need assign a result value */
1507 if ((IS_ITEMP (IC_RESULT (ic)) &&
1508 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1509 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1510 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1512 aopOp (IC_RESULT (ic), ic, FALSE);
1514 assignResultValue (IC_RESULT (ic));
1515 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1518 /* adjust the stack for parameters if
1520 if (ic->parmBytes) {
1522 if (ic->parmBytes > 3) {
1523 emitcode ("mov", "a,%s", spname);
1524 emitcode ("add", "a,#0x%02x",
1525 (-ic->parmBytes) & 0xff);
1526 emitcode ("mov", "%s,a", spname);
1529 for (i = 0; i < ic->parmBytes; i++)
1530 emitcode ("dec", "%s", spname);
1534 /* adjust the stack for parameters if required */
1535 if (ic->parmBytes) {
1536 if (ic->parmBytes > 63) {
1537 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1540 emitcode ("subi", "r28,lo8(%d)",
1542 emitcode ("sbci", "r29,hi8(%d)",
1550 /*-----------------------------------------------------------------*/
1551 /* resultRemat - result is rematerializable */
1552 /*-----------------------------------------------------------------*/
1554 resultRemat (iCode * ic)
1556 if (SKIP_IC (ic) || ic->op == IFX)
1559 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1560 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1561 if (sym->remat && !POINTER_SET (ic))
1568 #if defined(__BORLANDC__) || defined(_MSC_VER)
1569 #define STRCASECMP stricmp
1571 #define STRCASECMP strcasecmp
1574 /*-----------------------------------------------------------------*/
1575 /* inExcludeList - return 1 if the string is in exclude Reg list */
1576 /*-----------------------------------------------------------------*/
1578 inExcludeList (char *s)
1582 if (options.excludeRegs[i] &&
1583 STRCASECMP (options.excludeRegs[i], "none") == 0)
1586 for (i = 0; options.excludeRegs[i]; i++) {
1587 if (options.excludeRegs[i] &&
1588 STRCASECMP (s, options.excludeRegs[i]) == 0)
1594 /*-----------------------------------------------------------------*/
1595 /* genFunction - generated code for function entry */
1596 /*-----------------------------------------------------------------*/
1598 genFunction (iCode * ic)
1605 /* create the function header */
1606 emitcode (";", "-----------------------------------------");
1607 emitcode (";", " function %s",
1608 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1609 emitcode (";", "-----------------------------------------");
1611 emitcode ("", "%s:", sym->rname);
1612 fetype = getSpec (operandType (IC_LEFT (ic)));
1614 /* if critical function then turn interrupts off */
1615 if (SPEC_CRTCL (fetype))
1616 emitcode ("cli", "");
1618 if (IS_ISR (sym->etype)) {
1621 /* save the preserved registers that are used in this function */
1622 for (i = R2_IDX; i <= R15_IDX; i++) {
1623 if (bitVectBitValue (sym->regsUsed, i)) {
1625 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1628 /* now for the pointer registers */
1629 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1631 emitcode ("push", "r26");
1633 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1635 emitcode ("push", "r27");
1637 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1639 emitcode ("push", "r30");
1641 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1643 emitcode ("push", "r31");
1645 /* adjust the stack for the function */
1647 emitcode ("push", "r28");
1648 emitcode ("push", "r29");
1649 emitcode ("in", "r28,__SP_L__");
1650 emitcode ("in", "r29,__SP_H__");
1651 if (sym->stack <= 63) {
1652 emitcode ("sbiw", "r28,%d", sym->stack);
1655 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1656 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1658 emitcode ("out", "__SP_L__,r28");
1659 emitcode ("out", "__SP_H__,r29");
1663 /*-----------------------------------------------------------------*/
1664 /* genEndFunction - generates epilogue for functions */
1665 /*-----------------------------------------------------------------*/
1667 genEndFunction (iCode * ic)
1669 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1672 /* restore stack pointer */
1674 if (sym->stack <= 63) {
1675 emitcode ("adiw", "r28,%d", sym->stack);
1678 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1679 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1681 emitcode ("out", "__SP_L__,r28");
1682 emitcode ("out", "__SP_H__,r29");
1684 /* pop frame pointer */
1685 emitcode ("pop", "r29");
1686 emitcode ("pop", "r28");
1688 /* restore preserved registers */
1689 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1691 emitcode ("pop", "r31");
1693 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1695 emitcode ("pop", "r30");
1697 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1699 emitcode ("pop", "r27");
1701 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1703 emitcode ("pop", "r26");
1705 for (i = R15_IDX; i >= R2_IDX; i--) {
1706 if (bitVectBitValue (sym->regsUsed, i)) {
1708 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1712 if (SPEC_CRTCL (sym->etype))
1713 emitcode ("sti", "");
1715 if (IS_ISR (sym->etype)) {
1716 emitcode ("rti", "");
1719 emitcode ("ret", "");
1724 /*-----------------------------------------------------------------*/
1725 /* genRet - generate code for return statement */
1726 /*-----------------------------------------------------------------*/
1730 int size, offset = 0;
1732 /* if we have no return value then
1733 just generate the "ret" */
1737 /* we have something to return then
1738 move the return value into place */
1739 aopOp (IC_LEFT (ic), ic, FALSE);
1740 size = AOP_SIZE (IC_LEFT (ic));
1743 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1744 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1746 (int) floatFromVal (AOP (IC_LEFT (ic))->
1747 aopu.aop_lit), offset);
1751 l = aopGet (AOP (IC_LEFT (ic)), offset);
1752 if (strcmp (fAVRReturn[offset], l))
1753 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1759 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1762 /* generate a jump to the return label
1763 if the next is not the return statement */
1764 if (!(ic->next && ic->next->op == LABEL &&
1765 IC_LABEL (ic->next) == returnLabel))
1767 emitcode ("rjmp", "L%05d", returnLabel->key);
1771 /*-----------------------------------------------------------------*/
1772 /* genLabel - generates a label */
1773 /*-----------------------------------------------------------------*/
1775 genLabel (iCode * ic)
1777 /* special case never generate */
1778 if (IC_LABEL (ic) == entryLabel)
1781 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1784 /*-----------------------------------------------------------------*/
1785 /* genGoto - generates a ljmp */
1786 /*-----------------------------------------------------------------*/
1788 genGoto (iCode * ic)
1790 emitcode ("rjmp", "L%05d:", (IC_LABEL (ic)->key + 100));
1793 /*-----------------------------------------------------------------*/
1794 /* findLabelBackwards: walks back through the iCode chain looking */
1795 /* for the given label. Returns number of iCode instructions */
1796 /* between that label and given ic. */
1797 /* Returns zero if label not found. */
1798 /*-----------------------------------------------------------------*/
1800 findLabelBackwards (iCode * ic, int key)
1808 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
1809 /* printf("findLabelBackwards = %d\n", count); */
1817 /*-----------------------------------------------------------------*/
1818 /* genPlusIncr :- does addition with increment if possible */
1819 /*-----------------------------------------------------------------*/
1821 genPlusIncr (iCode * ic)
1823 unsigned int icount;
1825 /* will try to generate an increment */
1826 /* if the right side is not a literal
1828 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1832 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1835 /* if the sizes are greater than 2 or they are not the same regs
1837 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1840 /* so we know LEFT & RESULT in the same registers and add
1842 /* for short & char types */
1843 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1845 emitcode ("inc", "%s",
1846 aopGet (AOP (IC_LEFT (ic)), 0));
1849 emitcode ("subi", "%s,lo8(%d)",
1850 aopGet (AOP (IC_LEFT (ic)), 0), -icount);
1854 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1855 /* if register pair and starts with 26/30 then adiw */
1856 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1858 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
1859 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1860 emitcode ("adiw", "%s,%d",
1861 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1866 emitcode ("subi", "%s,lo8(%d)",
1867 aopGet (AOP (IC_RESULT (ic)), 0), -icount);
1868 emitcode ("sbci", "%s,hi8(%d)",
1869 aopGet (AOP (IC_RESULT (ic)), 1), -icount);
1873 /* for 32 bit longs */
1874 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1876 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1878 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1880 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1886 /* This is the pure and virtuous version of this code.
1887 * I'm pretty certain it's right, but not enough to toss the old
1891 adjustArithmeticResult (iCode * ic)
1893 if (opIsGptr (IC_RESULT (ic)) &&
1894 opIsGptr (IC_LEFT (ic)) &&
1895 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1896 aopPut (AOP (IC_RESULT (ic)),
1897 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1901 if (opIsGptr (IC_RESULT (ic)) &&
1902 opIsGptr (IC_RIGHT (ic)) &&
1903 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1904 aopPut (AOP (IC_RESULT (ic)),
1905 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1909 if (opIsGptr (IC_RESULT (ic)) &&
1910 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1911 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1912 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1913 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1915 sprintf (buffer, "%d",
1916 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
1917 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
1921 /*-----------------------------------------------------------------*/
1922 /* genPlus - generates code for addition */
1923 /*-----------------------------------------------------------------*/
1925 genPlus (iCode * ic)
1927 int size, offset = 0;
1931 /* special cases :- */
1933 aopOp (IC_LEFT (ic), ic, FALSE);
1934 aopOp (IC_RIGHT (ic), ic, FALSE);
1935 aopOp (IC_RESULT (ic), ic, TRUE);
1937 /* if I can do an increment instead
1938 of add then GOOD for ME */
1939 if (genPlusIncr (ic) == TRUE)
1942 size = getDataSize (IC_RESULT (ic));
1943 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
1947 aopPut (AOP (IC_RESULT (ic)),
1948 aopGet (AOP (IC_LEFT (ic)), offset), offset);
1950 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
1957 emitcode (l, "%s,%s",
1958 aopGet (AOP (IC_RESULT (ic)), offset),
1959 aopGet (AOP (IC_RIGHT (ic)), offset));
1967 emitcode (l, "%s,%s(-%d)",
1968 aopGet (AOP (IC_RESULT (ic)), offset),
1970 (int) floatFromVal (AOP (IC_RIGHT (ic))->
1976 adjustArithmeticResult (ic);
1979 freeAsmop (IC_LEFT (ic), NULL, ic,
1980 (RESULTONSTACK (ic) ? FALSE : TRUE));
1981 freeAsmop (IC_RIGHT (ic), NULL, ic,
1982 (RESULTONSTACK (ic) ? FALSE : TRUE));
1983 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1986 /*-----------------------------------------------------------------*/
1987 /* genMinusDec :- does subtraction with deccrement if possible */
1988 /*-----------------------------------------------------------------*/
1990 genMinusDec (iCode * ic)
1992 unsigned int icount;
1994 /* will try to generate an increment */
1995 /* if the right side is not a literal
1997 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2001 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2004 /* if the sizes are greater than 2 or they are not the same regs
2006 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2009 /* so we know LEFT & RESULT in the same registers and add
2011 /* for short & char types */
2012 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2014 emitcode ("dec", "%s",
2015 aopGet (AOP (IC_LEFT (ic)), 0));
2018 emitcode ("subi", "%s,lo8(%d)",
2019 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2023 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2024 /* if register pair and starts with 26/30 then adiw */
2025 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2027 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
2028 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2029 emitcode ("sbiw", "%s,%d",
2030 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2035 emitcode ("subi", "%s,lo8(%d)",
2036 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2037 emitcode ("sbci", "%s,hi8(%d)",
2038 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2041 /* for 32 bit longs */
2042 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2044 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2046 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2048 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2054 /*-----------------------------------------------------------------*/
2055 /* addSign - complete with sign */
2056 /*-----------------------------------------------------------------*/
2058 addSign (operand * result, int offset, int sign)
2060 int size = (getDataSize (result) - offset);
2063 emitcode ("rlc", "a");
2064 emitcode ("subb", "a,acc");
2066 aopPut (AOP (result), "a", offset++);
2070 aopPut (AOP (result), zero, offset++);
2074 /*-----------------------------------------------------------------*/
2075 /* genMinus - generates code for subtraction */
2076 /*-----------------------------------------------------------------*/
2078 genMinus (iCode * ic)
2080 int size, offset = 0, samer;
2083 aopOp (IC_LEFT (ic), ic, FALSE);
2084 aopOp (IC_RIGHT (ic), ic, FALSE);
2085 aopOp (IC_RESULT (ic), ic, TRUE);
2087 /* if I can do an decrement instead
2088 of subtract then GOOD for ME */
2089 if (genMinusDec (ic) == TRUE)
2092 size = getDataSize (IC_RESULT (ic));
2093 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2096 aopPut (AOP (IC_RESULT (ic)),
2097 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2099 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2106 emitcode (l, "%s,%s",
2107 aopGet (AOP (IC_RESULT (ic)), offset),
2108 aopGet (AOP (IC_RIGHT (ic)), offset));
2116 emitcode (l, "%s,%s(%d)",
2117 aopGet (AOP (IC_RESULT (ic)), offset),
2119 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2125 adjustArithmeticResult (ic);
2128 freeAsmop (IC_LEFT (ic), NULL, ic,
2129 (RESULTONSTACK (ic) ? FALSE : TRUE));
2130 freeAsmop (IC_RIGHT (ic), NULL, ic,
2131 (RESULTONSTACK (ic) ? FALSE : TRUE));
2132 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2135 /*-----------------------------------------------------------------*/
2136 /* genMultOneByte : 8 bit multiplication & division */
2137 /*-----------------------------------------------------------------*/
2139 genMultOneByte (operand * left, operand * right, operand * result)
2141 sym_link *opetype = operandType (result);
2145 /* (if two literals, the value is computed before) */
2146 /* if one literal, literal on the right */
2147 if (AOP_TYPE (left) == AOP_LIT) {
2153 size = AOP_SIZE (result);
2155 if (SPEC_USIGN (opetype)) {
2156 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2157 aopGet (AOP (right), 0));
2160 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2161 aopGet (AOP (right), 0));
2163 aopPut (AOP (result), "r0", 0);
2165 aopPut (AOP (result), "r1", 1);
2168 if (SPEC_USIGN (opetype)) {
2170 aopPut (AOP (result), zero, offset++);
2175 lbl = newiTempLabel (NULL);
2176 emitcode ("ldi", "r24,0");
2177 emitcode ("brcc", "L%05d", lbl->key);
2178 emitcode ("ldi", "r24,lo8(-1)");
2179 emitcode ("", "L%05d:", lbl->key);
2181 aopPut (AOP (result), "r24",
2189 /*-----------------------------------------------------------------*/
2190 /* genMult - generates code for multiplication */
2191 /*-----------------------------------------------------------------*/
2193 genMult (iCode * ic)
2195 operand *left = IC_LEFT (ic);
2196 operand *right = IC_RIGHT (ic);
2197 operand *result = IC_RESULT (ic);
2199 /* assign the amsops */
2200 aopOp (left, ic, FALSE);
2201 aopOp (right, ic, FALSE);
2202 aopOp (result, ic, TRUE);
2204 /* if both are of size == 1 */
2205 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2206 genMultOneByte (left, right, result);
2210 /* should have been converted to function call */
2214 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2215 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2216 freeAsmop (result, NULL, ic, TRUE);
2219 /*-----------------------------------------------------------------*/
2220 /* genDiv - generates code for division */
2221 /*-----------------------------------------------------------------*/
2225 /* should have been converted to function call */
2229 /*-----------------------------------------------------------------*/
2230 /* genMod - generates code for division */
2231 /*-----------------------------------------------------------------*/
2235 /* should have been converted to function call */
2247 /*-----------------------------------------------------------------*/
2248 /* revavrcnd - reverse a conditional for avr */
2249 /*-----------------------------------------------------------------*/
2251 revavrcnd (int type)
2263 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2264 if (rar[i].type == type)
2265 return rar[i].rtype;
2266 if (rar[i].rtype == type)
2269 assert (1); /* cannot happen */
2270 return 0; /* makes the compiler happy */
2273 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2274 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2276 /*-----------------------------------------------------------------*/
2277 /* genBranch - generate the branch instruction */
2278 /*-----------------------------------------------------------------*/
2280 genBranch (iCode * ifx, int br_type, int sign)
2282 int tj = (IC_TRUE (ifx) ? 1 : 0);
2284 if (tj) { /* if true jump */
2285 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2286 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2288 else { /* if false jump */
2289 int rtype = revavrcnd (br_type);
2290 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2291 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2296 /*-----------------------------------------------------------------*/
2297 /* genCmp - compare & jump */
2298 /*-----------------------------------------------------------------*/
2300 genCmp (iCode * ic, iCode * ifx, int br_type)
2302 operand *left, *right, *result;
2303 sym_link *letype, *retype;
2305 int sign, size, offset = 0;
2307 left = IC_LEFT (ic);
2308 right = IC_RIGHT (ic);
2309 result = IC_RESULT (ic);
2311 letype = getSpec (operandType (left));
2312 retype = getSpec (operandType (right));
2313 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2315 /* assign the amsops */
2316 aopOp (left, ic, FALSE);
2317 aopOp (right, ic, FALSE);
2318 aopOp (result, ic, TRUE);
2319 size = AOP_SIZE (left);
2323 if (AOP_TYPE (right) == AOP_LIT) {
2324 emitcode ("cpi", "%s,lo8(%d)",
2325 aopGet (AOP (left), 0),
2327 floatFromVal (AOP (IC_RIGHT (ic))->
2329 genBranch (ifx, br_type, sign);
2331 else { /* right != literal */
2332 emitcode ("cp", "%s,%s",
2333 aopGet (AOP (left), 0),
2334 aopGet (AOP (right), 0));
2335 genBranch (ifx, br_type, sign);
2338 else { /* size != 1 */
2341 emitcode ("cp", "%s,%s",
2342 aopGet (AOP (left), 0),
2343 aopGet (AOP (right), 0));
2345 emitcode ("cpc", "%s,%s",
2346 aopGet (AOP (left), offset),
2347 aopGet (AOP (right),
2351 genBranch (ifx, br_type, sign);
2355 emitcode ("clr", "r0");
2358 emitcode ("cp", "%s,%s",
2359 aopGet (AOP (left), 0),
2360 aopGet (AOP (right), 0));
2362 emitcode ("cpc", "%s,%s",
2363 aopGet (AOP (left), offset),
2364 aopGet (AOP (right), offset));
2367 lbl = newiTempLabel (NULL);
2368 br_type = revavrcnd (br_type);
2370 emitcode (br_uname[br_type], "L%05d", lbl->key);
2372 emitcode (br_name[br_type], "L%05d", lbl->key);
2373 emitcode ("inc", "r0");
2374 emitcode ("", "L%05d:", lbl->key);
2375 aopPut (AOP (result), "r0", 0);
2376 size = AOP_SIZE (result) - 1;
2379 aopPut (AOP (result), zero, offset++);
2382 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2383 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2384 freeAsmop (result, NULL, ic, TRUE);
2387 /*-----------------------------------------------------------------*/
2388 /* genCmpGt :- greater than comparison */
2389 /*-----------------------------------------------------------------*/
2391 genCmpGt (iCode * ic, iCode * ifx)
2393 /* should have transformed by the parser */
2397 /*-----------------------------------------------------------------*/
2398 /* genCmpLt - less than comparisons */
2399 /*-----------------------------------------------------------------*/
2401 genCmpLt (iCode * ic, iCode * ifx)
2403 genCmp (ic, ifx, AVR_LT);
2406 /*-----------------------------------------------------------------*/
2407 /* genCmpEq - generates code for equal to */
2408 /*-----------------------------------------------------------------*/
2410 genCmpEq (iCode * ic, iCode * ifx)
2412 genCmp (ic, ifx, AVR_EQ);
2415 /*-----------------------------------------------------------------*/
2416 /* genCmpNe - generates code for not equal to */
2417 /*-----------------------------------------------------------------*/
2419 genCmpNe (iCode * ic, iCode * ifx)
2421 genCmp (ic, ifx, AVR_NE);
2424 /*-----------------------------------------------------------------*/
2425 /* genCmpGe - generates code for greater than equal to */
2426 /*-----------------------------------------------------------------*/
2428 genCmpGe (iCode * ic, iCode * ifx)
2430 genCmp (ic, ifx, AVR_GE);
2433 /*-----------------------------------------------------------------*/
2434 /* genCmpLe - generates code for less than equal to */
2435 /*-----------------------------------------------------------------*/
2437 genCmpLe (iCode * ic, iCode * ifx)
2439 operand *left = IC_LEFT (ic);
2440 operand *right = IC_RIGHT (ic);
2442 IC_RIGHT (ic) = left;
2443 IC_LEFT (ic) = right;
2444 genCmp (ic, ifx, AVR_GE);
2447 /*-----------------------------------------------------------------*/
2448 /* ifxForOp - returns the icode containing the ifx for operand */
2449 /*-----------------------------------------------------------------*/
2451 ifxForOp (operand * op, iCode * ic)
2453 /* if true symbol then needs to be assigned */
2454 if (IS_TRUE_SYMOP (op))
2457 /* if this has register type condition and
2458 the next instruction is ifx with the same operand
2459 and live to of the operand is upto the ifx only then */
2461 ic->next->op == IFX &&
2462 IC_COND (ic->next)->key == op->key &&
2463 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2468 /*-----------------------------------------------------------------*/
2469 /* genAndOp - for && operation */
2470 /*-----------------------------------------------------------------*/
2472 genAndOp (iCode * ic)
2474 operand *left, *right, *result;
2478 /* note here that && operations that are in an
2479 if statement are taken away by backPatchLabels
2480 only those used in arthmetic operations remain */
2481 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2482 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2483 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2485 tlbl = newiTempLabel (NULL);
2486 toBoolean (left, "r0", TRUE);
2487 toBoolean (right, "r1", TRUE);
2488 emitcode ("and", "r0,r1");
2489 emitcode ("ldi", "r24,1");
2490 emitcode ("breq", "L%05d", tlbl->key);
2491 emitcode ("dec", "r24");
2492 emitcode ("", "L%05d:", tlbl->key);
2493 aopPut (AOP (result), "r24", 0);
2494 size = AOP_SIZE (result) - 1;
2497 aopPut (AOP (result), zero, offset++);
2499 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2500 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2501 freeAsmop (result, NULL, ic, TRUE);
2505 /*-----------------------------------------------------------------*/
2506 /* genOrOp - for || operation */
2507 /*-----------------------------------------------------------------*/
2509 genOrOp (iCode * ic)
2511 operand *left, *right, *result;
2515 /* note here that || operations that are in an
2516 if statement are taken away by backPatchLabels
2517 only those used in arthmetic operations remain */
2518 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2519 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2520 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2522 tlbl = newiTempLabel (NULL);
2523 toBoolean (left, "r0", TRUE);
2524 toBoolean (right, "r0", FALSE);
2525 emitcode ("ldi", "r24,1");
2526 emitcode ("breq", "L%05d", tlbl->key);
2527 emitcode ("dec", "r24");
2528 emitcode ("", "L%05d:", tlbl->key);
2529 aopPut (AOP (result), "r24", 0);
2530 size = AOP_SIZE (result) - 1;
2533 aopPut (AOP (result), zero, offset++);
2535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2536 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2537 freeAsmop (result, NULL, ic, TRUE);
2540 /*-----------------------------------------------------------------*/
2541 /* isLiteralBit - test if lit == 2^n */
2542 /*-----------------------------------------------------------------*/
2544 isLiteralBit (unsigned long lit)
2546 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
2547 0x100L, 0x200L, 0x400L, 0x800L,
2548 0x1000L, 0x2000L, 0x4000L, 0x8000L,
2549 0x10000L, 0x20000L, 0x40000L, 0x80000L,
2550 0x100000L, 0x200000L, 0x400000L, 0x800000L,
2551 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
2552 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
2556 for (idx = 0; idx < 32; idx++)
2563 AVR_AND = 0, AVR_OR, AVR_XOR
2565 static char *bopnames_lit[] = { "andi", "ori" };
2566 static char *bopnames[] = { "and", "or", "eor" };
2567 /*-----------------------------------------------------------------*/
2568 /* genBitWise - generate bitwise operations */
2569 /*-----------------------------------------------------------------*/
2571 genBitWise (iCode * ic, iCode * ifx, int bitop)
2573 operand *left, *right, *result;
2574 int size, offset = 0;
2579 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2580 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2581 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2583 size = AOP_SIZE (left);
2585 if (ifx) { /* used only for jumps */
2586 if (AOP_TYPE (right) == AOP_LIT &&
2587 (bitop == AVR_AND || bitop == AVR_OR)) {
2589 (int) floatFromVal (AOP (right)->aopu.
2591 int p2 = powof2 (lit);
2592 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2593 l = aopGet (AOP (left), p2 / 8);
2594 if (IC_TRUE (ifx)) {
2595 emitcode ("sbrc", "%s,%d", l,
2597 emitcode ("rjmp", "L%05d",
2598 IC_TRUE (ifx)->key);
2601 emitcode ("sbrs", "%s,%d", l,
2603 emitcode ("rjmp", "L%05d",
2604 IC_FALSE (ifx)->key);
2607 else { /* right not power of two */
2608 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2610 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2611 emitcode (bopnames_lit[bitop],
2613 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2616 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2617 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2619 lbl = newiTempLabel (NULL);
2620 if (IC_TRUE (ifx)) {
2621 emitcode ("breq", "L%05d", lbl->key);
2622 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2625 emitcode ("brne", "L%05d", lbl->key);
2626 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2628 emitcode ("", "L%05d:", lbl->key);
2630 else if (size == 2) {
2631 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2632 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2633 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2634 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2635 emitcode ("sbiw", "r24,0");
2636 lbl = newiTempLabel (NULL);
2637 if (IC_TRUE (ifx)) {
2638 emitcode ("breq", "L%05d", lbl->key);
2639 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2642 emitcode ("brne", "L%05d", lbl->key);
2643 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2645 emitcode ("", "L%05d:", lbl->key);
2648 lbl = newiTempLabel (NULL);
2649 lbl1 = newiTempLabel (NULL);
2651 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2652 emitcode (bopnames_lit [bitop], "%s,lo8(%d)",
2653 aopGet (AOP (IC_LEFT (ic)), offset),
2657 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2659 emitcode ("andi", "r24,lo8(%d)", lit);
2661 emitcode ("brne", "L%05d", lbl->key);
2666 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2668 emitcode ("rjmp", "L%05d", lbl1->key);
2669 emitcode ("", "L%05d:", lbl->key);
2672 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2673 emitcode ("", "L%05d:", lbl1->key);
2678 else { /* right is not a literal */
2679 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2680 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2683 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2684 aopGet (AOP (IC_RIGHT (ic)), 0));
2687 emitcode (bopnames[bitop], "%s,%s",
2688 aopGet (AOP (IC_RIGHT (ic)), 0),
2689 aopGet (AOP (IC_LEFT (ic)), 0));
2692 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2693 emitcode (bopnames[bitop], "r0,%s",
2694 aopGet (AOP (IC_RIGHT (ic)), 0));
2696 lbl = newiTempLabel (NULL);
2697 if (IC_TRUE (ifx)) {
2698 emitcode ("breq", "L%05d", lbl->key);
2699 emitcode ("rjmp", "L%05d",
2700 IC_TRUE (ifx)->key);
2703 emitcode ("brne", "L%05d", lbl->key);
2704 emitcode ("rjmp", "L%05d",
2705 IC_FALSE (ifx)->key);
2707 emitcode ("", "L%05d:", lbl->key);
2709 else if (size == 2) {
2710 emitcode ("mov", "r24,%s",
2711 aopGet (AOP (IC_LEFT (ic)), 0));
2712 emitcode ("mov", "r25,%s",
2713 aopGet (AOP (IC_LEFT (ic)), 1));
2714 emitcode (bopnames[bitop], "r24,%s",
2715 aopGet (AOP (IC_RIGHT (ic)), 0));
2716 emitcode (bopnames[bitop], "r25,%s",
2717 aopGet (AOP (IC_RIGHT (ic)), 1));
2718 emitcode ("sbiw", "r24,0");
2719 lbl = newiTempLabel (NULL);
2720 if (IC_TRUE (ifx)) {
2721 emitcode ("breq", "L%05d", lbl->key);
2722 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2725 emitcode ("brne", "L%05d", lbl->key);
2726 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2728 emitcode ("", "L%05d:", lbl->key);
2731 lbl = newiTempLabel (NULL);
2732 lbl1 = newiTempLabel (NULL);
2735 emitcode (bopnames[bitop], "%s,%s",
2736 aopGet (AOP (IC_LEFT (ic)), offset),
2737 aopGet (AOP (IC_RIGHT (ic)), offset));
2740 emitcode (bopnames[bitop], "%s,%s",
2741 aopGet (AOP (IC_RIGHT (ic)), offset),
2742 aopGet (AOP (IC_LEFT (ic)), offset));
2745 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2746 emitcode (bopnames[bitop], "r0,%s",
2747 aopGet (AOP (IC_RIGHT (ic)), offset));
2749 emitcode ("brne", "L%05d", lbl->key);
2754 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2756 emitcode ("rjmp", "L%05d", lbl1->key);
2757 emitcode ("", "L%05d:", lbl->key);
2760 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2761 emitcode ("", "L%05d:", lbl1->key);
2768 /* result needs to go a register */
2769 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2770 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2772 if (AOP_TYPE (right) == AOP_LIT) {
2774 (int) floatFromVal (AOP (right)->aopu.
2776 if (((lit >> (8 * offset)) & 0xff) == 0) {
2777 if (bitop == AVR_AND) {
2778 aopPut (AOP (result), zero, offset++);
2781 else if (bitop == AVR_OR) {
2783 aopPut (AOP (result),
2793 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2794 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2795 (bitop == AVR_AND || bitop == AVR_OR)) {
2796 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2797 aopGet (AOP (IC_LEFT (ic)), offset),
2799 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2802 emitcode (bopnames[bitop], "%s,%s",
2803 aopGet (AOP (IC_LEFT (ic)), offset),
2804 aopGet (AOP (IC_RIGHT (ic)), offset));
2808 emitcode (bopnames[bitop], "%s,%s",
2809 aopGet (AOP (IC_RIGHT (ic)), offset),
2810 aopGet (AOP (IC_LEFT (ic)), offset));
2813 aopPut (AOP (IC_RESULT (ic)),
2814 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2815 emitcode (bopnames[bitop],
2816 aopGet (AOP (IC_RESULT (ic)), offset),
2817 aopGet (AOP (IC_RIGHT (ic)), offset));
2822 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2823 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2824 freeAsmop (result, NULL, ic, TRUE);
2827 /*-----------------------------------------------------------------*/
2828 /* genAnd - code for and */
2829 /*-----------------------------------------------------------------*/
2831 genAnd (iCode * ic, iCode * ifx)
2833 genBitWise (ic, ifx, AVR_AND);
2836 /*-----------------------------------------------------------------*/
2837 /* genOr - code for or */
2838 /*-----------------------------------------------------------------*/
2840 genOr (iCode * ic, iCode * ifx)
2842 genBitWise (ic, ifx, AVR_OR);
2845 /*-----------------------------------------------------------------*/
2846 /* genXor - code for xclusive or */
2847 /*-----------------------------------------------------------------*/
2849 genXor (iCode * ic, iCode * ifx)
2851 genBitWise (ic, ifx, AVR_XOR);
2854 /*-----------------------------------------------------------------*/
2855 /* genInline - write the inline code out */
2856 /*-----------------------------------------------------------------*/
2858 genInline (iCode * ic)
2860 char buffer[MAX_INLINEASM];
2864 _G.inLine += (!options.asmpeep);
2865 strcpy (buffer, IC_INLINE (ic));
2867 /* emit each line as a code */
2888 /* emitcode("",buffer); */
2889 _G.inLine -= (!options.asmpeep);
2892 /*-----------------------------------------------------------------*/
2893 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2894 /*-----------------------------------------------------------------*/
2896 genRotC (iCode * ic, int lr)
2898 operand *left, *result;
2899 int size, offset = 0;
2901 /* rotate right with carry */
2902 left = IC_LEFT (ic);
2903 result = IC_RESULT (ic);
2904 aopOp (left, ic, FALSE);
2905 aopOp (result, ic, FALSE);
2907 /* move it to the result */
2908 size = AOP_SIZE (result);
2909 if (!sameRegs (AOP (left), AOP (result))) {
2912 aopPut (AOP (result),
2913 aopGet (AOP (left), offset), offset);
2916 size = AOP_SIZE (result);
2924 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
2926 emitcode ("sec", "");
2929 emitcode ((lr ? "ror" : "rol"), "%s",
2930 aopGet (AOP (result), offset));
2936 freeAsmop (left, NULL, ic, TRUE);
2937 freeAsmop (result, NULL, ic, TRUE);
2940 /*-----------------------------------------------------------------*/
2941 /* genRRC - rotate right with carry */
2942 /*-----------------------------------------------------------------*/
2949 /*-----------------------------------------------------------------*/
2950 /* genRLC - generate code for rotate left with carry */
2951 /*-----------------------------------------------------------------*/
2958 /*-----------------------------------------------------------------*/
2959 /* genGetHbit - generates code get highest order bit */
2960 /*-----------------------------------------------------------------*/
2962 genGetHbit (iCode * ic)
2964 operand *left, *result;
2967 left = IC_LEFT (ic);
2968 result = IC_RESULT (ic);
2969 aopOp (left, ic, FALSE);
2970 aopOp (result, ic, FALSE);
2972 size = AOP_SIZE (result);
2973 if (!sameRegs (AOP (left), AOP (result))) {
2974 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
2975 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
2976 emitcode ("subi", "%s,lo8(-1)",
2977 aopGet (AOP (result), size - 1));
2980 emitcode ("clr", "r0");
2981 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
2982 emitcode ("subi", "r0,lo8(-1)");
2983 aopPut (AOP (result), "r0", 0);
2988 emitcode ("clr", aopGet (AOP (result), offset++));
2990 freeAsmop (left, NULL, ic, TRUE);
2991 freeAsmop (result, NULL, ic, TRUE);
2994 /*-----------------------------------------------------------------*/
2995 /* genShiftLeftLit - shift left by a known amount */
2996 /*-----------------------------------------------------------------*/
2998 genShiftLeftLit (iCode * ic)
3000 operand *left, *right, *result;
3001 int size, shCount, offset = 0;
3004 right = IC_RIGHT (ic);
3005 left = IC_LEFT (ic);
3006 result = IC_RESULT (ic);
3008 aopOp (left, ic, FALSE);
3009 aopOp (result, ic, FALSE);
3010 size = AOP_SIZE (result);
3011 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3013 if (shCount > (size * 8 - 1)) {
3015 aopPut (AOP (result), zero, offset++);
3020 if (!sameRegs (AOP (left), AOP (result)))
3021 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3023 if (AOP_ISHIGHREG(AOP(result),0)) {
3024 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3025 emitcode ("andi", "%s,0xf0");
3027 emitcode ("ldi","r24,0xf0");
3028 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3029 emitcode ("and", "%s,r24");
3034 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3035 aopGet (AOP (result), 0));
3039 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3042 if (shCount >= 12) {
3043 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3044 aopPut (AOP (result), zero, 0);
3045 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3046 if (AOP_ISHIGHREG(AOP(result),1)) {
3047 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3049 emitcode ("ldi","r24,0xf0");
3050 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3056 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3057 aopPut (AOP (result), zero, 0);
3063 if (!sameRegs (AOP (left), AOP (result))) {
3064 aopPut (AOP (result), aopGet (AOP (left), 0),
3066 aopPut (AOP (result), aopGet (AOP (left), 1),
3069 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3070 emitcode ("andi", "r24,0x0f");
3071 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3072 emitcode("ldi","r25,0xf0");
3074 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3075 if (AOP_ISHIGHREG(AOP(result),0)) {
3076 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3078 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3080 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3081 if (AOP_ISHIGHREG(AOP(result),1)) {
3082 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3084 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3086 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3088 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3089 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3092 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3096 aopPut (AOP (result),
3097 aopGet (AOP (left), offset), offset);
3103 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3106 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3107 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3112 assert ("shifting generic pointer ?\n");
3115 /* 32 bits we do only byte boundaries */
3116 if (shCount >= 24) {
3117 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3118 aopPut (AOP (result), zero, 2);
3119 aopPut (AOP (result), zero, 1);
3120 aopPut (AOP (result), zero, 0);
3124 if (shCount >= 16) {
3125 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3126 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3127 aopPut (AOP (result), zero, 1);
3128 aopPut (AOP (result), zero, 0);
3133 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3134 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3135 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3136 aopPut (AOP (result), zero, 0);
3140 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3143 aopPut (AOP (result),
3144 aopGet (AOP (left), offset), offset);
3148 size = AOP_SIZE (result);
3154 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3155 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3156 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3157 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3162 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3163 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3164 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3169 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3170 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3175 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3183 freeAsmop (left, NULL, ic, TRUE);
3184 freeAsmop (right, NULL, ic, TRUE);
3185 freeAsmop (result, NULL, ic, TRUE);
3188 /*-----------------------------------------------------------------*/
3189 /* genLeftShift - generates code for left shifting */
3190 /*-----------------------------------------------------------------*/
3192 genLeftShift (iCode * ic)
3194 operand *left, *right, *result;
3198 right = IC_RIGHT (ic);
3199 left = IC_LEFT (ic);
3200 result = IC_RESULT (ic);
3202 aopOp (right, ic, FALSE);
3204 if (AOP_TYPE (right) == AOP_LIT) {
3205 genShiftLeftLit (ic);
3210 aopOp (left, ic, FALSE);
3211 aopOp (result, ic, FALSE);
3212 size = AOP_SIZE (result);
3214 if (AOP_SIZE (right) > 1) {
3215 if (isRegPair (AOP (right))) {
3216 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3219 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3220 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3224 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3226 if (!sameRegs (AOP (left), AOP (result))) {
3228 aopPut (AOP (result), aopGet (AOP (left), offset),
3232 size = AOP_SIZE (result);
3234 tlbl = newiTempLabel (NULL);
3235 emitcode ("", "L%05d:", tlbl->key);
3239 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3241 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3244 if (AOP_SIZE (right) > 1)
3245 emitcode ("sbiw", "r24,1");
3247 emitcode ("dec", "r24");
3248 emitcode ("brne", "L%05d", tlbl->key);
3250 freeAsmop (left, NULL, ic, TRUE);
3251 freeAsmop (right, NULL, ic, TRUE);
3252 freeAsmop (result, NULL, ic, TRUE);
3255 /*-----------------------------------------------------------------*/
3256 /* genShiftRightLit - generate for right shift with known count */
3257 /*-----------------------------------------------------------------*/
3259 genShiftRightLit (iCode * ic)
3261 operand *left = IC_LEFT (ic)
3262 , *right = IC_RIGHT (ic)
3263 , *result = IC_RESULT (ic);
3264 int size, shCount, offset = 0;
3266 sym_link *letype = getSpec (operandType (left));
3267 int sign = !SPEC_USIGN (letype);
3269 right = IC_RIGHT (ic);
3270 left = IC_LEFT (ic);
3271 result = IC_RESULT (ic);
3273 aopOp (left, ic, FALSE);
3274 aopOp (result, ic, FALSE);
3275 size = AOP_SIZE (result);
3276 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3278 /* if signed then give up and use a loop to shift */
3281 if (!sameRegs (AOP (left), AOP (result))) {
3283 aopPut (AOP (result),
3284 aopGet (AOP (left), offset), offset);
3287 size = size = AOP_SIZE (result);
3290 /* be as economical as possible */
3295 size = AOP_SIZE (result);
3297 if (offset == (size - 1))
3298 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3300 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3306 emitcode ("ldi", "r24,lo8(%d)", shCount);
3307 tlbl = newiTempLabel (NULL);
3308 emitcode ("", "L%05d:", tlbl->key);
3311 if (offset == (size - 1))
3312 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3314 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3317 emitcode ("dec", "r24");
3318 emitcode ("brne", "L%05d", tlbl->key);
3322 if (shCount > (size * 8 - 1)) {
3324 aopPut (AOP (result), zero, offset++);
3327 /* for unsigned we can much more efficient */
3330 if (!sameRegs (AOP (left), AOP (result)))
3331 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3333 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3334 if (AOP_ISHIGHREG(AOP(result),0)) {
3335 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3337 emitcode ("ldi","r24,0x0f");
3338 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3343 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3346 if (shCount >= 12) {
3347 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3348 aopPut (AOP (result), zero, 1);
3349 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3350 if (AOP_ISHIGHREG(AOP(result),0)) {
3351 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3353 emitcode ("ldi","r24,0x0f");
3354 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3360 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3361 aopPut (AOP (result), zero, 1);
3367 if (!sameRegs (AOP (left), AOP (result))) {
3368 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3369 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3371 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3372 emitcode("ldi","r25,0x0f");
3374 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3375 emitcode ("andi", "r24,0xf0");
3376 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3377 if (AOP_ISHIGHREG(AOP(result),0)) {
3378 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3380 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3382 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3383 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3384 if (AOP_ISHIGHREG(AOP(result),1)) {
3385 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3387 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3390 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3391 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3395 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3399 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3405 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3408 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3409 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3415 assert ("shifting generic pointer ?\n");
3418 /* 32 bits we do only byte boundaries */
3419 if (shCount >= 24) {
3420 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3421 aopPut (AOP (result), zero, 1);
3422 aopPut (AOP (result), zero, 2);
3423 aopPut (AOP (result), zero, 3);
3427 if (shCount >= 16) {
3428 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3429 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3430 aopPut (AOP (result), zero, 2);
3431 aopPut (AOP (result), zero, 3);
3436 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3437 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3438 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3439 aopPut (AOP (result), zero, 3);
3443 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3446 aopPut (AOP (result),
3447 aopGet (AOP (left), offset), offset);
3451 size = AOP_SIZE (result);
3457 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3458 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3459 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3460 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3465 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3466 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3467 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3472 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3473 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3478 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3485 freeAsmop (left, NULL, ic, TRUE);
3486 freeAsmop (right, NULL, ic, TRUE);
3487 freeAsmop (result, NULL, ic, TRUE);
3490 /*-----------------------------------------------------------------*/
3491 /* genRightShift - generate code for right shifting */
3492 /*-----------------------------------------------------------------*/
3494 genRightShift (iCode * ic)
3496 operand *right, *left, *result;
3499 int sign = 0, first = 1;
3502 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3504 if (AOP_TYPE (right) == AOP_LIT) {
3505 genShiftRightLit (ic);
3509 if (AOP_SIZE (right) > 1) {
3510 if (isRegPair (AOP (right))) {
3511 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3514 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3515 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3519 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3521 aopOp (left = IC_LEFT (ic), ic, FALSE);
3522 aopOp (result = IC_RESULT (ic), ic, FALSE);
3523 size = AOP_SIZE (result);
3524 tlbl = newiTempLabel (NULL);
3525 emitcode ("", "L%05d:", tlbl->key);
3527 letype = getSpec (operandType (left));
3528 sign = !SPEC_USIGN (letype);
3529 if (!sameRegs (AOP (left), AOP (result))) {
3531 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3534 size = AOP_SIZE (result);
3536 size = AOP_SIZE (result);
3540 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3542 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3546 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3549 if (AOP_SIZE (right) > 1)
3550 emitcode ("sbiw", "r24,1");
3552 emitcode ("dec", "r24");
3553 emitcode ("brne", "L%05d", tlbl->key);
3555 freeAsmop (left, NULL, ic, TRUE);
3556 freeAsmop (result, NULL, ic, TRUE);
3559 /*-----------------------------------------------------------------*/
3560 /* RRsh - shift right rn by known count */
3561 /*-----------------------------------------------------------------*/
3563 RRsh (int shCount,int reg)
3565 shCount &= 0x0007; // shCount : 0..7
3571 emitcode ("lsr", "r%d",reg);
3574 emitcode ("lsr", "r%d",reg);
3575 emitcode ("lsr", "r%d",reg);
3578 emitcode ("swap", "r%d",reg);
3579 emitcode ("lsl", "r%d",reg);
3582 emitcode ("swap", "r%d",reg);
3585 emitcode ("swap", "r%d",reg);
3586 emitcode ("lsr", "r%d",reg);
3589 emitcode ("swap","r%d",reg);
3590 emitcode ("lsr", "r%d",reg);
3591 emitcode ("lsr", "r%d",reg);
3594 emitcode ("swap","r%d",reg);
3595 emitcode ("lsr", "r%d",reg);
3596 emitcode ("lsr", "r%d",reg);
3597 emitcode ("lsr", "r%d",reg);
3602 /*-----------------------------------------------------------------*/
3603 /* RLsh - shift left rn by known count */
3604 /*-----------------------------------------------------------------*/
3606 RLsh (int shCount, int reg)
3608 shCount &= 0x0007; // shCount : 0..7
3614 emitcode ("lsl", "r%d",reg);
3617 emitcode ("lsl", "r%d",reg);
3618 emitcode ("lsl", "r%d",reg);
3621 emitcode ("swap","r%d",reg);
3622 emitcode ("lsr", "r%d",reg);
3625 emitcode ("swap", "r%d",reg);
3628 emitcode ("swap","r%d",reg);
3629 emitcode ("lsl", "r%d",reg);
3632 emitcode ("swap","r%d",reg);
3633 emitcode ("lsl", "r%d",reg);
3634 emitcode ("lsl", "r%d",reg);
3637 emitcode ("swap","r%d",reg);
3638 emitcode ("lsl", "r%d",reg);
3639 emitcode ("lsl", "r%d",reg);
3640 emitcode ("lsl", "r%d",reg);
3645 /*-----------------------------------------------------------------*/
3646 /* genUnpackBits - generates code for unpacking bits */
3647 /*-----------------------------------------------------------------*/
3649 genUnpackBits (operand * result, char *rname, int ptype)
3657 etype = getSpec (operandType (result));
3658 rsize = getSize (operandType (result));
3659 /* read the first byte */
3666 emitcode ("ld", "r24,%s+", rname);
3670 emitcode ("lpm", "r24,%s+", rname);
3674 emitcode ("call","__gptrget_pi");
3675 emitcode ("mov","r24,r0");
3679 rlen = SPEC_BLEN (etype);
3681 /* if we have bitdisplacement then it fits */
3682 /* into this byte completely or if length is */
3683 /* less than a byte */
3684 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3686 /* shift right acc */
3689 emitcode ("andi", "r24,lo(0x%x)",
3690 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3691 aopPut (AOP (result), "r24", offset++);
3695 /* bit field did not fit in a byte */
3696 aopPut (AOP (result), "r24", offset++);
3706 emitcode ("ld", "r24,%s+");
3710 emitcode ("lpm", "r24,%s+");
3714 emitcode ("call", "__gptrget_pi");
3719 /* if we are done */
3723 aopPut (AOP (result), "r24", offset++);
3728 aopPut (AOP (result), "r24", offset++);
3732 if (offset < rsize) {
3735 aopPut (AOP (result), zero, offset++);
3740 /*-----------------------------------------------------------------*/
3741 /* genDataPointerGet - generates code when ptr offset is known */
3742 /*-----------------------------------------------------------------*/
3744 genDataPointerGet (operand * left, operand * result, iCode * ic)
3748 int size, offset = 0;
3749 aopOp (result, ic, TRUE);
3751 /* get the string representation of the name */
3752 l = aopGet (AOP (left), 0);
3753 size = AOP_SIZE (result);
3756 sprintf (buffer, "(%s + %d)", l, offset);
3758 sprintf (buffer, "%s", l);
3759 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3763 freeAsmop (left, NULL, ic, TRUE);
3764 freeAsmop (result, NULL, ic, TRUE);
3767 /*-----------------------------------------------------------------*/
3768 /* genNearPointerGet - emitcode for near pointer fetch */
3769 /*-----------------------------------------------------------------*/
3771 genMemPointerGet (operand * left, operand * result, iCode * ic)
3776 char *rname, *frname = NULL;
3777 sym_link *rtype, *retype;
3778 sym_link *ltype = operandType (left);
3780 rtype = operandType (result);
3781 retype = getSpec (rtype);
3783 aopOp (left, ic, FALSE);
3785 /* if left is rematerialisable and
3786 result is not bit variable type and
3787 the left is pointer to data space i.e
3788 lower 128 bytes of space */
3789 if (AOP_TYPE (left) == AOP_IMMD &&
3790 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3791 genDataPointerGet (left, result, ic);
3795 /* if the value is already in a pointer register
3796 then don't need anything more */
3797 if (!AOP_INPREG (AOP (left))) {
3798 /* otherwise get a free pointer register */
3800 preg = getFreePtr (ic, &aop, FALSE, 0);
3801 if (isRegPair (AOP (left) )) {
3802 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name);
3804 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3805 aopGet (AOP (left), 0));
3806 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3807 aopGet (AOP (left), 1));
3813 frname = aopGet(aop,0);
3817 } else if (AOP_ISZ(aop)) {
3820 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3821 "pointer not in correct register");
3825 freeAsmop (left, NULL, ic, TRUE);
3826 aopOp (result, ic, FALSE);
3828 /* if bitfield then unpack the bits */
3829 if (IS_BITVAR (retype))
3830 genUnpackBits (result, rname, POINTER);
3832 /* we have can just get the values */
3833 int size = AOP_SIZE (result);
3838 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3840 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3845 /* now some housekeeping stuff */
3847 /* we had to allocate for this iCode */
3848 freeAsmop (NULL, aop, ic, TRUE);
3851 /* we did not allocate which means left
3852 already in a pointer register, then
3853 if size > 0 && this could be used again
3854 we have to point it back to where it
3856 if (AOP_SIZE (result) > 1 &&
3857 !OP_SYMBOL (left)->remat &&
3858 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
3859 int size = AOP_SIZE (result) - 1;
3860 emitcode ("sbiw", "%s,%d",frname,size);
3865 freeAsmop (result, NULL, ic, TRUE);
3869 /*-----------------------------------------------------------------*/
3870 /* genCodePointerGet - gget value from code space */
3871 /*-----------------------------------------------------------------*/
3873 genCodePointerGet (operand * left, operand * result, iCode * ic)
3876 sym_link *retype = getSpec (operandType (result));
3880 aopOp (left, ic, FALSE);
3882 /* if the operand is already in Z register
3883 then we do nothing else we move the value to Z register */
3884 if (AOP_ISZ(AOP(left))) {
3888 getFreePtr(ic,&aop,FALSE,TRUE);
3889 if (isRegPair(AOP (left))) {
3890 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3892 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3893 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3898 aopOp (result, ic, FALSE);
3900 /* if bit then unpack */
3901 if (IS_BITVAR (retype))
3902 genUnpackBits (result, "Z", CPOINTER);
3904 size = AOP_SIZE (result);
3909 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
3911 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
3916 freeAsmop (left, NULL, ic, TRUE);
3917 /* now some housekeeping stuff */
3919 /* we had to allocate for this iCode */
3920 freeAsmop (NULL, aop, ic, TRUE);
3923 /* we did not allocate which means left
3924 already in a pointer register, then
3925 if size > 0 && this could be used again
3926 we have to point it back to where it
3928 if (AOP_SIZE (result) > 1 &&
3929 !OP_SYMBOL (left)->remat &&
3930 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
3931 int size = AOP_SIZE (result) - 1;
3932 emitcode ("sbiw", "r30,%d",size);
3937 freeAsmop (result, NULL, ic, TRUE);
3941 /*-----------------------------------------------------------------*/
3942 /* genGenPointerGet - gget value from generic pointer space */
3943 /*-----------------------------------------------------------------*/
3945 genGenPointerGet (operand * left, operand * result, iCode * ic)
3949 sym_link *retype = getSpec (operandType (result));
3952 aopOp (left, ic, FALSE);
3954 /* if the operand is already in dptr
3955 then we do nothing else we move the value to dptr */
3956 if (AOP_ISZ(AOP(left))) {
3960 getFreePtr(ic,&aop,FALSE,TRUE);
3962 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3963 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3964 emitcode ("mov", "r0,%s", aopGet (AOP (left), 2));
3968 /* so Z register now contains the address */
3970 aopOp (result, ic, FALSE);
3972 /* if bit then unpack */
3973 if (IS_BITVAR (retype))
3974 genUnpackBits (result, "Z", GPOINTER);
3976 size = AOP_SIZE (result);
3981 emitcode ("call", "__gptrget_pi");
3983 emitcode ("call", "__gptrget");
3984 aopPut (AOP (result), "r0", offset++);
3988 freeAsmop (left, NULL, ic, TRUE);
3989 /* now some housekeeping stuff */
3991 /* we had to allocate for this iCode */
3992 freeAsmop (NULL, aop, ic, TRUE);
3995 /* we did not allocate which means left
3996 already in a pointer register, then
3997 if size > 0 && this could be used again
3998 we have to point it back to where it
4000 if (AOP_SIZE (result) > 1 &&
4001 !OP_SYMBOL (left)->remat &&
4002 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
4003 int size = AOP_SIZE (result) - 1;
4004 emitcode ("sbiw", "r30,%d",size);
4007 freeAsmop (result, NULL, ic, TRUE);
4010 /*-----------------------------------------------------------------*/
4011 /* genPointerGet - generate code for pointer get */
4012 /*-----------------------------------------------------------------*/
4014 genPointerGet (iCode * ic)
4016 operand *left, *result;
4017 sym_link *type, *etype;
4020 left = IC_LEFT (ic);
4021 result = IC_RESULT (ic);
4023 /* depending on the type of pointer we need to
4024 move it to the correct pointer register */
4025 type = operandType (left);
4026 etype = getSpec (type);
4027 /* if left is of type of pointer then it is simple */
4028 if (IS_PTR (type) && !IS_FUNC (type->next))
4029 p_type = DCL_TYPE (type);
4031 /* we have to go by the storage class */
4032 p_type = PTR_TYPE (SPEC_OCLS (etype));
4037 /* now that we have the pointer type we assign
4038 the pointer values */
4045 genMemPointerGet (left, result, ic);
4049 genCodePointerGet (left, result, ic);
4053 genGenPointerGet (left, result, ic);
4059 /*-----------------------------------------------------------------*/
4060 /* genPackBits - generates code for packed bit storage */
4061 /*-----------------------------------------------------------------*/
4063 genPackBits (sym_link * etype,
4065 char *rname, int p_type)
4073 blen = SPEC_BLEN (etype);
4074 bstr = SPEC_BSTR (etype);
4076 l = aopGet (AOP (right), offset++);
4079 /* if the bit lenth is less than or */
4080 /* it exactly fits a byte then */
4081 if (SPEC_BLEN (etype) <= 8) {
4082 shCount = SPEC_BSTR (etype);
4084 /* shift left acc */
4087 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4094 emitcode ("ld", "r1,%s",rname);
4098 emitcode ("push", "r1");
4099 emitcode ("push", "r24");
4100 emitcode ("call", "__gptrget");
4101 emitcode ("pop", "r1");
4102 emitcode ("mov","r24,r0");
4106 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4107 ((unsigned char) (0xFF << (blen + bstr)) |
4108 (unsigned char) (0xFF >> (8 - bstr))));
4109 emitcode ("or", "r24,r1");
4110 if (p_type == GPOINTER)
4111 emitcode ("pop", "r1");
4120 emitcode("st","%s+,r24");
4124 emitcode("mov","r0,r24");
4125 emitcode ("call", "__gptrput_pi");
4130 if (SPEC_BLEN (etype) <= 8)
4133 rLen = SPEC_BLEN (etype);
4135 /* now generate for lengths greater than one byte */
4138 l = aopGet (AOP (right), offset++);
4149 emitcode ("st", "%s+,%s",rname,l);
4154 emitcode ("lcall", "__gptrput_pi");
4161 /* last last was not complete */
4163 /* save the byte & read byte */
4169 emitcode ("st","%s+,r24",rname);
4172 emitcode ("push", "r1");
4173 emitcode ("push", "r24");
4174 emitcode ("lcall", "__gptrget");
4175 emitcode ("mov","r24,r0");
4176 emitcode ("pop", "r1");
4180 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4181 emitcode ("or", "r24,r1");
4184 if (p_type == GPOINTER)
4185 emitcode ("pop", "r1");
4193 emitcode ("st", "%s,r24", rname);
4197 emitcode ("mov","r0,r24");
4198 emitcode ("call", "__gptrput");
4203 /*-----------------------------------------------------------------*/
4204 /* genDataPointerSet - remat pointer to data space */
4205 /*-----------------------------------------------------------------*/
4207 genDataPointerSet (operand * right, operand * result, iCode * ic)
4209 int size, offset = 0;
4210 char *l, buffer[256];
4212 aopOp (right, ic, FALSE);
4214 l = aopGet (AOP (result), 0);
4215 size = AOP_SIZE (right);
4218 sprintf (buffer, "(%s + %d)", l, offset);
4220 sprintf (buffer, "%s", l);
4221 emitcode ("sts", "%s,%s", buffer,
4222 aopGet (AOP (right), offset++));
4225 freeAsmop (right, NULL, ic, TRUE);
4226 freeAsmop (result, NULL, ic, TRUE);
4229 /*-----------------------------------------------------------------*/
4230 /* genNearPointerSet - emitcode for near pointer put */
4231 /*-----------------------------------------------------------------*/
4233 genMemPointerSet (operand * right, operand * result, iCode * ic)
4236 char *frname, *rname, *l;
4239 sym_link *ptype = operandType (result);
4241 retype = getSpec (operandType (right));
4243 aopOp (result, ic, FALSE);
4245 /* if the result is rematerializable &
4246 in data space & not a bit variable */
4247 if (AOP_TYPE (result) == AOP_IMMD &&
4248 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4249 genDataPointerSet (right, result, ic);
4252 if (!AOP_INPREG(AOP(result))) {
4253 /* otherwise get a free pointer register */
4255 getFreePtr (ic, &aop, FALSE, 0);
4256 if (isRegPair (AOP (result) )) {
4257 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name);
4259 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4260 aopGet (AOP (result), 0));
4261 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4262 aopGet (AOP (result), 1));
4267 frname = aopGet(aop,0);
4270 aopOp (right, ic, FALSE);
4273 } else if (AOP_ISZ(aop)) {
4276 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4277 "pointer not in correct register");
4280 /* if bitfield then unpack the bits */
4281 if (IS_BITVAR (retype))
4282 genPackBits (retype, right, rname, POINTER);
4284 /* we have can just get the values */
4285 int size = AOP_SIZE (right);
4289 l = aopGet (AOP (right), offset);
4291 emitcode ("sts", "%s+,%s", rname,l);
4293 emitcode ("sts", "%s,%s", rname,l);
4298 /* now some housekeeping stuff */
4299 freeAsmop (result, NULL, ic, TRUE);
4301 /* we had to allocate for this iCode */
4302 freeAsmop (NULL, aop, ic, TRUE);
4305 /* we did not allocate which means left
4306 already in a pointer register, then
4307 if size > 0 && this could be used again
4308 we have to point it back to where it
4310 if (AOP_SIZE (right) > 1 &&
4311 !OP_SYMBOL (result)->remat &&
4312 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) {
4313 int size = AOP_SIZE (right) - 1;
4314 emitcode ("sbiw", "%s,%d",frname,size);
4319 freeAsmop (right, NULL, ic, TRUE);
4322 /*-----------------------------------------------------------------*/
4323 /* genGenPointerSet - set value from generic pointer space */
4324 /*-----------------------------------------------------------------*/
4326 genGenPointerSet (operand * right, operand * result, iCode * ic)
4330 sym_link *retype = getSpec (operandType (right));
4333 aopOp (result, ic, FALSE);
4335 /* if the operand is already in dptr
4336 then we do nothing else we move the value to dptr */
4337 if (AOP_ISZ(AOP(result))) {
4341 getFreePtr(ic,&aop,FALSE,TRUE);
4343 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4344 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4345 emitcode ("mov", "r0,%s", aopGet (AOP (result), 2));
4349 /* so Z register now contains the address */
4350 aopOp (right, ic, FALSE);
4352 /* if bit then unpack */
4353 if (IS_BITVAR (retype))
4354 genUnpackBits (result, "Z", GPOINTER);
4356 size = AOP_SIZE (right);
4360 char *l = aopGet(AOP (right), offset++);
4364 emitcode ("call", "__gptrput_pi");
4366 emitcode ("call", "__gptrput");
4370 freeAsmop (right, NULL, ic, TRUE);
4371 /* now some housekeeping stuff */
4373 /* we had to allocate for this iCode */
4374 freeAsmop (NULL, aop, ic, TRUE);
4377 /* we did not allocate which means left
4378 already in a pointer register, then
4379 if size > 0 && this could be used again
4380 we have to point it back to where it
4382 if (AOP_SIZE (right) > 1 &&
4383 !OP_SYMBOL (result)->remat &&
4384 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
4385 int size = AOP_SIZE (right) - 1;
4386 emitcode ("sbiw", "r30,%d",size);
4389 freeAsmop (result, NULL, ic, TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* genPointerSet - stores the value into a pointer location */
4394 /*-----------------------------------------------------------------*/
4396 genPointerSet (iCode * ic)
4398 operand *right, *result;
4399 sym_link *type, *etype;
4402 right = IC_RIGHT (ic);
4403 result = IC_RESULT (ic);
4405 /* depending on the type of pointer we need to
4406 move it to the correct pointer register */
4407 type = operandType (result);
4408 etype = getSpec (type);
4409 /* if left is of type of pointer then it is simple */
4410 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4411 p_type = DCL_TYPE (type);
4414 /* we have to go by the storage class */
4415 p_type = PTR_TYPE (SPEC_OCLS (etype));
4419 /* now that we have the pointer type we assign
4420 the pointer values */
4427 genMemPointerSet (right, result, ic);
4431 genGenPointerSet (right, result, ic);
4437 /*-----------------------------------------------------------------*/
4438 /* genIfx - generate code for Ifx statement */
4439 /*-----------------------------------------------------------------*/
4441 genIfx (iCode * ic, iCode * popIc)
4443 operand *cond = IC_COND (ic);
4446 aopOp (cond, ic, FALSE);
4448 /* get the value into acc */
4449 if (AOP_TYPE (cond) != AOP_CRY)
4450 toBoolean (cond, "", 0);
4453 /* the result is now in the accumulator */
4454 freeAsmop (cond, NULL, ic, TRUE);
4456 /* if there was something to be popped then do it */
4460 /* if the condition is a bit variable */
4461 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4462 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4465 /* if (isbit && !IS_ITEMP(cond)) */
4466 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4468 /* // genIfxJump(ic,"a"); */
4473 /*-----------------------------------------------------------------*/
4474 /* genAddrOf - generates code for address of */
4475 /*-----------------------------------------------------------------*/
4477 genAddrOf (iCode * ic)
4479 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4482 aopOp (IC_RESULT (ic), ic, FALSE);
4484 /* if the operand is on the stack then we
4485 need to get the stack offset of this
4488 /* if it has an offset then we need to compute
4491 emitcode ("mov", "a,_bp");
4492 emitcode ("add", "a,#0x%02x",
4493 ((char) sym->stack & 0xff));
4494 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4497 /* we can just move _bp */
4498 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4500 /* fill the result with zero */
4501 size = AOP_SIZE (IC_RESULT (ic)) - 1;
4504 if (options.stack10bit && size < (FPTRSIZE - 1)) {
4506 "*** warning: pointer to stack var truncated.\n");
4512 if (options.stack10bit && offset == 2) {
4513 aopPut (AOP (IC_RESULT (ic)), "#0x40",
4517 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4524 /* object not on stack then we need the name */
4525 size = AOP_SIZE (IC_RESULT (ic));
4529 char s[SDCC_NAME_MAX];
4531 sprintf (s, "#(%s >> %d)", sym->rname, offset * 8);
4533 sprintf (s, "#%s", sym->rname);
4534 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4538 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4542 /*-----------------------------------------------------------------*/
4543 /* genFarFarAssign - assignment when both are in far space */
4544 /*-----------------------------------------------------------------*/
4546 genFarFarAssign (operand * result, operand * right, iCode * ic)
4548 int size = AOP_SIZE (right);
4551 /* first push the right side on to the stack */
4553 l = aopGet (AOP (right), offset++);
4555 emitcode ("push", "acc");
4558 freeAsmop (right, NULL, ic, FALSE);
4559 /* now assign DPTR to result */
4560 aopOp (result, ic, FALSE);
4561 size = AOP_SIZE (result);
4563 emitcode ("pop", "acc");
4564 aopPut (AOP (result), "a", --offset);
4566 freeAsmop (result, NULL, ic, FALSE);
4570 /*-----------------------------------------------------------------*/
4571 /* genAssign - generate code for assignment */
4572 /*-----------------------------------------------------------------*/
4574 genAssign (iCode * ic)
4576 operand *result, *right;
4578 unsigned long lit = 0L;
4580 result = IC_RESULT (ic);
4581 right = IC_RIGHT (ic);
4583 /* if they are the same */
4584 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4587 aopOp (right, ic, FALSE);
4589 /* special case both in far space */
4590 if (AOP_TYPE (right) == AOP_DPTR &&
4591 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4593 genFarFarAssign (result, right, ic);
4597 aopOp (result, ic, TRUE);
4599 /* if they are the same registers */
4600 if (sameRegs (AOP (right), AOP (result)))
4603 /* if the result is a bit */
4604 if (AOP_TYPE (result) == AOP_CRY) {
4606 /* if the right size is a literal then
4607 we know what the value is */
4608 if (AOP_TYPE (right) == AOP_LIT) {
4609 if (((int) operandLitValue (right)))
4610 aopPut (AOP (result), one, 0);
4612 aopPut (AOP (result), zero, 0);
4616 /* the right is also a bit variable */
4617 if (AOP_TYPE (right) == AOP_CRY) {
4618 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4619 aopPut (AOP (result), "c", 0);
4624 toBoolean (right, "", 0);
4625 aopPut (AOP (result), "a", 0);
4629 /* bit variables done */
4631 size = AOP_SIZE (result);
4633 if (AOP_TYPE (right) == AOP_LIT)
4635 (unsigned long) floatFromVal (AOP (right)->aopu.
4637 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4638 && (AOP_TYPE (right) == AOP_LIT)
4639 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4640 emitcode ("clr", "a");
4642 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4643 0) aopPut (AOP (result), "a", size);
4645 aopPut (AOP (result),
4646 aopGet (AOP (right), size), size);
4651 aopPut (AOP (result),
4652 aopGet (AOP (right), offset), offset);
4658 freeAsmop (right, NULL, ic, FALSE);
4659 freeAsmop (result, NULL, ic, TRUE);
4662 /*-----------------------------------------------------------------*/
4663 /* genJumpTab - genrates code for jump table */
4664 /*-----------------------------------------------------------------*/
4666 genJumpTab (iCode * ic)
4671 aopOp (IC_JTCOND (ic), ic, FALSE);
4672 /* get the condition into accumulator */
4673 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4675 /* multiply by three */
4676 emitcode ("add", "a,acc");
4677 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4678 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4680 jtab = newiTempLabel (NULL);
4681 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4682 emitcode ("jmp", "@a+dptr");
4683 emitcode ("", "%05d$:", jtab->key + 100);
4684 /* now generate the jump labels */
4685 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4686 jtab = setNextItem (IC_JTLABELS (ic)))
4687 emitcode ("ljmp", "%05d$", jtab->key + 100);
4691 /*-----------------------------------------------------------------*/
4692 /* genCast - gen code for casting */
4693 /*-----------------------------------------------------------------*/
4695 genCast (iCode * ic)
4697 operand *result = IC_RESULT (ic);
4698 sym_link *ctype = operandType (IC_LEFT (ic));
4699 sym_link *rtype = operandType (IC_RIGHT (ic));
4700 operand *right = IC_RIGHT (ic);
4703 /* if they are equivalent then do nothing */
4704 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4707 aopOp (right, ic, FALSE);
4708 aopOp (result, ic, FALSE);
4710 /* if the result is a bit */
4711 if (AOP_TYPE (result) == AOP_CRY) {
4712 /* if the right size is a literal then
4713 we know what the value is */
4714 if (AOP_TYPE (right) == AOP_LIT) {
4715 if (((int) operandLitValue (right)))
4716 aopPut (AOP (result), one, 0);
4718 aopPut (AOP (result), zero, 0);
4723 /* the right is also a bit variable */
4724 if (AOP_TYPE (right) == AOP_CRY) {
4725 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4726 aopPut (AOP (result), "c", 0);
4731 toBoolean (right, "", 0);
4732 aopPut (AOP (result), "a", 0);
4736 /* if they are the same size : or less */
4737 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4739 /* if they are in the same place */
4740 if (sameRegs (AOP (right), AOP (result)))
4743 /* if they in different places then copy */
4744 size = AOP_SIZE (result);
4747 aopPut (AOP (result),
4748 aopGet (AOP (right), offset), offset);
4755 /* if the result is of type pointer */
4756 if (IS_PTR (ctype)) {
4759 sym_link *type = operandType (right);
4760 sym_link *etype = getSpec (type);
4762 /* pointer to generic pointer */
4763 if (IS_GENPTR (ctype)) {
4767 p_type = DCL_TYPE (type);
4769 /* we have to go by the storage class */
4770 p_type = PTR_TYPE (SPEC_OCLS (etype));
4773 /* the first two bytes are known */
4774 size = GPTRSIZE - 1;
4777 aopPut (AOP (result),
4778 aopGet (AOP (right), offset), offset);
4781 /* the last byte depending on type */
4798 /* this should never happen */
4799 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4800 "got unknown pointer type");
4803 aopPut (AOP (result), l, GPTRSIZE - 1);
4807 /* just copy the pointers */
4808 size = AOP_SIZE (result);
4811 aopPut (AOP (result),
4812 aopGet (AOP (right), offset), offset);
4818 /* so we now know that the size of destination is greater
4819 than the size of the source */
4820 /* we move to result for the size of source */
4821 size = AOP_SIZE (right);
4824 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4828 /* now depending on the sign of the source && destination */
4829 size = AOP_SIZE (result) - AOP_SIZE (right);
4830 /* if unsigned or not an integral type */
4831 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4833 aopPut (AOP (result), zero, offset++);
4836 /* we need to extend the sign :{ */
4837 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4839 emitcode ("rlc", "a");
4840 emitcode ("subb", "a,acc");
4842 aopPut (AOP (result), "a", offset++);
4845 /* we are done hurray !!!! */
4848 freeAsmop (right, NULL, ic, TRUE);
4849 freeAsmop (result, NULL, ic, TRUE);
4853 /*-----------------------------------------------------------------*/
4854 /* genDjnz - generate decrement & jump if not zero instrucion */
4855 /*-----------------------------------------------------------------*/
4857 genDjnz (iCode * ic, iCode * ifx)
4863 /* if the if condition has a false label
4864 then we cannot save */
4868 /* if the minus is not of the form
4870 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
4871 !IS_OP_LITERAL (IC_RIGHT (ic)))
4874 if (operandLitValue (IC_RIGHT (ic)) != 1)
4877 /* if the size of this greater than one then no
4879 if (getSize (operandType (IC_RESULT (ic))) > 1)
4882 /* otherwise we can save BIG */
4883 lbl = newiTempLabel (NULL);
4884 lbl1 = newiTempLabel (NULL);
4886 aopOp (IC_RESULT (ic), ic, FALSE);
4888 if (IS_AOP_PREG (IC_RESULT (ic))) {
4889 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
4890 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
4891 emitcode ("jnz", "%05d$", lbl->key + 100);
4894 emitcode ("djnz", "%s,%05d$",
4895 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
4897 emitcode ("sjmp", "%05d$", lbl1->key + 100);
4898 emitcode ("", "%05d$:", lbl->key + 100);
4899 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4900 emitcode ("", "%05d$:", lbl1->key + 100);
4902 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4907 static char *recvregs[8] = {
4908 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
4912 /*-----------------------------------------------------------------*/
4913 /* genReceive - generate code for a receive iCode */
4914 /*-----------------------------------------------------------------*/
4916 genReceive (iCode * ic)
4918 int size, offset = 0;
4919 aopOp (IC_RESULT (ic), ic, FALSE);
4920 size = AOP_SIZE (IC_RESULT (ic));
4922 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
4925 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4928 /*-----------------------------------------------------------------*/
4929 /* gen51Code - generate code for 8051 based controllers */
4930 /*-----------------------------------------------------------------*/
4932 genAVRCode (iCode * lic)
4937 lineHead = lineCurr = NULL;
4939 /* print the allocation information */
4941 printAllocInfo (currFunc, codeOutFile);
4942 /* if debug information required */
4943 /* if (options.debug && currFunc) { */
4945 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
4947 emitcode ("", ".type %s,@function", currFunc->name);
4950 /* stack pointer name */
4954 for (ic = lic; ic; ic = ic->next) {
4956 if (cln != ic->lineno) {
4957 if (options.debug) {
4959 emitcode ("", "C$%s$%d$%d$%d ==.",
4960 FileBaseName (ic->filename),
4961 ic->lineno, ic->level, ic->block);
4964 emitcode (";", "%s %d", ic->filename, ic->lineno);
4967 /* if the result is marked as
4968 spilt and rematerializable or code for
4969 this has already been generated then
4971 if (resultRemat (ic) || ic->generated)
4974 /* depending on the operation */
4993 /* IPOP happens only when trying to restore a
4994 spilt live range, if there is an ifx statement
4995 following this pop then the if statement might
4996 be using some of the registers being popped which
4997 would destory the contents of the register so
4998 we need to check for this condition and handle it */
5000 ic->next->op == IFX &&
5001 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5002 genIfx (ic->next, ic);
5020 genEndFunction (ic);
5040 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5057 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5061 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5065 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5069 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5073 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5077 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5089 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5093 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5097 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5124 case GET_VALUE_AT_ADDRESS:
5129 if (POINTER_SET (ic))
5156 addSet (&_G.sendSet, ic);
5161 /* piCode(ic,stdout); */
5167 /* now we are ready to call the
5168 peep hole optimizer */
5169 if (!options.nopeep)
5170 peepHole (&lineHead);
5172 /* now do the actual printing */
5173 printLine (lineHead, codeOutFile);