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"
35 #include "SDCCpeeph.h"
39 char *aopLiteral (value * val, int offset);
42 /* this is the down and dirty file with all kinds of
43 kludgy & hacky stuff. This is what it is all about
44 CODE GENERATION for a specific MCU . some of the
45 routines may be reusable, will have to see */
47 static char *zero = "0x00";
48 static char *one = "0x01";
51 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
52 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
53 char **fAVRReturn = fReturnAVR;
54 static char *larray[4] = { ">", "<", "hlo8", "hhi8" };
66 extern int avr_ptrRegReq;
68 extern FILE *codeOutFile;
69 #define RESULTONSTACK(x) \
70 (IC_RESULT(x) && IC_RESULT(x)->aop && \
71 IC_RESULT(x)->aop->type == AOP_STK )
73 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
74 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
75 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
76 #define CLRC emitcode("clc","")
77 #define SETC emitcode("stc","")
79 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
81 static lineNode *lineHead = NULL;
82 static lineNode *lineCurr = NULL;
91 /*-----------------------------------------------------------------*/
92 /* reAdjustPreg - points a register back to where it should */
93 /*-----------------------------------------------------------------*/
95 reAdjustPreg (asmop * aop)
100 if ((size = aop->size) <= 1)
106 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
112 /*-----------------------------------------------------------------*/
113 /* outBitC - output a bit C */
114 /*-----------------------------------------------------------------*/
116 outBitC (operand * result)
118 emitcode ("clr", "r0");
119 emitcode ("rol", "r0");
123 /*-----------------------------------------------------------------*/
124 /* inExcludeList - return 1 if the string is in exclude Reg list */
125 /*-----------------------------------------------------------------*/
127 inExcludeList (char *s)
131 if (options.excludeRegs[i] &&
132 STRCASECMP (options.excludeRegs[i], "none") == 0)
135 for (i = 0; options.excludeRegs[i]; i++) {
136 if (options.excludeRegs[i] &&
137 STRCASECMP (s, options.excludeRegs[i]) == 0)
143 /*-----------------------------------------------------------------*/
144 /* findLabelBackwards: walks back through the iCode chain looking */
145 /* for the given label. Returns number of iCode instructions */
146 /* between that label and given ic. */
147 /* Returns zero if label not found. */
148 /*-----------------------------------------------------------------*/
150 findLabelBackwards (iCode * ic, int key)
158 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
159 /* printf("findLabelBackwards = %d\n", count); */
167 /*-----------------------------------------------------------------*/
168 /* addSign - complete with sign */
169 /*-----------------------------------------------------------------*/
171 addSign (operand * result, int offset, int sign)
173 int size = (getDataSize (result) - offset);
176 emitcode ("rlc", "a");
177 emitcode ("subb", "a,acc");
179 aopPut (AOP (result), "a", offset++);
183 aopPut (AOP (result), zero, offset++);
187 /*-----------------------------------------------------------------*/
188 /* isLiteralBit - test if lit == 2^n */
189 /*-----------------------------------------------------------------*/
191 isLiteralBit (unsigned long lit)
193 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
194 0x100L, 0x200L, 0x400L, 0x800L,
195 0x1000L, 0x2000L, 0x4000L, 0x8000L,
196 0x10000L, 0x20000L, 0x40000L, 0x80000L,
197 0x100000L, 0x200000L, 0x400000L, 0x800000L,
198 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
199 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
203 for (idx = 0; idx < 32; idx++)
209 /*-----------------------------------------------------------------*/
210 /* outAcc - output Acc */
211 /*-----------------------------------------------------------------*/
213 outAcc (operand * result)
216 size = getDataSize (result);
218 aopPut (AOP (result), "r0", 0);
221 /* unsigned or positive */
223 aopPut (AOP (result), zero, offset++);
228 #endif // End Unused code section
230 /*-----------------------------------------------------------------*/
231 /* emitcode - writes the code into a file : for now it is simple */
232 /*-----------------------------------------------------------------*/
234 emitcode (char *inst, char *fmt, ...)
237 char lb[INITIAL_INLINEASM];
244 sprintf (lb, "%s\t", inst);
246 sprintf (lb, "%s", inst);
247 vsprintf (lb + (strlen (lb)), fmt, ap);
250 vsprintf (lb, fmt, ap);
252 while (isspace (*lbp))
256 lineCurr = (lineCurr ?
257 connectLine (lineCurr, newLineNode (lb)) :
258 (lineHead = newLineNode (lb)));
259 lineCurr->isInline = _G.inLine;
260 lineCurr->isDebug = _G.debugLine;
264 /*-----------------------------------------------------------------*/
265 /* hasInc - operand is incremented before any other use */
266 /*-----------------------------------------------------------------*/
268 hasInc (operand *op, iCode *ic)
270 sym_link *type = operandType(op);
271 sym_link *retype = getSpec (type);
272 iCode *lic = ic->next;
275 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
276 if (IS_AGGREGATE(type->next)) return NULL;
277 isize = getSize(type->next);
279 /* if operand of the form op = op + <sizeof *op> */
280 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
281 isOperandEqual(IC_RESULT(lic),op) &&
282 isOperandLiteral(IC_RIGHT(lic)) &&
283 operandLitValue(IC_RIGHT(lic)) == isize) {
286 /* if the operand used or deffed */
287 if (bitVectBitValue(OP_USES(op),lic->key) || ((unsigned) lic->defKey == op->key)) {
295 /*-----------------------------------------------------------------*/
296 /* getFreePtr - returns X or Z whichever is free or can be pushed */
297 /*-----------------------------------------------------------------*/
299 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
301 bool xiu = FALSE, ziu = FALSE;
302 bool xou = FALSE, zou = FALSE;
304 /* the logic: if x & z used in the instruction
305 then we are in trouble otherwise */
307 /* first check if x & z are used by this
308 instruction, in which case we are in trouble */
309 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
310 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
314 xou = bitVectBitValue (ic->rMask, X_IDX);
315 zou = bitVectBitValue (ic->rMask, Z_IDX);
317 /* if no usage of Z then return it */
319 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
320 (*aopp)->type = AOP_Z;
322 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
323 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
326 /* if no usage of X then return it */
327 if (!xiu && !xou && !zonly) {
328 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
329 (*aopp)->type = AOP_X;
331 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
332 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
335 /* if z not used then */
338 /* push it if not already pushed */
340 emitcode ("push", "%s",
341 avr_regWithIdx (R30_IDX)->dname);
342 emitcode ("push", "%s",
343 avr_regWithIdx (R31_IDX)->dname);
347 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
348 (*aopp)->type = AOP_Z;
349 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
350 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
353 /* now we know they both have usage */
354 /* if x not used in this instruction */
355 if (!xiu && !zonly) {
356 /* push it if not already pushed */
358 emitcode ("push", "%s",
359 avr_regWithIdx (R26_IDX)->dname);
360 emitcode ("push", "%s",
361 avr_regWithIdx (R27_IDX)->dname);
365 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
366 (*aopp)->type = AOP_X;
368 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
369 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
374 /* I said end of world but not quite end of world yet */
375 /* if this is a result then we can push it on the stack */
377 (*aopp)->type = AOP_STK;
381 /* other wise this is true end of the world */
382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
383 "getFreePtr should never reach here");
387 /*-----------------------------------------------------------------*/
388 /* newAsmop - creates a new asmOp */
389 /*-----------------------------------------------------------------*/
391 newAsmop (short type)
395 aop = Safe_calloc (1, sizeof (asmop));
400 /*-----------------------------------------------------------------*/
401 /* pointerCode - returns the code for a pointer type */
402 /*-----------------------------------------------------------------*/
404 pointerCode (sym_link * etype)
407 return PTR_TYPE (SPEC_OCLS (etype));
411 /*-----------------------------------------------------------------*/
412 /* aopForSym - for a true symbol */
413 /*-----------------------------------------------------------------*/
415 aopForSym (iCode * ic, symbol * sym, bool result)
418 memmap *space = SPEC_OCLS (sym->etype);
420 /* if already has one */
424 /* assign depending on the storage class */
425 /* if it is on the stack */
427 sym->aop = aop = newAsmop (0);
428 aop->size = getSize (sym->type);
430 /* we can use std / ldd instruction */
432 && (sym->stack + getSize (sym->type) - 1) <= 63) {
433 aop->type = AOP_STK_D;
434 aop->aopu.aop_stk = sym->stack;
438 /* otherwise get a free pointer register X/Z */
439 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
441 /* now assign the address of the variable to
442 the pointer register */
443 if (aop->type != AOP_STK) {
444 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
445 if (sym->stack < 0) {
446 if ((sym->stack - _G.nRegsSaved) > -63) {
447 emitcode ("sbiw", "%s,0x%02x",
448 aop->aopu.aop_ptr->name,
453 emitcode ("subi", "%s,<(%d)",
454 aop->aopu.aop_ptr->name,
455 sym->stack - _G.nRegsSaved);
456 emitcode ("sbci", "%s,>(%d)",
458 sym->stack - _G.nRegsSaved);
462 if (sym->stack <= 63) {
463 emitcode ("adiw", "%s,0x%02x",
464 aop->aopu.aop_ptr->name,
468 emitcode ("subi", "%s,<(-%d)",
469 aop->aopu.aop_ptr->name,
471 emitcode ("sbci", "%s,>(-%d)",
480 /* if in bit space */
481 if (IN_BITSPACE (space)) {
482 sym->aop = aop = newAsmop (AOP_CRY);
483 aop->aopu.aop_dir = sym->rname;
484 aop->size = getSize (sym->type);
487 /* if it is in direct space */
488 if (IN_DIRSPACE (space)) {
489 sym->aop = aop = newAsmop (AOP_DIR);
490 aop->aopu.aop_dir = sym->rname;
491 aop->size = getSize (sym->type);
495 /* special case for a function */
496 if (IS_FUNC (sym->type)) {
497 sym->aop = aop = newAsmop (AOP_IMMD);
498 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
499 strcpy (aop->aopu.aop_immd, sym->rname);
500 aop->size = FPTRSIZE;
504 /* only remaining is code / eeprom which will need pointer reg */
505 /* if it is in code space */
507 sym->aop = aop = newAsmop (0);
509 if (IN_CODESPACE (space))
512 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
513 aop->size = getSize (sym->type);
514 emitcode ("ldi", "%s,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
515 emitcode ("ldi", "%s,>(%s)", aop->aop_ptr2);
520 /*-----------------------------------------------------------------*/
521 /* aopForRemat - rematerialzes an object */
522 /*-----------------------------------------------------------------*/
524 aopForRemat (symbol * sym)
526 iCode *ic = sym->rematiCode;
527 asmop *aop = newAsmop (AOP_IMMD);
532 val += (int) operandLitValue (IC_RIGHT (ic));
533 else if (ic->op == '-')
534 val -= (int) operandLitValue (IC_RIGHT (ic));
538 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
542 sprintf (buffer, "(%s %c 0x%04x)",
543 OP_SYMBOL (IC_LEFT (ic))->rname,
544 val >= 0 ? '+' : '-', abs (val) & 0xffff);
546 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
548 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
549 strcpy (aop->aopu.aop_immd, buffer);
553 /*-----------------------------------------------------------------*/
554 /* regsInCommon - two operands have some registers in common */
555 /*-----------------------------------------------------------------*/
557 regsInCommon (operand * op1, operand * op2)
562 /* if they have registers in common */
563 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
566 sym1 = OP_SYMBOL (op1);
567 sym2 = OP_SYMBOL (op2);
569 if (sym1->nRegs == 0 || sym2->nRegs == 0)
572 for (i = 0; i < sym1->nRegs; i++) {
577 for (j = 0; j < sym2->nRegs; j++) {
581 if (sym2->regs[j] == sym1->regs[i])
589 /*-----------------------------------------------------------------*/
590 /* operandsEqu - equivalent */
591 /*-----------------------------------------------------------------*/
593 operandsEqu (operand * op1, operand * op2)
597 /* if they not symbols */
598 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
601 sym1 = OP_SYMBOL (op1);
602 sym2 = OP_SYMBOL (op2);
604 /* if both are itemps & one is spilt
605 and the other is not then false */
606 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
607 sym1->isspilt != sym2->isspilt) return FALSE;
609 /* if they are the same */
613 if (strcmp (sym1->rname, sym2->rname) == 0)
617 /* if left is a tmp & right is not */
618 if (IS_ITEMP (op1) &&
619 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
622 if (IS_ITEMP (op2) &&
624 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
630 /*-----------------------------------------------------------------*/
631 /* sameRegs - two asmops have the same registers */
632 /*-----------------------------------------------------------------*/
634 sameRegs (asmop * aop1, asmop * aop2)
641 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
644 if (aop1->size != aop2->size)
647 for (i = 0; i < aop1->size; i++)
648 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
654 /*-----------------------------------------------------------------*/
655 /* isRegPair - for size 2 if this operand has a register pair */
656 /*-----------------------------------------------------------------*/
658 isRegPair (asmop * aop)
660 if (!aop || aop->size < 2)
662 if (aop->type == AOP_X || aop->type == AOP_Z)
664 if (aop->type != AOP_REG)
666 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
667 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
673 /*-----------------------------------------------------------------*/
674 /* allHigh - all registers are high registers */
675 /*-----------------------------------------------------------------*/
676 static int allHigh (asmop * aop)
680 if (aop->type == AOP_X || aop->type == AOP_Z)
682 if (aop->type != AOP_REG)
684 for (i=0; i < aop->size ; i++ )
685 if (aop->aopu.aop_reg[i]->rIdx < R16_IDX) return 0;
689 /*-----------------------------------------------------------------*/
690 /* aopOp - allocates an asmop for an operand : */
691 /*-----------------------------------------------------------------*/
693 aopOp (operand * op, iCode * ic, bool result)
702 /* if this a literal */
703 if (IS_OP_LITERAL (op)) {
704 op->aop = aop = newAsmop (AOP_LIT);
705 aop->aopu.aop_lit = op->operand.valOperand;
706 aop->size = getSize (operandType (op));
710 /* if already has a asmop then continue */
714 /* if the underlying symbol has a aop */
715 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
716 op->aop = OP_SYMBOL (op)->aop;
720 /* if this is a true symbol */
721 if (IS_TRUE_SYMOP (op)) {
722 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
726 /* this is a temporary : this has
732 e) can be a return use only */
734 sym = OP_SYMBOL (op);
737 /* if the type is a conditional */
738 if (sym->regType & REG_CND) {
739 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
744 /* if it is spilt then two situations
746 b) has a spill location */
747 if (sym->isspilt || sym->nRegs == 0) {
749 /* rematerialize it NOW */
751 sym->aop = op->aop = aop = aopForRemat (sym);
752 aop->size = getSize (sym->type);
757 assert ("ACC_USE cannot happen in AVR\n");
762 aop = op->aop = sym->aop = newAsmop (AOP_STR);
763 aop->size = getSize (sym->type);
764 for (i = 0; i < (int) fAVRReturnSize; i++)
765 aop->aopu.aop_str[i] = fAVRReturn[i];
769 /* else spill location */
770 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
771 /* force a new aop if sizes differ */
772 sym->usl.spillLoc->aop = NULL;
774 sym->aop = op->aop = aop =
775 aopForSym (ic, sym->usl.spillLoc, result);
776 aop->size = getSize (sym->type);
780 /* must be in a register */
781 sym->aop = op->aop = aop = newAsmop (AOP_REG);
782 aop->size = sym->nRegs;
783 for (i = 0; i < sym->nRegs; i++)
784 aop->aopu.aop_reg[i] = sym->regs[i];
787 /*-----------------------------------------------------------------*/
788 /* freeAsmop - free up the asmop given to an operand */
789 /*----------------------------------------------------------------*/
791 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
808 /* depending on the asmop type only three cases need work AOP_RO
809 , AOP_R1 && AOP_STK */
814 emitcode ("pop", "r26");
815 emitcode ("pop", "r27");
819 bitVectUnSetBit (ic->rUsed, X_IDX);
825 emitcode ("pop", "r30");
826 emitcode ("pop", "r31");
830 bitVectUnSetBit (ic->rUsed, Z_IDX);
836 int stk = aop->aopu.aop_stk + aop->size;
837 bitVectUnSetBit (ic->rUsed, X_IDX);
838 bitVectUnSetBit (ic->rUsed, Z_IDX);
840 getFreePtr (ic, &aop, FALSE, 0);
842 emitcode ("movw", "%s,r28");
844 if (stk <= 63 && stk > 0) {
845 emitcode ("adiw", "%s,0x%02x",
846 aop->aopu.aop_ptr->name,
850 emitcode ("subi", "%s,<(%d)",
851 aop->aopu.aop_ptr->name,
853 emitcode ("sbci", "%s,>(%d)",
860 emitcode ("pop", "r24");
861 emitcode ("st", "-%s,r24",
862 aop->type == AOP_X ? "X" : "Z");
867 freeAsmop (op, NULL, ic, TRUE);
869 emitcode ("pop", "r26");
870 emitcode ("pop", "r27");
875 emitcode ("pop", "r30");
876 emitcode ("pop", "r31");
883 /* all other cases just dealloc */
887 OP_SYMBOL (op)->aop = NULL;
888 /* if the symbol has a spill */
890 SPIL_LOC (op)->aop = NULL;
895 /*-----------------------------------------------------------------*/
896 /* aopGet - for fetching value of the aop */
897 /*-----------------------------------------------------------------*/
899 aopGet (asmop * aop, int offset)
904 /* offset is greater than
906 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
909 /* depending on type */
913 if (offset > aop->coff) {
914 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
918 if (offset < aop->coff) {
919 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
924 emitcode ("ld", "%s,x",
925 (rs = ((offset & 1) ? "r25" : "r24")));
930 if (offset > aop->coff) {
931 emitcode ("adiw", "r30,%d",
935 emitcode ("sbiw", "r30,%d",
938 emitcode ("lpm", "%s,z",
939 (rs = ((offset & 1) ? "r25" : "r24")));
943 if (offset > aop->coff) {
944 emitcode ("ldd", "%s,z+%d",
946 ((offset & 1) ? "r25" : "r24")),
950 emitcode ("sbiw", "%s,%d",
951 aop->aopu.aop_ptr->name,
954 emitcode ("ld", "%s,z",
956 ((offset & 1) ? "r25" : "r24")));
963 emitcode ("lds", "%s,(%s)+%d",
964 (rs = ((offset & 1) ? "r25" : "r24")),
965 aop->aopu.aop_immd, offset);
969 emitcode ("lds", "%s,(%s)+%d",
970 (rs = ((offset & 1) ? "r25" : "r24")),
971 aop->aopu.aop_dir, offset);
975 return aop->aopu.aop_reg[offset]->name;
978 assert ("cannot be in bit space AOP_CRY\n");
982 s = aopLiteral (aop->aopu.aop_lit, offset);
983 emitcode ("ldi", "%s,<(%s)",
984 (rs = ((offset & 1) ? "r24" : "r25")), s);
989 return aop->aopu.aop_str[offset];
992 emitcode ("ldd", "%s,Y+%d",
993 (rs = ((offset & 1) ? "r25" : "r24")),
994 aop->aopu.aop_stk + offset);
998 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
999 "aopget got unsupported aop->type");
1003 /*-----------------------------------------------------------------*/
1004 /* aopPut - puts a string for a aop */
1005 /*-----------------------------------------------------------------*/
1007 aopPut (asmop * aop, char *s, int offset)
1011 if (aop->size && offset > (aop->size - 1)) {
1012 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1013 "aopPut got offset > aop->size");
1017 /* will assign value to value */
1018 /* depending on where it is ofcourse */
1019 switch (aop->type) {
1022 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1025 sprintf (d, "%s", aop->aopu.aop_dir);
1028 emitcode ("sts", "%s,%s", d, s);
1032 if (toupper (*s) != 'R') {
1034 emitcode ("clr", "%s",
1035 aop->aopu.aop_reg[offset]->name);
1038 emitcode ("ldi", "r25,%s", s);
1039 emitcode ("mov", "%s,r35",
1040 aop->aopu.aop_reg[offset]->name);
1044 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1045 emitcode ("mov", "%s,%s",
1046 aop->aopu.aop_reg[offset]->name, s);
1052 if (offset > aop->coff) {
1053 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1054 offset - aop->coff);
1057 if (offset < aop->coff) {
1058 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1059 aop->coff - offset);
1063 emitcode ("st", "x,%s", s);
1068 if (offset > aop->coff) {
1069 emitcode ("adiw", "r30,%d",
1070 offset - aop->coff);
1073 emitcode ("sbiw", "r30,%d",
1074 aop->coff - offset);
1076 emitcode ("lpm", "%s,z", s);
1079 /* we can use lds */
1080 if (offset > aop->coff) {
1081 emitcode ("sdd", "z+%d,%s",
1082 offset - aop->coff, s);
1085 emitcode ("sbiw", "%s,%d",
1086 aop->aopu.aop_ptr->name,
1087 aop->coff - offset);
1089 emitcode ("ld", "%s,z", s);
1095 emitcode ("push", "%s", s);
1099 /* if used only for a condition code check */
1100 assert (toupper (*s) == 'R');
1102 emitcode ("xrl", "r0,r0");
1103 emitcode ("cpi", "%s,0", s);
1106 emitcode ("cpc", "r0,%s", s);
1112 if (strcmp (aop->aopu.aop_str[offset], s))
1113 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1118 emitcode ("std", "y+%d,%s", offset, s);
1122 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1123 "aopPut got unsupported aop->type");
1129 #define AOP(op) op->aop
1130 #define AOP_TYPE(op) AOP(op)->type
1131 #define AOP_SIZE(op) AOP(op)->size
1132 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1133 AOP_TYPE(x) == AOP_Z))
1134 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1135 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1136 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1137 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1138 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1139 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1140 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1142 /*-----------------------------------------------------------------*/
1143 /* genNotFloat - generates not for float operations */
1144 /*-----------------------------------------------------------------*/
1146 genNotFloat (operand * op, operand * res)
1152 /* we will put 127 in the first byte of
1154 aopPut (AOP (res), "127", 0);
1155 size = AOP_SIZE (op) - 1;
1158 l = aopGet (op->aop, offset++);
1162 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1164 tlbl = newiTempLabel (NULL);
1166 tlbl = newiTempLabel (NULL);
1167 aopPut (res->aop, zero, 1);
1168 emitcode ("cpi", "r0,0");
1169 emitcode ("breq", "L%05d", tlbl->key);
1170 aopPut (res->aop, one, 1);
1171 emitcode ("", "L%05d:", tlbl->key);
1173 size = res->aop->size - 2;
1175 /* put zeros in the rest */
1177 aopPut (res->aop, zero, offset++);
1180 /*-----------------------------------------------------------------*/
1181 /* opIsGptr: returns non-zero if the passed operand is */
1182 /* a generic pointer type. */
1183 /*-----------------------------------------------------------------*/
1185 opIsGptr (operand * op)
1187 sym_link *type = operandType (op);
1189 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1195 /*-----------------------------------------------------------------*/
1196 /* getDataSize - get the operand data size */
1197 /*-----------------------------------------------------------------*/
1199 getDataSize (operand * op)
1202 size = AOP_SIZE (op);
1203 if (size == GPTRSIZE) {
1204 sym_link *type = operandType (op);
1205 if (IS_GENPTR (type)) {
1206 /* generic pointer; arithmetic operations
1207 * should ignore the high byte (pointer type).
1215 /*-----------------------------------------------------------------*/
1216 /* toBoolean - emit code for orl a,operator(sizeop) */
1217 /*-----------------------------------------------------------------*/
1219 toBoolean (operand * oper, char *r, bool clr)
1221 int size = AOP_SIZE (oper);
1224 emitcode ("clr", "%s", r);
1226 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1229 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1230 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1235 /*-----------------------------------------------------------------*/
1236 /* genNot - generate code for ! operation */
1237 /*-----------------------------------------------------------------*/
1242 sym_link *optype = operandType (IC_LEFT (ic));
1243 int size, offset = 1;
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if type float then do float */
1250 if (IS_FLOAT (optype)) {
1251 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1254 emitcode ("clr", "r24");
1255 tlbl = newiTempLabel (NULL);
1256 size = AOP_SIZE (IC_LEFT (ic));
1259 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1264 emitcode ("cpc", "%s,r24",
1265 aopGet (AOP (IC_LEFT (ic)),
1268 emitcode ("cpi", "%s,0",
1269 aopGet (AOP (IC_LEFT (ic)),
1273 emitcode ("bne", "L%05d", tlbl->key);
1275 emitcode ("ldi", "r24,1");
1276 emitcode ("", "L%05d:", tlbl->key);
1277 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1278 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1281 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1285 /* release the aops */
1286 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1291 /*-----------------------------------------------------------------*/
1292 /* genCpl - generate code for complement */
1293 /*-----------------------------------------------------------------*/
1301 /* assign asmOps to operand & result */
1302 aopOp (IC_LEFT (ic), ic, FALSE);
1303 aopOp (IC_RESULT (ic), ic, TRUE);
1304 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1305 size = AOP_SIZE (IC_RESULT (ic));
1307 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1309 emitcode ("com", "%s", l);
1312 aopPut (AOP (IC_RESULT (ic)), l, offset);
1313 emitcode ("com", "%s",
1314 aopGet (AOP (IC_RESULT (ic)), offset));
1319 /* release the aops */
1320 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1321 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1324 /*-----------------------------------------------------------------*/
1325 /* genUminusFloat - unary minus for floating points */
1326 /*-----------------------------------------------------------------*/
1328 genUminusFloat (operand * op, operand * result)
1330 int size, offset = 0;
1332 /* for this we just need to flip the
1333 first it then copy the rest in place */
1334 size = AOP_SIZE (op) - 1;
1335 l = aopGet (AOP (op), 3);
1337 emitcode ("ldi", "r24,0x80");
1338 if (sameRegs (AOP (op), AOP (result))) {
1339 emitcode ("eor", "%s,r24", l);
1342 aopPut (AOP (result), l, 3);
1343 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1346 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1351 /*-----------------------------------------------------------------*/
1352 /* genUminus - unary minus code generation */
1353 /*-----------------------------------------------------------------*/
1355 genUminus (iCode * ic)
1358 sym_link *optype, *rtype;
1362 aopOp (IC_LEFT (ic), ic, FALSE);
1363 aopOp (IC_RESULT (ic), ic, TRUE);
1365 optype = operandType (IC_LEFT (ic));
1366 rtype = operandType (IC_RESULT (ic));
1368 /* if float then do float stuff */
1369 if (IS_FLOAT (optype)) {
1370 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1374 /* otherwise subtract from zero */
1375 size = AOP_SIZE (IC_LEFT (ic));
1377 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1380 emitcode ("neg", "%s",
1381 aopGet (AOP (IC_LEFT (ic)), 0));
1384 aopPut (AOP (IC_RESULT (ic)),
1385 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1386 emitcode ("neg", "%s",
1387 aopGet (AOP (IC_RESULT (ic)), 0));
1393 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1395 aopPut (AOP (IC_RESULT (ic)), l, offset);
1396 l = aopGet (AOP (IC_RESULT (ic)), offset);
1399 emitcode ("com", "%s", l);
1401 emitcode ("neg", "%s", l);
1404 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1407 emitcode ("sbci", "%s,0xff",
1408 aopGet (AOP (IC_RESULT (ic)), offset++));
1412 /* if any remaining bytes in the result */
1413 /* we just need to propagate the sign */
1414 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1415 symbol *tlbl = newiTempLabel (NULL);
1416 emitcode ("clr", "r0");
1417 emitcode ("brcc", "L%05d", tlbl->key);
1418 emitcode ("com", "r0");
1419 emitcode ("", "L%05d:", tlbl->key);
1421 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1425 /* release the aops */
1426 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1427 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1430 /*-----------------------------------------------------------------*/
1431 /* assignResultValue - */
1432 /*-----------------------------------------------------------------*/
1434 assignResultValue (operand * oper)
1437 int size = AOP_SIZE (oper);
1439 aopPut (AOP (oper), fAVRReturn[offset], offset);
1444 /*-----------------------------------------------------------------*/
1445 /* saveZreg - if indirect call then save z-pointer register */
1446 /*-----------------------------------------------------------------*/
1448 saveZreg (iCode * ic)
1450 /* only if live accross this call */
1451 if (ic->regsSaved == 0 &&
1452 (bitVectBitValue (ic->rMask, R30_IDX) ||
1453 bitVectBitValue (ic->rMask, R31_IDX))) {
1455 emitcode ("push", "r30");
1456 emitcode ("push", "r31");
1460 /*-----------------------------------------------------------------*/
1461 /* popZreg - restore values of zreg */
1462 /*-----------------------------------------------------------------*/
1464 popZreg (iCode * ic)
1466 if (ic->regsSaved) {
1467 emitcode ("pop", "r31");
1468 emitcode ("pop", "r30");
1472 /*-----------------------------------------------------------------*/
1473 /* genIpush - genrate code for pushing this gets a little complex */
1474 /*-----------------------------------------------------------------*/
1476 genIpush (iCode * ic)
1478 int size, offset = 0;
1482 if (!ic->parmPush) {
1483 /* and the item is spilt then do nothing */
1484 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1489 for (lic = ic->next; lic; lic = lic->next)
1490 if (lic->op == PCALL)
1496 /* this is a paramter push */
1497 aopOp (IC_LEFT (ic), ic, FALSE);
1498 size = AOP_SIZE (IC_LEFT (ic));
1500 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1501 emitcode ("push", "%s", l);
1504 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1507 /*-----------------------------------------------------------------*/
1508 /* genIpop - recover the registers: can happen only for spilling */
1509 /*-----------------------------------------------------------------*/
1511 genIpop (iCode * ic)
1516 /* if the temp was not pushed then */
1517 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1520 aopOp (IC_LEFT (ic), ic, FALSE);
1521 size = AOP_SIZE (IC_LEFT (ic));
1522 offset = (size - 1);
1524 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1526 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1529 /*-----------------------------------------------------------------*/
1530 /* genCall - generates a call statement */
1531 /*-----------------------------------------------------------------*/
1533 genCall (iCode * ic)
1536 /* if send set is not empty the assign */
1540 for (sic = setFirstItem (_G.sendSet); sic;
1541 sic = setNextItem (_G.sendSet)) {
1542 int size, offset = 0;
1543 aopOp (IC_LEFT (sic), sic, FALSE);
1544 size = AOP_SIZE (IC_LEFT (sic));
1547 aopGet (AOP (IC_LEFT (sic)), offset);
1549 sprintf (buffer, "r%d", rnum++);
1551 emitcode ("mov", "%s,%s", b, l);
1554 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1559 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1560 OP_SYMBOL (IC_LEFT (ic))->rname :
1561 OP_SYMBOL (IC_LEFT (ic))->name));
1563 /* if we need assign a result value */
1564 if ((IS_ITEMP (IC_RESULT (ic)) &&
1565 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1566 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1567 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1569 aopOp (IC_RESULT (ic), ic, FALSE);
1570 assignResultValue (IC_RESULT (ic));
1571 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1574 /* adjust the stack for parameters if required */
1575 if (ic->parmBytes) {
1576 if (ic->parmBytes > 63) {
1577 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1580 emitcode ("subi", "r28,<(%d)",
1582 emitcode ("sbci", "r29,>(%d)",
1589 /*-----------------------------------------------------------------*/
1590 /* genPcall - generates a call by pointer statement */
1591 /*-----------------------------------------------------------------*/
1593 genPcall (iCode * ic)
1599 aopOp (IC_LEFT (ic), ic, FALSE);
1600 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1601 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1602 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1604 /* if send set is not empty the assign */
1608 for (sic = setFirstItem (_G.sendSet); sic;
1609 sic = setNextItem (_G.sendSet)) {
1610 int size, offset = 0;
1611 aopOp (IC_LEFT (sic), sic, FALSE);
1612 size = AOP_SIZE (IC_LEFT (sic));
1615 aopGet (AOP (IC_LEFT (sic)), offset);
1617 sprintf (b, "r%d", rnum++);
1619 emitcode ("mov", "%s,%s", b, l);
1622 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1627 emitcode ("icall", "");
1629 /* if we need assign a result value */
1630 if ((IS_ITEMP (IC_RESULT (ic)) &&
1631 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1632 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1633 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1635 aopOp (IC_RESULT (ic), ic, FALSE);
1637 assignResultValue (IC_RESULT (ic));
1638 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1641 /* adjust the stack for parameters if
1643 if (ic->parmBytes) {
1645 if (ic->parmBytes > 3) {
1646 emitcode ("mov", "a,%s", spname);
1647 emitcode ("add", "a,#0x%02x",
1648 (-ic->parmBytes) & 0xff);
1649 emitcode ("mov", "%s,a", spname);
1652 for (i = 0; i < ic->parmBytes; i++)
1653 emitcode ("dec", "%s", spname);
1657 /* adjust the stack for parameters if required */
1658 if (ic->parmBytes) {
1659 if (ic->parmBytes > 63) {
1660 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1663 emitcode ("subi", "r28,<(%d)",
1665 emitcode ("sbci", "r29,>(%d)",
1673 /*-----------------------------------------------------------------*/
1674 /* resultRemat - result is rematerializable */
1675 /*-----------------------------------------------------------------*/
1677 resultRemat (iCode * ic)
1679 if (SKIP_IC (ic) || ic->op == IFX)
1682 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1683 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1684 if (sym->remat && !POINTER_SET (ic))
1691 #if defined(__BORLANDC__) || defined(_MSC_VER)
1692 #define STRCASECMP stricmp
1694 #define STRCASECMP strcasecmp
1697 /*-----------------------------------------------------------------*/
1698 /* genFunction - generated code for function entry */
1699 /*-----------------------------------------------------------------*/
1701 genFunction (iCode * ic)
1708 /* create the function header */
1709 emitcode (";", "-----------------------------------------");
1710 emitcode (";", " function %s",
1711 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1712 emitcode (";", "-----------------------------------------");
1714 emitcode ("", "%s:", sym->rname);
1715 ftype = operandType (IC_LEFT (ic));
1717 /* if critical function then turn interrupts off */
1718 if (IFFUNC_ISCRITICAL (ftype))
1719 emitcode ("cli", "");
1721 if (IFFUNC_ISISR (sym->type)) {
1724 /* save the preserved registers that are used in this function */
1725 for (i = R2_IDX; i <= R15_IDX; i++) {
1726 if (bitVectBitValue (sym->regsUsed, i)) {
1728 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1731 /* now for the pointer registers */
1732 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1734 emitcode ("push", "r26");
1736 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1738 emitcode ("push", "r27");
1740 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1742 emitcode ("push", "r30");
1744 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1746 emitcode ("push", "r31");
1748 /* adjust the stack for the function */
1750 emitcode ("push", "r28");
1751 emitcode ("push", "r29");
1752 emitcode ("in", "r28,__SP_L__");
1753 emitcode ("in", "r29,__SP_H__");
1754 if (sym->stack <= 63) {
1755 emitcode ("sbiw", "r28,%d", sym->stack);
1758 emitcode ("subi", "r28,<(%d)", sym->stack);
1759 emitcode ("sbci", "r29,>(%d)", sym->stack);
1761 emitcode ("out", "__SP_L__,r28");
1762 emitcode ("out", "__SP_H__,r29");
1766 /*-----------------------------------------------------------------*/
1767 /* genEndFunction - generates epilogue for functions */
1768 /*-----------------------------------------------------------------*/
1770 genEndFunction (iCode * ic)
1772 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1775 /* restore stack pointer */
1777 if (sym->stack <= 63) {
1778 emitcode ("adiw", "r28,%d", sym->stack);
1781 emitcode ("subi", "r28,<(-%d)", sym->stack);
1782 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1784 emitcode ("out", "__SP_L__,r28");
1785 emitcode ("out", "__SP_H__,r29");
1787 /* pop frame pointer */
1788 emitcode ("pop", "r29");
1789 emitcode ("pop", "r28");
1791 /* restore preserved registers */
1792 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1794 emitcode ("pop", "r31");
1796 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1798 emitcode ("pop", "r30");
1800 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1802 emitcode ("pop", "r27");
1804 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1806 emitcode ("pop", "r26");
1808 for (i = R15_IDX; i >= R2_IDX; i--) {
1809 if (bitVectBitValue (sym->regsUsed, i)) {
1811 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1815 if (IFFUNC_ISCRITICAL (sym->type))
1816 emitcode ("sti", "");
1818 if (IFFUNC_ISISR (sym->type)) {
1819 emitcode ("rti", "");
1822 emitcode ("ret", "");
1827 /*-----------------------------------------------------------------*/
1828 /* genRet - generate code for return statement */
1829 /*-----------------------------------------------------------------*/
1833 int size, offset = 0;
1835 /* if we have no return value then
1836 just generate the "ret" */
1840 /* we have something to return then
1841 move the return value into place */
1842 aopOp (IC_LEFT (ic), ic, FALSE);
1843 size = AOP_SIZE (IC_LEFT (ic));
1846 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1847 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1849 (int) floatFromVal (AOP (IC_LEFT (ic))->
1850 aopu.aop_lit), offset);
1854 l = aopGet (AOP (IC_LEFT (ic)), offset);
1855 if (strcmp (fAVRReturn[offset], l))
1856 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1862 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1865 /* generate a jump to the return label
1866 if the next is not the return statement */
1867 if (!(ic->next && ic->next->op == LABEL &&
1868 IC_LABEL (ic->next) == returnLabel))
1870 emitcode ("rjmp", "L%05d", returnLabel->key);
1874 /*-----------------------------------------------------------------*/
1875 /* genLabel - generates a label */
1876 /*-----------------------------------------------------------------*/
1878 genLabel (iCode * ic)
1880 /* special case never generate */
1881 if (IC_LABEL (ic) == entryLabel)
1884 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1887 /*-----------------------------------------------------------------*/
1888 /* genGoto - generates a ljmp */
1889 /*-----------------------------------------------------------------*/
1891 genGoto (iCode * ic)
1893 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1896 /*-----------------------------------------------------------------*/
1897 /* genPlusIncr :- does addition with increment if possible */
1898 /*-----------------------------------------------------------------*/
1900 genPlusIncr (iCode * ic)
1902 unsigned int icount;
1905 /* will try to generate an increment */
1906 /* if the right side is not a literal
1908 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1911 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1914 /* if the sizes are greater than 2 or they are not the same regs
1916 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1919 /* so we know LEFT & RESULT in the same registers and add
1921 /* for short & char types */
1922 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1924 emitcode ("inc", "%s",
1925 aopGet (AOP (IC_LEFT (ic)), 0));
1928 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1929 emitcode ("subi", "%s,<(%d)",
1930 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1935 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1936 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1939 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1940 /* if register pair and starts with 26/30 then adiw */
1941 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1943 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1944 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1945 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1946 emitcode ("adiw", "%s,%d",
1947 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1952 emitcode ("subi", "%s,<(%d)",
1953 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1954 emitcode ("sbci", "%s,>(%d)",
1955 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1959 /* for 32 bit longs */
1960 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1962 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1964 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1966 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1972 /* This is the pure and virtuous version of this code.
1973 * I'm pretty certain it's right, but not enough to toss the old
1977 adjustArithmeticResult (iCode * ic)
1979 if (opIsGptr (IC_RESULT (ic)) &&
1980 opIsGptr (IC_LEFT (ic)) &&
1981 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1982 aopPut (AOP (IC_RESULT (ic)),
1983 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1987 if (opIsGptr (IC_RESULT (ic)) &&
1988 opIsGptr (IC_RIGHT (ic)) &&
1989 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1990 aopPut (AOP (IC_RESULT (ic)),
1991 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1995 if (opIsGptr (IC_RESULT (ic)) &&
1996 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1997 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1998 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1999 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2001 sprintf (buffer, "%d",
2002 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2003 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2007 /*-----------------------------------------------------------------*/
2008 /* genPlus - generates code for addition */
2009 /*-----------------------------------------------------------------*/
2011 genPlus (iCode * ic)
2013 int size, offset = 0;
2017 /* special cases :- */
2019 aopOp (IC_LEFT (ic), ic, FALSE);
2020 aopOp (IC_RIGHT (ic), ic, FALSE);
2021 aopOp (IC_RESULT (ic), ic, TRUE);
2023 /* if I can do an increment instead
2024 of add then GOOD for ME */
2025 if (genPlusIncr (ic) == TRUE)
2028 size = getDataSize (IC_RESULT (ic));
2029 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2033 aopPut (AOP (IC_RESULT (ic)),
2034 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2036 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2043 emitcode (l, "%s,%s",
2044 aopGet (AOP (IC_RESULT (ic)), offset),
2045 aopGet (AOP (IC_RIGHT (ic)), offset));
2048 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2054 emitcode (l, "%s,%s(-%d)",
2055 aopGet (AOP (IC_RESULT (ic)), offset),
2057 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2065 emitcode (l, "%s,%s",
2066 aopGet (AOP (IC_RESULT (ic)), offset),
2067 aopGet (AOP (IC_RIGHT (ic)), offset));
2073 adjustArithmeticResult (ic);
2076 freeAsmop (IC_LEFT (ic), NULL, ic,
2077 (RESULTONSTACK (ic) ? FALSE : TRUE));
2078 freeAsmop (IC_RIGHT (ic), NULL, ic,
2079 (RESULTONSTACK (ic) ? FALSE : TRUE));
2080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2083 /*-----------------------------------------------------------------*/
2084 /* genMinusDec :- does subtraction with deccrement if possible */
2085 /*-----------------------------------------------------------------*/
2087 genMinusDec (iCode * ic)
2089 unsigned int icount;
2092 /* will try to generate an increment */
2093 /* if the right side is not a literal
2095 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2099 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2102 /* if the sizes are greater than 2 or they are not the same regs
2104 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2107 /* so we know LEFT & RESULT in the same registers and add
2109 /* for short & char types */
2110 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2112 emitcode ("dec", "%s",
2113 aopGet (AOP (IC_LEFT (ic)), 0));
2116 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2117 emitcode ("subi", "%s,<(%d)",
2118 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2123 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2124 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2127 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2128 /* if register pair and starts with 26/30 then adiw */
2129 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2131 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2132 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2133 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2134 emitcode ("sbiw", "%s,%d",
2135 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2140 emitcode ("subi", "%s,<(%d)",
2141 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2142 emitcode ("sbci", "%s,>(%d)",
2143 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2146 /* for 32 bit longs */
2147 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2149 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2151 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2153 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2159 /*-----------------------------------------------------------------*/
2160 /* genMinus - generates code for subtraction */
2161 /*-----------------------------------------------------------------*/
2163 genMinus (iCode * ic)
2165 int size, offset = 0, samer;
2168 aopOp (IC_LEFT (ic), ic, FALSE);
2169 aopOp (IC_RIGHT (ic), ic, FALSE);
2170 aopOp (IC_RESULT (ic), ic, TRUE);
2172 /* if I can do an decrement instead
2173 of subtract then GOOD for ME */
2174 if (genMinusDec (ic) == TRUE)
2177 size = getDataSize (IC_RESULT (ic));
2178 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2181 aopPut (AOP (IC_RESULT (ic)),
2182 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2184 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2191 emitcode (l, "%s,%s",
2192 aopGet (AOP (IC_RESULT (ic)), offset),
2193 aopGet (AOP (IC_RIGHT (ic)), offset));
2196 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2202 emitcode (l, "%s,%s(%d)",
2203 aopGet (AOP (IC_RESULT (ic)), offset),
2205 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2213 emitcode (l, "%s,%s",
2214 aopGet (AOP (IC_RESULT (ic)), offset),
2215 aopGet (AOP (IC_RIGHT (ic)), offset));
2221 adjustArithmeticResult (ic);
2224 freeAsmop (IC_LEFT (ic), NULL, ic,
2225 (RESULTONSTACK (ic) ? FALSE : TRUE));
2226 freeAsmop (IC_RIGHT (ic), NULL, ic,
2227 (RESULTONSTACK (ic) ? FALSE : TRUE));
2228 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2231 /*-----------------------------------------------------------------*/
2232 /* genMultOneByte : 8 bit multiplication & division */
2233 /*-----------------------------------------------------------------*/
2235 genMultOneByte (operand * left, operand * right, operand * result)
2237 sym_link *opetype = operandType (result);
2241 /* (if two literals, the value is computed before) */
2242 /* if one literal, literal on the right */
2243 if (AOP_TYPE (left) == AOP_LIT) {
2249 size = AOP_SIZE (result);
2251 if (SPEC_USIGN (opetype)) {
2252 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2253 aopGet (AOP (right), 0));
2256 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2257 aopGet (AOP (right), 0));
2259 aopPut (AOP (result), "r0", 0);
2261 aopPut (AOP (result), "r1", 1);
2264 if (SPEC_USIGN (opetype)) {
2266 aopPut (AOP (result), zero, offset++);
2271 lbl = newiTempLabel (NULL);
2272 emitcode ("ldi", "r24,0");
2273 emitcode ("brcc", "L%05d", lbl->key);
2274 emitcode ("ldi", "r24,0xff)");
2275 emitcode ("", "L%05d:", lbl->key);
2277 aopPut (AOP (result), "r24",
2285 /*-----------------------------------------------------------------*/
2286 /* genMult - generates code for multiplication */
2287 /*-----------------------------------------------------------------*/
2289 genMult (iCode * ic)
2291 operand *left = IC_LEFT (ic);
2292 operand *right = IC_RIGHT (ic);
2293 operand *result = IC_RESULT (ic);
2295 /* assign the amsops */
2296 aopOp (left, ic, FALSE);
2297 aopOp (right, ic, FALSE);
2298 aopOp (result, ic, TRUE);
2300 /* if both are of size == 1 */
2301 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2302 genMultOneByte (left, right, result);
2306 /* should have been converted to function call */
2310 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2311 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2312 freeAsmop (result, NULL, ic, TRUE);
2315 /*-----------------------------------------------------------------*/
2316 /* genDiv - generates code for division */
2317 /*-----------------------------------------------------------------*/
2321 /* should have been converted to function call */
2325 /*-----------------------------------------------------------------*/
2326 /* genMod - generates code for division */
2327 /*-----------------------------------------------------------------*/
2331 /* should have been converted to function call */
2343 /*-----------------------------------------------------------------*/
2344 /* revavrcnd - reverse a conditional for avr */
2345 /*-----------------------------------------------------------------*/
2347 revavrcnd (int type)
2359 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2360 if (rar[i].type == type)
2361 return rar[i].rtype;
2362 if (rar[i].rtype == type)
2365 assert (0); /* cannot happen */
2366 return 0; /* makes the compiler happy */
2369 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2370 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2372 /*-----------------------------------------------------------------*/
2373 /* genBranch - generate the branch instruction */
2374 /*-----------------------------------------------------------------*/
2376 genBranch (iCode * ifx, int br_type, int sign)
2378 int tj = (IC_TRUE (ifx) ? 1 : 0);
2380 if (tj) { /* if true jump */
2381 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2382 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2384 else { /* if false jump */
2385 int rtype = revavrcnd (br_type);
2386 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2387 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2392 /*-----------------------------------------------------------------*/
2393 /* genCmp - compare & jump */
2394 /*-----------------------------------------------------------------*/
2396 genCmp (iCode * ic, iCode * ifx, int br_type)
2398 operand *left, *right, *result;
2399 sym_link *letype, *retype;
2401 int sign, size, offset = 0;
2403 left = IC_LEFT (ic);
2404 right = IC_RIGHT (ic);
2405 result = IC_RESULT (ic);
2407 letype = getSpec (operandType (left));
2408 retype = getSpec (operandType (right));
2409 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2411 /* assign the amsops */
2412 aopOp (left, ic, FALSE);
2413 aopOp (right, ic, FALSE);
2414 aopOp (result, ic, TRUE);
2415 size = AOP_SIZE (left);
2419 if (AOP_TYPE (right) == AOP_LIT) {
2420 emitcode ("cpi", "%s,<(%d)",
2421 aopGet (AOP (left), 0),
2423 floatFromVal (AOP (IC_RIGHT (ic))->
2425 genBranch (ifx, br_type, sign);
2427 else { /* right != literal */
2428 emitcode ("cp", "%s,%s",
2429 aopGet (AOP (left), 0),
2430 aopGet (AOP (right), 0));
2431 genBranch (ifx, br_type, sign);
2434 else { /* size != 1 */
2437 emitcode ("cp", "%s,%s",
2438 aopGet (AOP (left), 0),
2439 aopGet (AOP (right), 0));
2441 emitcode ("cpc", "%s,%s",
2442 aopGet (AOP (left), offset),
2443 aopGet (AOP (right),
2447 genBranch (ifx, br_type, sign);
2451 emitcode ("clr", "r0");
2454 emitcode ("cp", "%s,%s",
2455 aopGet (AOP (left), 0),
2456 aopGet (AOP (right), 0));
2458 emitcode ("cpc", "%s,%s",
2459 aopGet (AOP (left), offset),
2460 aopGet (AOP (right), offset));
2463 lbl = newiTempLabel (NULL);
2464 br_type = revavrcnd (br_type);
2466 emitcode (br_uname[br_type], "L%05d", lbl->key);
2468 emitcode (br_name[br_type], "L%05d", lbl->key);
2469 emitcode ("inc", "r0");
2470 emitcode ("", "L%05d:", lbl->key);
2471 aopPut (AOP (result), "r0", 0);
2472 size = AOP_SIZE (result) - 1;
2475 aopPut (AOP (result), zero, offset++);
2478 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2479 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2480 freeAsmop (result, NULL, ic, TRUE);
2483 /*-----------------------------------------------------------------*/
2484 /* genCmpGt :- greater than comparison */
2485 /*-----------------------------------------------------------------*/
2487 genCmpGt (iCode * ic, iCode * ifx)
2489 /* should have transformed by the parser */
2493 /*-----------------------------------------------------------------*/
2494 /* genCmpLt - less than comparisons */
2495 /*-----------------------------------------------------------------*/
2497 genCmpLt (iCode * ic, iCode * ifx)
2499 genCmp (ic, ifx, AVR_LT);
2502 /*-----------------------------------------------------------------*/
2503 /* genCmpEq - generates code for equal to */
2504 /*-----------------------------------------------------------------*/
2506 genCmpEq (iCode * ic, iCode * ifx)
2508 genCmp (ic, ifx, AVR_EQ);
2511 /*-----------------------------------------------------------------*/
2512 /* genCmpNe - generates code for not equal to */
2513 /*-----------------------------------------------------------------*/
2515 genCmpNe (iCode * ic, iCode * ifx)
2517 genCmp (ic, ifx, AVR_NE);
2520 /*-----------------------------------------------------------------*/
2521 /* genCmpGe - generates code for greater than equal to */
2522 /*-----------------------------------------------------------------*/
2524 genCmpGe (iCode * ic, iCode * ifx)
2526 genCmp (ic, ifx, AVR_GE);
2529 /*-----------------------------------------------------------------*/
2530 /* genCmpLe - generates code for less than equal to */
2531 /*-----------------------------------------------------------------*/
2533 genCmpLe (iCode * ic, iCode * ifx)
2535 operand *left = IC_LEFT (ic);
2536 operand *right = IC_RIGHT (ic);
2538 IC_RIGHT (ic) = left;
2539 IC_LEFT (ic) = right;
2540 genCmp (ic, ifx, AVR_GE);
2543 /*-----------------------------------------------------------------*/
2544 /* ifxForOp - returns the icode containing the ifx for operand */
2545 /*-----------------------------------------------------------------*/
2547 ifxForOp (operand * op, iCode * ic)
2549 /* if true symbol then needs to be assigned */
2550 if (IS_TRUE_SYMOP (op))
2553 /* if this has register type condition and
2554 the next instruction is ifx with the same operand
2555 and live to of the operand is upto the ifx only then */
2557 ic->next->op == IFX &&
2558 IC_COND (ic->next)->key == op->key &&
2559 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2564 /*-----------------------------------------------------------------*/
2565 /* genAndOp - for && operation */
2566 /*-----------------------------------------------------------------*/
2568 genAndOp (iCode * ic)
2570 operand *left, *right, *result;
2574 /* note here that && operations that are in an
2575 if statement are taken away by backPatchLabels
2576 only those used in arthmetic operations remain */
2577 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2578 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2579 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2581 tlbl = newiTempLabel (NULL);
2582 toBoolean (left, "r0", TRUE);
2583 toBoolean (right, "r1", TRUE);
2584 emitcode ("and", "r0,r1");
2585 emitcode ("ldi", "r24,1");
2586 emitcode ("breq", "L%05d", tlbl->key);
2587 emitcode ("dec", "r24");
2588 emitcode ("", "L%05d:", tlbl->key);
2589 aopPut (AOP (result), "r24", 0);
2590 size = AOP_SIZE (result) - 1;
2593 aopPut (AOP (result), zero, offset++);
2595 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2596 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2597 freeAsmop (result, NULL, ic, TRUE);
2601 /*-----------------------------------------------------------------*/
2602 /* genOrOp - for || operation */
2603 /*-----------------------------------------------------------------*/
2605 genOrOp (iCode * ic)
2607 operand *left, *right, *result;
2611 /* note here that || operations that are in an
2612 if statement are taken away by backPatchLabels
2613 only those used in arthmetic operations remain */
2614 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2615 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2616 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2618 tlbl = newiTempLabel (NULL);
2619 toBoolean (left, "r0", TRUE);
2620 toBoolean (right, "r0", FALSE);
2621 emitcode ("ldi", "r24,1");
2622 emitcode ("breq", "L%05d", tlbl->key);
2623 emitcode ("dec", "r24");
2624 emitcode ("", "L%05d:", tlbl->key);
2625 aopPut (AOP (result), "r24", 0);
2626 size = AOP_SIZE (result) - 1;
2629 aopPut (AOP (result), zero, offset++);
2631 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2632 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2633 freeAsmop (result, NULL, ic, TRUE);
2637 AVR_AND = 0, AVR_OR, AVR_XOR
2639 static char *bopnames_lit[] = { "andi", "ori" };
2640 static char *bopnames[] = { "and", "or", "eor" };
2641 /*-----------------------------------------------------------------*/
2642 /* genBitWise - generate bitwise operations */
2643 /*-----------------------------------------------------------------*/
2645 genBitWise (iCode * ic, iCode * ifx, int bitop)
2647 operand *left, *right, *result;
2648 int size, offset = 0;
2653 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2654 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2655 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2657 size = AOP_SIZE (left);
2659 if (ifx) { /* used only for jumps */
2660 if (AOP_TYPE (right) == AOP_LIT &&
2661 (bitop == AVR_AND || bitop == AVR_OR)) {
2663 (int) floatFromVal (AOP (right)->aopu.
2665 int p2 = powof2 (lit);
2666 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2667 l = aopGet (AOP (left), p2 / 8);
2668 if (IC_TRUE (ifx)) {
2669 emitcode ("sbrc", "%s,%d", l,
2671 emitcode ("rjmp", "L%05d",
2672 IC_TRUE (ifx)->key);
2675 emitcode ("sbrs", "%s,%d", l,
2677 emitcode ("rjmp", "L%05d",
2678 IC_FALSE (ifx)->key);
2681 else { /* right not power of two */
2682 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2684 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2685 emitcode (bopnames_lit[bitop],
2687 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2690 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2691 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2693 lbl = newiTempLabel (NULL);
2694 if (IC_TRUE (ifx)) {
2695 emitcode ("breq", "L%05d", lbl->key);
2696 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2699 emitcode ("brne", "L%05d", lbl->key);
2700 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2702 emitcode ("", "L%05d:", lbl->key);
2704 else if (size == 2) {
2705 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2706 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2707 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2708 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2709 emitcode ("sbiw", "r24,0");
2710 lbl = newiTempLabel (NULL);
2711 if (IC_TRUE (ifx)) {
2712 emitcode ("breq", "L%05d", lbl->key);
2713 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2716 emitcode ("brne", "L%05d", lbl->key);
2717 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2719 emitcode ("", "L%05d:", lbl->key);
2722 lbl = newiTempLabel (NULL);
2723 lbl1 = newiTempLabel (NULL);
2725 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2726 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2727 aopGet (AOP (IC_LEFT (ic)), offset),
2731 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2733 emitcode ("andi", "r24,<(%d)", lit);
2735 emitcode ("brne", "L%05d", lbl->key);
2740 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2742 emitcode ("rjmp", "L%05d", lbl1->key);
2743 emitcode ("", "L%05d:", lbl->key);
2746 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2747 emitcode ("", "L%05d:", lbl1->key);
2752 else { /* right is not a literal */
2753 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2754 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2757 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2758 aopGet (AOP (IC_RIGHT (ic)), 0));
2761 emitcode (bopnames[bitop], "%s,%s",
2762 aopGet (AOP (IC_RIGHT (ic)), 0),
2763 aopGet (AOP (IC_LEFT (ic)), 0));
2766 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2767 emitcode (bopnames[bitop], "r0,%s",
2768 aopGet (AOP (IC_RIGHT (ic)), 0));
2770 lbl = newiTempLabel (NULL);
2771 if (IC_TRUE (ifx)) {
2772 emitcode ("breq", "L%05d", lbl->key);
2773 emitcode ("rjmp", "L%05d",
2774 IC_TRUE (ifx)->key);
2777 emitcode ("brne", "L%05d", lbl->key);
2778 emitcode ("rjmp", "L%05d",
2779 IC_FALSE (ifx)->key);
2781 emitcode ("", "L%05d:", lbl->key);
2783 else if (size == 2) {
2784 emitcode ("mov", "r24,%s",
2785 aopGet (AOP (IC_LEFT (ic)), 0));
2786 emitcode ("mov", "r25,%s",
2787 aopGet (AOP (IC_LEFT (ic)), 1));
2788 emitcode (bopnames[bitop], "r24,%s",
2789 aopGet (AOP (IC_RIGHT (ic)), 0));
2790 emitcode (bopnames[bitop], "r25,%s",
2791 aopGet (AOP (IC_RIGHT (ic)), 1));
2792 emitcode ("sbiw", "r24,0");
2793 lbl = newiTempLabel (NULL);
2794 if (IC_TRUE (ifx)) {
2795 emitcode ("breq", "L%05d", lbl->key);
2796 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2799 emitcode ("brne", "L%05d", lbl->key);
2800 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2802 emitcode ("", "L%05d:", lbl->key);
2805 lbl = newiTempLabel (NULL);
2806 lbl1 = newiTempLabel (NULL);
2809 emitcode (bopnames[bitop], "%s,%s",
2810 aopGet (AOP (IC_LEFT (ic)), offset),
2811 aopGet (AOP (IC_RIGHT (ic)), offset));
2814 emitcode (bopnames[bitop], "%s,%s",
2815 aopGet (AOP (IC_RIGHT (ic)), offset),
2816 aopGet (AOP (IC_LEFT (ic)), offset));
2819 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2820 emitcode (bopnames[bitop], "r0,%s",
2821 aopGet (AOP (IC_RIGHT (ic)), offset));
2823 emitcode ("brne", "L%05d", lbl->key);
2828 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2830 emitcode ("rjmp", "L%05d", lbl1->key);
2831 emitcode ("", "L%05d:", lbl->key);
2834 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2835 emitcode ("", "L%05d:", lbl1->key);
2842 /* result needs to go a register */
2843 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2844 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2846 if (AOP_TYPE (right) == AOP_LIT) {
2848 (int) floatFromVal (AOP (right)->aopu.
2850 if (((lit >> (8 * offset)) & 0xff) == 0) {
2851 if (bitop == AVR_AND) {
2852 aopPut (AOP (result), zero, offset++);
2855 else if (bitop == AVR_OR) {
2857 aopPut (AOP (result),
2867 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2868 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2869 (bitop == AVR_AND || bitop == AVR_OR)) {
2870 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2871 aopGet (AOP (IC_LEFT (ic)), offset),
2873 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2876 emitcode (bopnames[bitop], "%s,%s",
2877 aopGet (AOP (IC_LEFT (ic)), offset),
2878 aopGet (AOP (IC_RIGHT (ic)), offset));
2882 emitcode (bopnames[bitop], "%s,%s",
2883 aopGet (AOP (IC_RIGHT (ic)), offset),
2884 aopGet (AOP (IC_LEFT (ic)), offset));
2887 aopPut (AOP (IC_RESULT (ic)),
2888 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2889 emitcode (bopnames[bitop],
2890 aopGet (AOP (IC_RESULT (ic)), offset),
2891 aopGet (AOP (IC_RIGHT (ic)), offset));
2896 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2897 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2898 freeAsmop (result, NULL, ic, TRUE);
2901 /*-----------------------------------------------------------------*/
2902 /* genAnd - code for and */
2903 /*-----------------------------------------------------------------*/
2905 genAnd (iCode * ic, iCode * ifx)
2907 genBitWise (ic, ifx, AVR_AND);
2910 /*-----------------------------------------------------------------*/
2911 /* genOr - code for or */
2912 /*-----------------------------------------------------------------*/
2914 genOr (iCode * ic, iCode * ifx)
2916 genBitWise (ic, ifx, AVR_OR);
2919 /*-----------------------------------------------------------------*/
2920 /* genXor - code for xclusive or */
2921 /*-----------------------------------------------------------------*/
2923 genXor (iCode * ic, iCode * ifx)
2925 genBitWise (ic, ifx, AVR_XOR);
2928 /*-----------------------------------------------------------------*/
2929 /* genInline - write the inline code out */
2930 /*-----------------------------------------------------------------*/
2932 genInline (iCode * ic)
2934 char *buffer, *bp, *bp1;
2936 _G.inLine += (!options.asmpeep);
2938 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2939 strcpy (buffer, IC_INLINE (ic));
2941 /* emit each line as a code */
2962 /* emitcode("",buffer); */
2963 _G.inLine -= (!options.asmpeep);
2966 /*-----------------------------------------------------------------*/
2967 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2968 /*-----------------------------------------------------------------*/
2970 genRotC (iCode * ic, int lr)
2972 operand *left, *result;
2973 int size, offset = 0;
2975 /* rotate right with carry */
2976 left = IC_LEFT (ic);
2977 result = IC_RESULT (ic);
2978 aopOp (left, ic, FALSE);
2979 aopOp (result, ic, FALSE);
2981 /* move it to the result */
2982 size = AOP_SIZE (result);
2983 if (!sameRegs (AOP (left), AOP (result))) {
2986 aopPut (AOP (result),
2987 aopGet (AOP (left), offset), offset);
2990 size = AOP_SIZE (result);
2998 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3000 emitcode ("sec", "");
3003 emitcode ((lr ? "ror" : "rol"), "%s",
3004 aopGet (AOP (result), offset));
3010 freeAsmop (left, NULL, ic, TRUE);
3011 freeAsmop (result, NULL, ic, TRUE);
3014 /*-----------------------------------------------------------------*/
3015 /* genRRC - rotate right with carry */
3016 /*-----------------------------------------------------------------*/
3023 /*-----------------------------------------------------------------*/
3024 /* genRLC - generate code for rotate left with carry */
3025 /*-----------------------------------------------------------------*/
3032 /*-----------------------------------------------------------------*/
3033 /* genGetHbit - generates code get highest order bit */
3034 /*-----------------------------------------------------------------*/
3036 genGetHbit (iCode * ic)
3038 operand *left, *result;
3041 left = IC_LEFT (ic);
3042 result = IC_RESULT (ic);
3043 aopOp (left, ic, FALSE);
3044 aopOp (result, ic, FALSE);
3046 size = AOP_SIZE (result);
3047 if (!sameRegs (AOP (left), AOP (result))) {
3048 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3049 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3050 emitcode ("subi", "%s,<(-1)",
3051 aopGet (AOP (result), size - 1));
3054 emitcode ("clr", "r0");
3055 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3056 emitcode ("subi", "r0,<(-1)");
3057 aopPut (AOP (result), "r0", 0);
3062 emitcode ("clr", aopGet (AOP (result), offset++));
3064 freeAsmop (left, NULL, ic, TRUE);
3065 freeAsmop (result, NULL, ic, TRUE);
3068 /*-----------------------------------------------------------------*/
3069 /* genShiftLeftLit - shift left by a known amount */
3070 /*-----------------------------------------------------------------*/
3072 genShiftLeftLit (iCode * ic)
3074 operand *left, *right, *result;
3075 int size, shCount, offset = 0;
3078 right = IC_RIGHT (ic);
3079 left = IC_LEFT (ic);
3080 result = IC_RESULT (ic);
3082 aopOp (left, ic, FALSE);
3083 aopOp (result, ic, FALSE);
3084 size = AOP_SIZE (result);
3085 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3087 if (shCount > (size * 8 - 1)) {
3089 aopPut (AOP (result), zero, offset++);
3094 if (!sameRegs (AOP (left), AOP (result)))
3095 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3097 if (AOP_ISHIGHREG(AOP(result),0)) {
3098 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3099 emitcode ("andi", "%s,0xf0");
3101 emitcode ("ldi","r24,0xf0");
3102 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3103 emitcode ("and", "%s,r24");
3108 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3109 aopGet (AOP (result), 0));
3113 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3116 if (shCount >= 12) {
3117 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3118 aopPut (AOP (result), zero, 0);
3119 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3120 if (AOP_ISHIGHREG(AOP(result),1)) {
3121 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3123 emitcode ("ldi","r24,0xf0");
3124 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3130 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3131 aopPut (AOP (result), zero, 0);
3137 if (!sameRegs (AOP (left), AOP (result))) {
3138 aopPut (AOP (result), aopGet (AOP (left), 0),
3140 aopPut (AOP (result), aopGet (AOP (left), 1),
3143 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3144 emitcode ("andi", "r24,0x0f");
3145 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3146 emitcode("ldi","r25,0xf0");
3148 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3149 if (AOP_ISHIGHREG(AOP(result),0)) {
3150 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3152 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3154 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3155 if (AOP_ISHIGHREG(AOP(result),1)) {
3156 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3158 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3160 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3162 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3163 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3166 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3170 aopPut (AOP (result),
3171 aopGet (AOP (left), offset), offset);
3177 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3180 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3181 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3186 assert ("shifting generic pointer ?\n");
3189 /* 32 bits we do only byte boundaries */
3190 if (shCount >= 24) {
3191 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3192 aopPut (AOP (result), zero, 2);
3193 aopPut (AOP (result), zero, 1);
3194 aopPut (AOP (result), zero, 0);
3198 if (shCount >= 16) {
3199 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3200 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3201 aopPut (AOP (result), zero, 1);
3202 aopPut (AOP (result), zero, 0);
3207 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3208 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3209 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3210 aopPut (AOP (result), zero, 0);
3214 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3217 aopPut (AOP (result),
3218 aopGet (AOP (left), offset), offset);
3222 size = AOP_SIZE (result);
3228 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3229 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3230 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3231 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3236 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3237 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3238 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3243 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3244 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3249 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3257 freeAsmop (left, NULL, ic, TRUE);
3258 freeAsmop (right, NULL, ic, TRUE);
3259 freeAsmop (result, NULL, ic, TRUE);
3262 /*-----------------------------------------------------------------*/
3263 /* genLeftShift - generates code for left shifting */
3264 /*-----------------------------------------------------------------*/
3266 genLeftShift (iCode * ic)
3268 operand *left, *right, *result;
3272 right = IC_RIGHT (ic);
3273 left = IC_LEFT (ic);
3274 result = IC_RESULT (ic);
3276 aopOp (right, ic, FALSE);
3278 if (AOP_TYPE (right) == AOP_LIT) {
3279 genShiftLeftLit (ic);
3284 aopOp (left, ic, FALSE);
3285 aopOp (result, ic, FALSE);
3286 size = AOP_SIZE (result);
3288 if (AOP_SIZE (right) > 1) {
3289 if (isRegPair (AOP (right))) {
3290 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3293 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3294 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3298 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3300 if (!sameRegs (AOP (left), AOP (result))) {
3302 aopPut (AOP (result), aopGet (AOP (left), offset),
3306 size = AOP_SIZE (result);
3308 tlbl = newiTempLabel (NULL);
3309 emitcode ("", "L%05d:", tlbl->key);
3313 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3315 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3318 if (AOP_SIZE (right) > 1)
3319 emitcode ("sbiw", "r24,1");
3321 emitcode ("dec", "r24");
3322 emitcode ("brne", "L%05d", tlbl->key);
3324 freeAsmop (left, NULL, ic, TRUE);
3325 freeAsmop (right, NULL, ic, TRUE);
3326 freeAsmop (result, NULL, ic, TRUE);
3329 /*-----------------------------------------------------------------*/
3330 /* genShiftRightLit - generate for right shift with known count */
3331 /*-----------------------------------------------------------------*/
3333 genShiftRightLit (iCode * ic)
3335 operand *left = IC_LEFT (ic)
3336 , *right = IC_RIGHT (ic)
3337 , *result = IC_RESULT (ic);
3338 int size, shCount, offset = 0;
3340 sym_link *letype = getSpec (operandType (left));
3341 int sign = !SPEC_USIGN (letype);
3343 right = IC_RIGHT (ic);
3344 left = IC_LEFT (ic);
3345 result = IC_RESULT (ic);
3347 aopOp (left, ic, FALSE);
3348 aopOp (result, ic, FALSE);
3349 size = AOP_SIZE (result);
3350 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3352 /* if signed then give up and use a loop to shift */
3355 if (!sameRegs (AOP (left), AOP (result))) {
3357 aopPut (AOP (result),
3358 aopGet (AOP (left), offset), offset);
3361 size = AOP_SIZE (result);
3364 /* be as economical as possible */
3367 size = AOP_SIZE (result);
3370 /* highest order byte */
3371 if (offset == (AOP_SIZE(result)-1))
3372 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3374 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3380 emitcode ("ldi", "r24,<(%d)", shCount);
3381 tlbl = newiTempLabel (NULL);
3382 emitcode ("", "L%05d:", tlbl->key);
3385 if (offset == (AOP_SIZE(result) - 1))
3386 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3388 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3391 emitcode ("dec", "r24");
3392 emitcode ("brne", "L%05d", tlbl->key);
3396 if (shCount > (size * 8 - 1)) {
3398 aopPut (AOP (result), zero, offset++);
3401 /* for unsigned we can much more efficient */
3404 if (!sameRegs (AOP (left), AOP (result)))
3405 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3407 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3408 if (AOP_ISHIGHREG(AOP(result),0)) {
3409 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3411 emitcode ("ldi","r24,0x0f");
3412 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3417 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3420 if (shCount >= 12) {
3421 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3422 aopPut (AOP (result), zero, 1);
3423 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3424 if (AOP_ISHIGHREG(AOP(result),0)) {
3425 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3427 emitcode ("ldi","r24,0x0f");
3428 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3434 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3435 aopPut (AOP (result), zero, 1);
3441 if (!sameRegs (AOP (left), AOP (result))) {
3442 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3443 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3445 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3446 emitcode("ldi","r25,0x0f");
3448 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3449 emitcode ("andi", "r24,0xf0");
3450 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3451 if (AOP_ISHIGHREG(AOP(result),0)) {
3452 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3454 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3456 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3457 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3458 if (AOP_ISHIGHREG(AOP(result),1)) {
3459 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3461 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3464 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3465 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3469 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3473 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3479 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3482 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3483 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3489 assert ("shifting generic pointer ?\n");
3492 /* 32 bits we do only byte boundaries */
3493 if (shCount >= 24) {
3494 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3495 aopPut (AOP (result), zero, 1);
3496 aopPut (AOP (result), zero, 2);
3497 aopPut (AOP (result), zero, 3);
3501 if (shCount >= 16) {
3502 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3503 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3504 aopPut (AOP (result), zero, 2);
3505 aopPut (AOP (result), zero, 3);
3510 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3511 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3512 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3513 aopPut (AOP (result), zero, 3);
3517 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3520 aopPut (AOP (result),
3521 aopGet (AOP (left), offset), offset);
3525 size = AOP_SIZE (result);
3531 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3532 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3533 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3534 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3539 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3540 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3541 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3546 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3547 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3552 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3559 freeAsmop (left, NULL, ic, TRUE);
3560 freeAsmop (right, NULL, ic, TRUE);
3561 freeAsmop (result, NULL, ic, TRUE);
3564 /*-----------------------------------------------------------------*/
3565 /* genRightShift - generate code for right shifting */
3566 /*-----------------------------------------------------------------*/
3568 genRightShift (iCode * ic)
3570 operand *right, *left, *result;
3573 int sign = 0, first = 1;
3576 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3578 if (AOP_TYPE (right) == AOP_LIT) {
3579 genShiftRightLit (ic);
3583 if (AOP_SIZE (right) > 1) {
3584 if (isRegPair (AOP (right))) {
3585 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3588 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3589 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3593 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3595 aopOp (left = IC_LEFT (ic), ic, FALSE);
3596 aopOp (result = IC_RESULT (ic), ic, FALSE);
3597 size = AOP_SIZE (result);
3598 tlbl = newiTempLabel (NULL);
3599 emitcode ("", "L%05d:", tlbl->key);
3601 letype = getSpec (operandType (left));
3602 sign = !SPEC_USIGN (letype);
3603 if (!sameRegs (AOP (left), AOP (result))) {
3605 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3608 size = AOP_SIZE (result);
3610 size = AOP_SIZE (result);
3614 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3616 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3620 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3623 if (AOP_SIZE (right) > 1)
3624 emitcode ("sbiw", "r24,1");
3626 emitcode ("dec", "r24");
3627 emitcode ("brne", "L%05d", tlbl->key);
3629 freeAsmop (left, NULL, ic, TRUE);
3630 freeAsmop (result, NULL, ic, TRUE);
3633 /*-----------------------------------------------------------------*/
3634 /* RRsh - shift right rn by known count */
3635 /*-----------------------------------------------------------------*/
3637 RRsh (int shCount,int reg)
3639 shCount &= 0x0007; // shCount : 0..7
3645 emitcode ("lsr", "r%d",reg);
3648 emitcode ("lsr", "r%d",reg);
3649 emitcode ("lsr", "r%d",reg);
3652 emitcode ("swap", "r%d",reg);
3653 emitcode ("lsl", "r%d",reg);
3656 emitcode ("swap", "r%d",reg);
3659 emitcode ("swap", "r%d",reg);
3660 emitcode ("lsr", "r%d",reg);
3663 emitcode ("swap","r%d",reg);
3664 emitcode ("lsr", "r%d",reg);
3665 emitcode ("lsr", "r%d",reg);
3668 emitcode ("swap","r%d",reg);
3669 emitcode ("lsr", "r%d",reg);
3670 emitcode ("lsr", "r%d",reg);
3671 emitcode ("lsr", "r%d",reg);
3676 /*-----------------------------------------------------------------*/
3677 /* RLsh - shift left rn by known count */
3678 /*-----------------------------------------------------------------*/
3680 RLsh (int shCount, int reg)
3682 shCount &= 0x0007; // shCount : 0..7
3688 emitcode ("lsl", "r%d",reg);
3691 emitcode ("lsl", "r%d",reg);
3692 emitcode ("lsl", "r%d",reg);
3695 emitcode ("swap","r%d",reg);
3696 emitcode ("lsr", "r%d",reg);
3699 emitcode ("swap", "r%d",reg);
3702 emitcode ("swap","r%d",reg);
3703 emitcode ("lsl", "r%d",reg);
3706 emitcode ("swap","r%d",reg);
3707 emitcode ("lsl", "r%d",reg);
3708 emitcode ("lsl", "r%d",reg);
3711 emitcode ("swap","r%d",reg);
3712 emitcode ("lsl", "r%d",reg);
3713 emitcode ("lsl", "r%d",reg);
3714 emitcode ("lsl", "r%d",reg);
3719 /*-----------------------------------------------------------------*/
3720 /* genUnpackBits - generates code for unpacking bits */
3721 /*-----------------------------------------------------------------*/
3723 genUnpackBits (operand * result, char *rname, int ptype)
3731 etype = getSpec (operandType (result));
3732 rsize = getSize (operandType (result));
3733 /* read the first byte */
3740 emitcode ("ld", "r24,%s+", rname);
3744 emitcode ("lpm", "r24,%s+", rname);
3748 emitcode ("call","__gptrget_pi");
3749 emitcode ("mov","r24,r0");
3753 rlen = SPEC_BLEN (etype);
3755 /* if we have bitdisplacement then it fits */
3756 /* into this byte completely or if length is */
3757 /* less than a byte */
3758 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3760 /* shift right acc */
3763 emitcode ("andi", "r24,lo(0x%x)",
3764 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3765 aopPut (AOP (result), "r24", offset++);
3769 /* bit field did not fit in a byte */
3770 aopPut (AOP (result), "r24", offset++);
3780 emitcode ("ld", "r24,%s+");
3784 emitcode ("lpm", "r24,%s+");
3788 emitcode ("call", "__gptrget_pi");
3793 /* if we are done */
3797 aopPut (AOP (result), "r24", offset++);
3802 aopPut (AOP (result), "r24", offset++);
3806 if (offset < rsize) {
3809 aopPut (AOP (result), zero, offset++);
3814 /*-----------------------------------------------------------------*/
3815 /* genDataPointerGet - generates code when ptr offset is known */
3816 /*-----------------------------------------------------------------*/
3818 genDataPointerGet (operand * left, operand * result, iCode * ic)
3822 int size, offset = 0;
3823 aopOp (result, ic, TRUE);
3825 /* get the string representation of the name */
3826 l = aopGet (AOP (left), 0);
3827 size = AOP_SIZE (result);
3830 sprintf (buffer, "(%s + %d)", l, offset);
3832 sprintf (buffer, "%s", l);
3833 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3837 freeAsmop (left, NULL, ic, TRUE);
3838 freeAsmop (result, NULL, ic, TRUE);
3841 /*-----------------------------------------------------------------*/
3842 /* genNearPointerGet - emitcode for near pointer fetch */
3843 /*-----------------------------------------------------------------*/
3845 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3850 char *rname, *frname = NULL;
3851 sym_link *rtype, *retype;
3852 sym_link *ltype = operandType (left);
3854 rtype = operandType (result);
3855 retype = getSpec (rtype);
3857 aopOp (left, ic, FALSE);
3859 /* if left is rematerialisable and
3860 result is not bit variable type and
3861 the left is pointer to data space i.e
3862 lower 128 bytes of space */
3863 if (AOP_TYPE (left) == AOP_IMMD &&
3864 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3865 genDataPointerGet (left, result, ic);
3869 /* if the value is already in a pointer register
3870 then don't need anything more */
3871 if (!AOP_INPREG (AOP (left))) {
3872 /* otherwise get a free pointer register */
3874 preg = getFreePtr (ic, &aop, FALSE, 0);
3875 if (isRegPair (AOP (left) )) {
3876 emitcode ("movw", "%s,%s",
3877 aop->aopu.aop_ptr->name,
3878 aopGet(AOP(left),0));
3880 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3881 aopGet (AOP (left), 0));
3882 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3883 aopGet (AOP (left), 1));
3889 frname = aopGet(aop,0);
3893 } else if (AOP_ISZ(aop)) {
3896 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3897 "pointer not in correct register");
3901 aopOp (result, ic, FALSE);
3903 /* if bitfield then unpack the bits */
3904 if (IS_BITVAR (retype))
3905 genUnpackBits (result, rname, POINTER);
3907 /* we have can just get the values */
3908 int size = AOP_SIZE (result);
3913 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3915 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3920 /* now some housekeeping stuff */
3922 /* we had to allocate for this iCode */
3924 if (isRegPair (AOP (left) )) {
3925 emitcode ("movw", "%s,%s",
3926 aopGet (AOP(left),0),
3927 aop->aopu.aop_ptr->name);
3929 emitcode ("mov", "%s,%s",
3930 aopGet (AOP (left), 0),
3931 aop->aopu.aop_ptr->name);
3932 emitcode ("mov", "%s,%s",
3933 aopGet (AOP (left), 1),
3934 aop->aop_ptr2->name);
3937 freeAsmop (NULL, aop, ic, TRUE);
3940 /* we did not allocate which means left
3941 already in a pointer register, then
3942 if size > 0 && this could be used again
3943 we have to point it back to where it
3945 if ((AOP_SIZE (result) > 1 &&
3946 !OP_SYMBOL (left)->remat &&
3947 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3948 int size = AOP_SIZE (result) - 1;
3949 emitcode ("sbiw", "%s,%d",frname,size);
3954 if (pi) pi->generated = 1;
3955 freeAsmop (left, NULL, ic, TRUE);
3956 freeAsmop (result, NULL, ic, TRUE);
3960 /*-----------------------------------------------------------------*/
3961 /* genCodePointerGet - gget value from code space */
3962 /*-----------------------------------------------------------------*/
3964 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3967 sym_link *retype = getSpec (operandType (result));
3971 aopOp (left, ic, FALSE);
3973 /* if the operand is already in Z register
3974 then we do nothing else we move the value to Z register */
3975 if (AOP_ISZ(AOP(left))) {
3979 getFreePtr(ic,&aop,FALSE,TRUE);
3980 if (isRegPair(AOP (left))) {
3981 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3983 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3984 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3989 aopOp (result, ic, FALSE);
3991 /* if bit then unpack */
3992 if (IS_BITVAR (retype))
3993 genUnpackBits (result, "Z", CPOINTER);
3995 size = AOP_SIZE (result);
4000 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4002 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4007 /* now some housekeeping stuff */
4009 /* we had to allocate for this iCode */
4011 if (isRegPair(AOP (left))) {
4012 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4014 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4015 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4018 freeAsmop (NULL, aop, ic, TRUE);
4021 /* we did not allocate which means left
4022 already in a pointer register, then
4023 if size > 0 && this could be used again
4024 we have to point it back to where it
4026 if ((AOP_SIZE (result) > 1 &&
4027 !OP_SYMBOL (left)->remat &&
4028 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4030 int size = AOP_SIZE (result) - 1;
4031 emitcode ("sbiw", "r30,%d",size);
4036 if (pi) pi->generated=1;
4037 freeAsmop (left, NULL, ic, TRUE);
4038 freeAsmop (result, NULL, ic, TRUE);
4042 /*-----------------------------------------------------------------*/
4043 /* genGenPointerGet - gget value from generic pointer space */
4044 /*-----------------------------------------------------------------*/
4046 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4050 sym_link *retype = getSpec (operandType (result));
4053 aopOp (left, ic, FALSE);
4055 /* if the operand is already in dptr
4056 then we do nothing else we move the value to dptr */
4057 if (AOP_ISZ(AOP(left))) {
4061 getFreePtr(ic,&aop,FALSE,TRUE);
4062 if (isRegPair(AOP(left))) {
4063 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4065 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4066 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4068 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4072 /* so Z register now contains the address */
4074 aopOp (result, ic, FALSE);
4076 /* if bit then unpack */
4077 if (IS_BITVAR (retype))
4078 genUnpackBits (result, "Z", GPOINTER);
4080 size = AOP_SIZE (result);
4085 emitcode ("call", "__gptrget_pi");
4087 emitcode ("call", "__gptrget");
4088 aopPut (AOP (result), "r0", offset++);
4093 /* now some housekeeping stuff */
4095 /* we had to allocate for this iCode */
4097 if (isRegPair(AOP (left))) {
4098 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4100 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4101 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4104 freeAsmop (NULL, aop, ic, TRUE);
4107 /* we did not allocate which means left
4108 already in a pointer register, then
4109 if size > 0 && this could be used again
4110 we have to point it back to where it
4112 if ((AOP_SIZE (result) > 1 &&
4113 !OP_SYMBOL (left)->remat &&
4114 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4116 int size = AOP_SIZE (result) - 1;
4117 emitcode ("sbiw", "r30,%d",size);
4120 if (pi) pi->generated=1;
4121 freeAsmop (left, NULL, ic, TRUE);
4122 freeAsmop (result, NULL, ic, TRUE);
4125 /*-----------------------------------------------------------------*/
4126 /* genPointerGet - generate code for pointer get */
4127 /*-----------------------------------------------------------------*/
4129 genPointerGet (iCode * ic, iCode *pi)
4131 operand *left, *result;
4132 sym_link *type, *etype;
4135 left = IC_LEFT (ic);
4136 result = IC_RESULT (ic);
4138 /* depending on the type of pointer we need to
4139 move it to the correct pointer register */
4140 type = operandType (left);
4141 etype = getSpec (type);
4142 /* if left is of type of pointer then it is simple */
4143 if (IS_PTR (type) && !IS_FUNC (type->next))
4144 p_type = DCL_TYPE (type);
4146 /* we have to go by the storage class */
4147 p_type = PTR_TYPE (SPEC_OCLS (etype));
4152 /* now that we have the pointer type we assign
4153 the pointer values */
4160 genMemPointerGet (left, result, ic, pi);
4164 genCodePointerGet (left, result, ic, pi);
4168 genGenPointerGet (left, result, ic, pi);
4174 /*-----------------------------------------------------------------*/
4175 /* genPackBits - generates code for packed bit storage */
4176 /*-----------------------------------------------------------------*/
4178 genPackBits (sym_link * etype,
4180 char *rname, int p_type)
4188 blen = SPEC_BLEN (etype);
4189 bstr = SPEC_BSTR (etype);
4191 l = aopGet (AOP (right), offset++);
4194 /* if the bit lenth is less than or */
4195 /* it exactly fits a byte then */
4196 if (SPEC_BLEN (etype) <= 8) {
4197 shCount = SPEC_BSTR (etype);
4199 /* shift left acc */
4202 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4209 emitcode ("ld", "r1,%s",rname);
4213 emitcode ("push", "r1");
4214 emitcode ("push", "r24");
4215 emitcode ("call", "__gptrget");
4216 emitcode ("pop", "r1");
4217 emitcode ("mov","r24,r0");
4221 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4222 ((unsigned char) (0xFF << (blen + bstr)) |
4223 (unsigned char) (0xFF >> (8 - bstr))));
4224 emitcode ("or", "r24,r1");
4225 if (p_type == GPOINTER)
4226 emitcode ("pop", "r1");
4235 emitcode("st","%s+,r24");
4239 emitcode("mov","r0,r24");
4240 emitcode ("call", "__gptrput_pi");
4245 if (SPEC_BLEN (etype) <= 8)
4248 rLen = SPEC_BLEN (etype);
4250 /* now generate for lengths greater than one byte */
4253 l = aopGet (AOP (right), offset++);
4264 emitcode ("st", "%s+,%s",rname,l);
4269 emitcode ("lcall", "__gptrput_pi");
4276 /* last last was not complete */
4278 /* save the byte & read byte */
4284 emitcode ("st","%s+,r24",rname);
4287 emitcode ("push", "r1");
4288 emitcode ("push", "r24");
4289 emitcode ("lcall", "__gptrget");
4290 emitcode ("mov","r24,r0");
4291 emitcode ("pop", "r1");
4295 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4296 emitcode ("or", "r24,r1");
4299 if (p_type == GPOINTER)
4300 emitcode ("pop", "r1");
4308 emitcode ("st", "%s,r24", rname);
4312 emitcode ("mov","r0,r24");
4313 emitcode ("call", "__gptrput");
4318 /*-----------------------------------------------------------------*/
4319 /* genDataPointerSet - remat pointer to data space */
4320 /*-----------------------------------------------------------------*/
4322 genDataPointerSet (operand * right, operand * result, iCode * ic)
4324 int size, offset = 0;
4325 char *l, buffer[256];
4327 aopOp (right, ic, FALSE);
4329 l = aopGet (AOP (result), 0);
4330 size = AOP_SIZE (right);
4333 sprintf (buffer, "(%s + %d)", l, offset);
4335 sprintf (buffer, "%s", l);
4336 emitcode ("sts", "%s,%s", buffer,
4337 aopGet (AOP (right), offset++));
4340 freeAsmop (right, NULL, ic, TRUE);
4341 freeAsmop (result, NULL, ic, TRUE);
4344 /*-----------------------------------------------------------------*/
4345 /* genNearPointerSet - emitcode for near pointer put */
4346 /*-----------------------------------------------------------------*/
4348 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4351 char *frname = NULL, *rname, *l;
4354 sym_link *ptype = operandType (result);
4356 retype = getSpec (operandType (right));
4358 aopOp (result, ic, FALSE);
4360 /* if the result is rematerializable &
4361 in data space & not a bit variable */
4362 if (AOP_TYPE (result) == AOP_IMMD &&
4363 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4364 genDataPointerSet (right, result, ic);
4367 if (!AOP_INPREG(AOP(result))) {
4368 /* otherwise get a free pointer register */
4370 getFreePtr (ic, &aop, FALSE, 0);
4371 if (isRegPair (AOP (result) )) {
4372 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4373 aopGet(AOP (result), 0));
4375 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4376 aopGet (AOP (result), 0));
4377 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4378 aopGet (AOP (result), 1));
4383 frname = aopGet(aop,0);
4386 aopOp (right, ic, FALSE);
4389 } else if (AOP_ISZ(aop)) {
4392 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4393 "pointer not in correct register");
4396 /* if bitfield then unpack the bits */
4397 if (IS_BITVAR (retype))
4398 genPackBits (retype, right, rname, POINTER);
4400 /* we have can just get the values */
4401 int size = AOP_SIZE (right);
4405 l = aopGet (AOP (right), offset);
4407 emitcode ("st", "%s+,%s", rname,l);
4409 emitcode ("st", "%s,%s", rname,l);
4414 /* now some housekeeping stuff */
4416 /* we had to allocate for this iCode */
4418 if (isRegPair (AOP (result) )) {
4419 emitcode ("movw", "%s,%s",
4420 aopGet(AOP(result),0),
4421 aop->aopu.aop_ptr->name);
4423 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4424 aopGet (AOP (result), 0));
4425 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4426 aopGet (AOP (result), 1));
4429 freeAsmop (NULL, aop, ic, TRUE);
4432 /* we did not allocate which means left
4433 already in a pointer register, then
4434 if size > 0 && this could be used again
4435 we have to point it back to where it
4437 if ((AOP_SIZE (right) > 1 &&
4438 !OP_SYMBOL (result)->remat &&
4439 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4440 int size = AOP_SIZE (right) - 1;
4441 emitcode ("sbiw", "%s,%d",frname,size);
4446 if (pi) pi->generated = 1;
4447 freeAsmop (result, NULL, ic, TRUE);
4448 freeAsmop (right, NULL, ic, TRUE);
4451 /*-----------------------------------------------------------------*/
4452 /* genGenPointerSet - set value from generic pointer space */
4453 /*-----------------------------------------------------------------*/
4455 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4459 sym_link *retype = getSpec (operandType (right));
4462 aopOp (result, ic, FALSE);
4464 /* if the operand is already in dptr
4465 then we do nothing else we move the value to dptr */
4466 if (AOP_ISZ(AOP(result))) {
4470 getFreePtr(ic,&aop,FALSE,TRUE);
4471 if (isRegPair(AOP(result))) {
4472 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4474 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4475 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4477 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4481 /* so Z register now contains the address */
4482 aopOp (right, ic, FALSE);
4484 /* if bit then unpack */
4485 if (IS_BITVAR (retype))
4486 genUnpackBits (result, "Z", GPOINTER);
4488 size = AOP_SIZE (right);
4492 char *l = aopGet(AOP (right), offset++);
4496 emitcode ("call", "__gptrput_pi");
4498 emitcode ("call", "__gptrput");
4502 /* now some housekeeping stuff */
4504 /* we had to allocate for this iCode */
4506 if (isRegPair(AOP(result))) {
4507 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4509 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4510 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4513 freeAsmop (NULL, aop, ic, TRUE);
4516 /* we did not allocate which means left
4517 already in a pointer register, then
4518 if size > 0 && this could be used again
4519 we have to point it back to where it
4521 if ((AOP_SIZE (right) > 1 &&
4522 !OP_SYMBOL (result)->remat &&
4523 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4524 int size = AOP_SIZE (right) - 1;
4525 emitcode ("sbiw", "r30,%d",size);
4528 if (pi) pi->generated = 1;
4529 freeAsmop (right, NULL, ic, TRUE);
4530 freeAsmop (result, NULL, ic, TRUE);
4533 /*-----------------------------------------------------------------*/
4534 /* genPointerSet - stores the value into a pointer location */
4535 /*-----------------------------------------------------------------*/
4537 genPointerSet (iCode * ic, iCode *pi)
4539 operand *right, *result;
4540 sym_link *type, *etype;
4543 right = IC_RIGHT (ic);
4544 result = IC_RESULT (ic);
4546 /* depending on the type of pointer we need to
4547 move it to the correct pointer register */
4548 type = operandType (result);
4549 etype = getSpec (type);
4550 /* if left is of type of pointer then it is simple */
4551 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4552 p_type = DCL_TYPE (type);
4555 /* we have to go by the storage class */
4556 p_type = PTR_TYPE (SPEC_OCLS (etype));
4560 /* now that we have the pointer type we assign
4561 the pointer values */
4568 genMemPointerSet (right, result, ic, pi);
4572 genGenPointerSet (right, result, ic, pi);
4576 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4577 "genPointerSet: illegal pointer type");
4582 /*-----------------------------------------------------------------*/
4583 /* genIfx - generate code for Ifx statement */
4584 /*-----------------------------------------------------------------*/
4586 genIfx (iCode * ic, iCode * popIc)
4588 operand *cond = IC_COND (ic);
4593 aopOp (cond, ic, FALSE);
4595 /* get the value into acc */
4596 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4597 cname = aopGet(AOP(cond),0);
4599 toBoolean (cond, "r24", 0);
4603 /* the result is now in the accumulator */
4604 freeAsmop (cond, NULL, ic, TRUE);
4606 /* if there was something to be popped then do it */
4609 emitcode("cpi","%s,0",cname);
4610 } else if (!tob) emitcode("cpi","%s,0",cname);
4612 lbl = newiTempLabel(NULL);
4614 emitcode ("breq","L%05d",lbl->key);
4615 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4616 emitcode ("","L%05d:",lbl->key);
4618 emitcode ("brne","L%05d",lbl->key);
4619 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4620 emitcode ("","L%05d:",lbl->key);
4625 /*-----------------------------------------------------------------*/
4626 /* genAddrOf - generates code for address of */
4627 /*-----------------------------------------------------------------*/
4629 genAddrOf (iCode * ic)
4631 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4634 aopOp (IC_RESULT (ic), ic, FALSE);
4635 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4636 /* if the operand is on the stack then we
4637 need to get the stack offset of this
4640 /* if it has an offset then we need to compute it */
4642 if (allHigh(AOP(IC_RESULT(ic)))) {
4643 if (isRegPair (AOP(IC_RESULT(ic)))) {
4644 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4646 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4647 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4649 if (sym->stack < 0) {
4650 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4651 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4653 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4654 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4657 emitcode("movw","r24,r28");
4658 if (sym->stack > -63 && sym->stack < 63) {
4660 emitcode("sbiw","r24,%d",-sym->stack);
4662 emitcode("sbiw","r24,%d",sym->stack);
4664 if (sym->stack < 0) {
4665 emitcode("subi","r24,<(%d)",-sym->stack);
4666 emitcode("sbci","r25,>(%d)",-sym->stack);
4668 emitcode("subi","r24,<(-%d)",sym->stack);
4669 emitcode("sbci","r25,>(-%d)",sym->stack);
4673 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4674 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4678 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4679 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4681 /* fill the result with zero */
4682 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4685 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4691 /* object not on stack then we need the name */
4692 size = AOP_SIZE (IC_RESULT (ic));
4696 char s[SDCC_NAME_MAX];
4698 sprintf (s, ">(%s)", sym->rname);
4700 sprintf (s, "<(%s)", sym->rname);
4701 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4705 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4709 /*-----------------------------------------------------------------*/
4710 /* genFarFarAssign - assignment when both are in far space */
4711 /*-----------------------------------------------------------------*/
4713 genFarFarAssign (operand * result, operand * right, iCode * ic)
4715 int size = AOP_SIZE (right);
4718 /* first push the right side on to the stack */
4720 l = aopGet (AOP (right), offset++);
4722 emitcode ("push", "acc");
4725 freeAsmop (right, NULL, ic, FALSE);
4726 /* now assign DPTR to result */
4727 aopOp (result, ic, FALSE);
4728 size = AOP_SIZE (result);
4730 emitcode ("pop", "acc");
4731 aopPut (AOP (result), "a", --offset);
4733 freeAsmop (result, NULL, ic, FALSE);
4737 /*-----------------------------------------------------------------*/
4738 /* genAssign - generate code for assignment */
4739 /*-----------------------------------------------------------------*/
4741 genAssign (iCode * ic)
4743 operand *result, *right;
4745 unsigned long lit = 0L;
4747 result = IC_RESULT (ic);
4748 right = IC_RIGHT (ic);
4750 /* if they are the same */
4751 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4754 aopOp (right, ic, FALSE);
4756 /* special case both in far space */
4757 if (AOP_TYPE (right) == AOP_DPTR &&
4758 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4760 genFarFarAssign (result, right, ic);
4764 aopOp (result, ic, TRUE);
4766 /* if they are the same registers */
4767 if (sameRegs (AOP (right), AOP (result)))
4770 /* if the result is a bit */
4771 if (AOP_TYPE (result) == AOP_CRY) {
4773 /* if the right size is a literal then
4774 we know what the value is */
4775 if (AOP_TYPE (right) == AOP_LIT) {
4776 if (((int) operandLitValue (right)))
4777 aopPut (AOP (result), one, 0);
4779 aopPut (AOP (result), zero, 0);
4783 /* the right is also a bit variable */
4784 if (AOP_TYPE (right) == AOP_CRY) {
4785 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4786 aopPut (AOP (result), "c", 0);
4791 toBoolean (right, "", 0);
4792 aopPut (AOP (result), "a", 0);
4796 /* bit variables done */
4798 size = AOP_SIZE (result);
4800 if (AOP_TYPE (right) == AOP_LIT)
4802 (unsigned long) floatFromVal (AOP (right)->aopu.
4804 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4805 && (AOP_TYPE (right) == AOP_LIT)
4806 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4807 emitcode ("clr", "a");
4809 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4810 0) aopPut (AOP (result), "a", size);
4812 aopPut (AOP (result),
4813 aopGet (AOP (right), size), size);
4818 aopPut (AOP (result),
4819 aopGet (AOP (right), offset), offset);
4825 freeAsmop (right, NULL, ic, FALSE);
4826 freeAsmop (result, NULL, ic, TRUE);
4829 /*-----------------------------------------------------------------*/
4830 /* genJumpTab - genrates code for jump table */
4831 /*-----------------------------------------------------------------*/
4833 genJumpTab (iCode * ic)
4838 aopOp (IC_JTCOND (ic), ic, FALSE);
4839 /* get the condition into accumulator */
4840 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4842 /* multiply by three */
4843 emitcode ("add", "a,acc");
4844 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4845 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4847 jtab = newiTempLabel (NULL);
4848 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4849 emitcode ("jmp", "@a+dptr");
4850 emitcode ("", "%05d$:", jtab->key + 100);
4851 /* now generate the jump labels */
4852 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4853 jtab = setNextItem (IC_JTLABELS (ic)))
4854 emitcode ("ljmp", "%05d$", jtab->key + 100);
4858 /*-----------------------------------------------------------------*/
4859 /* genCast - gen code for casting */
4860 /*-----------------------------------------------------------------*/
4862 genCast (iCode * ic)
4864 operand *result = IC_RESULT (ic);
4865 sym_link *ctype = operandType (IC_LEFT (ic));
4866 sym_link *rtype = operandType (IC_RIGHT (ic));
4867 operand *right = IC_RIGHT (ic);
4870 /* if they are equivalent then do nothing */
4871 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4874 aopOp (right, ic, FALSE);
4875 aopOp (result, ic, FALSE);
4877 /* if the result is a bit */
4878 if (AOP_TYPE (result) == AOP_CRY) {
4879 /* if the right size is a literal then
4880 we know what the value is */
4881 if (AOP_TYPE (right) == AOP_LIT) {
4882 if (((int) operandLitValue (right)))
4883 aopPut (AOP (result), one, 0);
4885 aopPut (AOP (result), zero, 0);
4890 /* the right is also a bit variable */
4891 if (AOP_TYPE (right) == AOP_CRY) {
4892 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4893 aopPut (AOP (result), "c", 0);
4898 toBoolean (right, "", 0);
4899 aopPut (AOP (result), "a", 0);
4903 /* if they are the same size : or less */
4904 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4906 /* if they are in the same place */
4907 if (sameRegs (AOP (right), AOP (result)))
4910 /* if they in different places then copy */
4911 size = AOP_SIZE (result);
4914 aopPut (AOP (result),
4915 aopGet (AOP (right), offset), offset);
4922 /* if the result is of type pointer */
4923 if (IS_PTR (ctype)) {
4926 sym_link *type = operandType (right);
4927 sym_link *etype = getSpec (type);
4929 /* pointer to generic pointer */
4930 if (IS_GENPTR (ctype)) {
4932 p_type = DCL_TYPE (type);
4934 /* we have to go by the storage class */
4935 p_type = PTR_TYPE (SPEC_OCLS (etype));
4938 /* the first two bytes are known */
4939 size = GPTRSIZE - 1;
4942 aopPut (AOP (result),
4943 aopGet (AOP (right), offset), offset);
4947 /* the last byte depending on type */
4949 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
4954 // pointerTypeToGPByte will have bitched.
4958 sprintf(gpValStr, "#0x%d", gpVal);
4959 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
4964 /* just copy the pointers */
4965 size = AOP_SIZE (result);
4968 aopPut (AOP (result),
4969 aopGet (AOP (right), offset), offset);
4975 /* so we now know that the size of destination is greater
4976 than the size of the source */
4977 /* we move to result for the size of source */
4978 size = AOP_SIZE (right);
4981 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4985 /* now depending on the sign of the source && destination */
4986 size = AOP_SIZE (result) - AOP_SIZE (right);
4987 /* if unsigned or not an integral type */
4988 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4990 aopPut (AOP (result), zero, offset++);
4993 /* we need to extend the sign :{ */
4994 // PENDING: Does nothing on avr
4996 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4999 emitcode ("rlc", "a");
5000 emitcode ("subb", "a,acc");
5002 aopPut (AOP (result), "a", offset++);
5005 /* we are done hurray !!!! */
5008 freeAsmop (right, NULL, ic, TRUE);
5009 freeAsmop (result, NULL, ic, TRUE);
5013 /*-----------------------------------------------------------------*/
5014 /* genDjnz - generate decrement & jump if not zero instrucion */
5015 /*-----------------------------------------------------------------*/
5017 genDjnz (iCode * ic, iCode * ifx)
5023 /* if the if condition has a false label
5024 then we cannot save */
5028 /* if the minus is not of the form
5030 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5031 !IS_OP_LITERAL (IC_RIGHT (ic)))
5034 if (operandLitValue (IC_RIGHT (ic)) != 1)
5037 /* if the size of this greater than one then no
5039 if (getSize (operandType (IC_RESULT (ic))) > 1)
5042 /* otherwise we can save BIG */
5043 lbl = newiTempLabel (NULL);
5044 lbl1 = newiTempLabel (NULL);
5046 aopOp (IC_RESULT (ic), ic, FALSE);
5048 if (IS_AOP_PREG (IC_RESULT (ic))) {
5049 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5050 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5051 emitcode ("jnz", "%05d$", lbl->key + 100);
5054 emitcode ("djnz", "%s,%05d$",
5055 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5057 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5058 emitcode ("", "%05d$:", lbl->key + 100);
5059 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5060 emitcode ("", "%05d$:", lbl1->key + 100);
5062 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5067 static char *recvregs[8] = {
5068 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5071 static int recvCnt = 0;
5073 /*-----------------------------------------------------------------*/
5074 /* genReceive - generate code for a receive iCode */
5075 /*-----------------------------------------------------------------*/
5077 genReceive (iCode * ic)
5079 int size, offset = 0;
5080 aopOp (IC_RESULT (ic), ic, FALSE);
5081 size = AOP_SIZE (IC_RESULT (ic));
5083 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5086 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5089 /*-----------------------------------------------------------------*/
5090 /* gen51Code - generate code for 8051 based controllers */
5091 /*-----------------------------------------------------------------*/
5093 genAVRCode (iCode * lic)
5098 lineHead = lineCurr = NULL;
5100 /* print the allocation information */
5102 printAllocInfo (currFunc, codeOutFile);
5103 /* if debug information required */
5104 /* if (options.debug && currFunc) { */
5106 debugFile->writeFunction(currFunc);
5108 /* emitcode ("", ".type %s,@function", currFunc->name); */
5111 /* stack pointer name */
5115 for (ic = lic; ic; ic = ic->next) {
5117 if (cln != ic->lineno) {
5118 if (options.debug) {
5120 emitcode ("", "C$%s$%d$%d$%d ==.",
5121 FileBaseName (ic->filename),
5122 ic->lineno, ic->level, ic->block);
5125 emitcode (";", "%s %d", ic->filename, ic->lineno);
5128 /* if the result is marked as
5129 spilt and rematerializable or code for
5130 this has already been generated then
5132 if (resultRemat (ic) || ic->generated)
5135 /* depending on the operation */
5154 /* IPOP happens only when trying to restore a
5155 spilt live range, if there is an ifx statement
5156 following this pop then the if statement might
5157 be using some of the registers being popped which
5158 would destory the contents of the register so
5159 we need to check for this condition and handle it */
5161 ic->next->op == IFX &&
5162 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5163 genIfx (ic->next, ic);
5181 genEndFunction (ic);
5201 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5218 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5222 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5226 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5230 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5234 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5238 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5250 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5254 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5258 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5285 case GET_VALUE_AT_ADDRESS:
5286 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5290 if (POINTER_SET (ic))
5291 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5317 addSet (&_G.sendSet, ic);
5326 /* now we are ready to call the
5327 peep hole optimizer */
5328 if (!options.nopeep)
5329 peepHole (&lineHead);
5331 /* now do the actual printing */
5332 printLine (lineHead, codeOutFile);