1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
34 #ifdef HAVE_SYS_ISA_DEFS_H
35 #include <sys/isa_defs.h>
40 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
41 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
42 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
48 #include "SDCCpeeph.h"
52 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "0x00";
61 static char *one = "0x01";
64 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
65 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
66 char **fAVRReturn = fReturnAVR;
67 static short rbank = -1;
68 static char *larray[4] = { "lo8", "hi8", "hlo8", "hhi8" };
69 static char *tscr[4] = { "r0", "r1", "r24", "r25" };
80 extern int avr_ptrRegReq;
82 extern FILE *codeOutFile;
83 static void saverbank (int, iCode *, bool);
84 #define RESULTONSTACK(x) \
85 (IC_RESULT(x) && IC_RESULT(x)->aop && \
86 IC_RESULT(x)->aop->type == AOP_STK )
88 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
89 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
90 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
91 #define CLRC emitcode("clc","")
92 #define SETC emitcode("stc","")
94 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00
102 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, char *fmt, ...)
118 char lb[MAX_INLINEASM];
125 sprintf (lb, "%s\t", inst);
127 sprintf (lb, "%s", inst);
128 vsprintf (lb + (strlen (lb)), fmt, ap);
131 vsprintf (lb, fmt, ap);
133 while (isspace (*lbp))
137 lineCurr = (lineCurr ?
138 connectLine (lineCurr, newLineNode (lb)) :
139 (lineHead = newLineNode (lb)));
140 lineCurr->isInline = _G.inLine;
141 lineCurr->isDebug = _G.debugLine;
145 /*-----------------------------------------------------------------*/
146 /* hasInc - operand is incremented before any other use */
147 /*-----------------------------------------------------------------*/
149 hasInc (operand *op, iCode *ic)
151 sym_link *type = operandType(op);
152 sym_link *retype = getSpec (type);
153 iCode *lic = ic->next;
156 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
157 isize = getSize(type->next);
159 /* if operand of the form op = op + <sizeof *op> */
160 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
161 isOperandEqual(IC_RESULT(lic),op) &&
162 isOperandLiteral(IC_RIGHT(lic)) &&
163 operandLitValue(IC_RIGHT(lic)) == isize) {
166 /* if the operand used or deffed */
167 if (bitVectBitValue(ic->uses,op->key) || ((unsigned) ic->defKey == op->key)) {
175 /*-----------------------------------------------------------------*/
176 /* getFreePtr - returns X or Z whichever is free or can be pushed */
177 /*-----------------------------------------------------------------*/
179 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
181 bool xiu = FALSE, ziu = FALSE;
182 bool xou = FALSE, zou = FALSE;
184 /* the logic: if x & z used in the instruction
185 then we are in trouble otherwise */
187 /* first check if x & z are used by this
188 instruction, in which case we are in trouble */
189 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
190 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
194 xou = bitVectBitValue (ic->rMask, X_IDX);
195 zou = bitVectBitValue (ic->rMask, Z_IDX);
197 /* if no usage of Z then return it */
199 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
200 (*aopp)->type = AOP_Z;
202 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
203 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
206 /* if no usage of X then return it */
207 if (!xiu && !xou && !zonly) {
208 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
209 (*aopp)->type = AOP_X;
211 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
212 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
215 /* if z not used then */
218 /* push it if not already pushed */
220 emitcode ("push", "%s",
221 avr_regWithIdx (R30_IDX)->dname);
222 emitcode ("push", "%s",
223 avr_regWithIdx (R31_IDX)->dname);
227 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
228 (*aopp)->type = AOP_Z;
229 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
230 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
233 /* now we know they both have usage */
234 /* if x not used in this instruction */
235 if (!xiu && !zonly) {
236 /* push it if not already pushed */
238 emitcode ("push", "%s",
239 avr_regWithIdx (R26_IDX)->dname);
240 emitcode ("push", "%s",
241 avr_regWithIdx (R27_IDX)->dname);
245 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
246 (*aopp)->type = AOP_X;
248 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
249 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
254 /* I said end of world but not quite end of world yet */
255 /* if this is a result then we can push it on the stack */
257 (*aopp)->type = AOP_STK;
261 /* other wise this is true end of the world */
262 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
263 "getFreePtr should never reach here");
267 /*-----------------------------------------------------------------*/
268 /* newAsmop - creates a new asmOp */
269 /*-----------------------------------------------------------------*/
271 newAsmop (short type)
275 aop = Safe_calloc (1, sizeof (asmop));
280 /*-----------------------------------------------------------------*/
281 /* pointerCode - returns the code for a pointer type */
282 /*-----------------------------------------------------------------*/
284 pointerCode (sym_link * etype)
287 return PTR_TYPE (SPEC_OCLS (etype));
291 /*-----------------------------------------------------------------*/
292 /* aopForSym - for a true symbol */
293 /*-----------------------------------------------------------------*/
295 aopForSym (iCode * ic, symbol * sym, bool result)
298 memmap *space = SPEC_OCLS (sym->etype);
300 /* if already has one */
304 /* assign depending on the storage class */
305 /* if it is on the stack */
307 sym->aop = aop = newAsmop (0);
308 aop->size = getSize (sym->type);
310 /* we can use std / ldd instruction */
312 && (sym->stack + getSize (sym->type) - 1) <= 63) {
313 aop->type = AOP_STK_D;
314 aop->aopu.aop_stk = sym->stack;
318 /* otherwise get a free pointer register X/Z */
319 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
321 /* now assign the address of the variable to
322 the pointer register */
323 if (aop->type != AOP_STK) {
324 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
325 if (sym->stack < 0) {
326 if ((sym->stack - _G.nRegsSaved) > -63) {
327 emitcode ("sbiw", "%s,0x%02x",
328 aop->aopu.aop_ptr->name,
333 emitcode ("subi", "%s,lo8(%d)",
334 aop->aopu.aop_ptr->name,
335 sym->stack - _G.nRegsSaved);
336 emitcode ("sbci", "%s,hi8(%d)",
338 sym->stack - _G.nRegsSaved);
342 if (sym->stack <= 63) {
343 emitcode ("adiw", "%s,0x%02x",
344 aop->aopu.aop_ptr->name,
348 emitcode ("subi", "%s,lo8(-%d)",
349 aop->aopu.aop_ptr->name,
351 emitcode ("sbci", "%s,hi8(-%d)",
360 /* if in bit space */
361 if (IN_BITSPACE (space)) {
362 sym->aop = aop = newAsmop (AOP_CRY);
363 aop->aopu.aop_dir = sym->rname;
364 aop->size = getSize (sym->type);
367 /* if it is in direct space */
368 if (IN_DIRSPACE (space)) {
369 sym->aop = aop = newAsmop (AOP_DIR);
370 aop->aopu.aop_dir = sym->rname;
371 aop->size = getSize (sym->type);
375 /* special case for a function */
376 if (IS_FUNC (sym->type)) {
377 sym->aop = aop = newAsmop (AOP_IMMD);
378 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
379 strcpy (aop->aopu.aop_immd, sym->rname);
380 aop->size = FPTRSIZE;
384 /* only remaining is code / eeprom which will need pointer reg */
385 /* if it is in code space */
387 sym->aop = aop = newAsmop (0);
389 if (IN_CODESPACE (space))
392 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
393 aop->size = getSize (sym->type);
394 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
395 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
400 /*-----------------------------------------------------------------*/
401 /* aopForRemat - rematerialzes an object */
402 /*-----------------------------------------------------------------*/
404 aopForRemat (symbol * sym)
406 iCode *ic = sym->rematiCode;
407 asmop *aop = newAsmop (AOP_IMMD);
412 val += (int) operandLitValue (IC_RIGHT (ic));
413 else if (ic->op == '-')
414 val -= (int) operandLitValue (IC_RIGHT (ic));
418 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
422 sprintf (buffer, "(%s %c 0x%04x)",
423 OP_SYMBOL (IC_LEFT (ic))->rname,
424 val >= 0 ? '+' : '-', abs (val) & 0xffff);
426 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
428 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
429 strcpy (aop->aopu.aop_immd, buffer);
433 /*-----------------------------------------------------------------*/
434 /* regsInCommon - two operands have some registers in common */
435 /*-----------------------------------------------------------------*/
437 regsInCommon (operand * op1, operand * op2)
442 /* if they have registers in common */
443 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
446 sym1 = OP_SYMBOL (op1);
447 sym2 = OP_SYMBOL (op2);
449 if (sym1->nRegs == 0 || sym2->nRegs == 0)
452 for (i = 0; i < sym1->nRegs; i++) {
457 for (j = 0; j < sym2->nRegs; j++) {
461 if (sym2->regs[j] == sym1->regs[i])
469 /*-----------------------------------------------------------------*/
470 /* operandsEqu - equivalent */
471 /*-----------------------------------------------------------------*/
473 operandsEqu (operand * op1, operand * op2)
477 /* if they not symbols */
478 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
481 sym1 = OP_SYMBOL (op1);
482 sym2 = OP_SYMBOL (op2);
484 /* if both are itemps & one is spilt
485 and the other is not then false */
486 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
487 sym1->isspilt != sym2->isspilt) return FALSE;
489 /* if they are the same */
493 if (strcmp (sym1->rname, sym2->rname) == 0)
497 /* if left is a tmp & right is not */
498 if (IS_ITEMP (op1) &&
499 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
502 if (IS_ITEMP (op2) &&
504 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
510 /*-----------------------------------------------------------------*/
511 /* sameRegs - two asmops have the same registers */
512 /*-----------------------------------------------------------------*/
514 sameRegs (asmop * aop1, asmop * aop2)
521 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
524 if (aop1->size != aop2->size)
527 for (i = 0; i < aop1->size; i++)
528 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
534 /*-----------------------------------------------------------------*/
535 /* isRegPair - for size 2 if this operand has a register pair */
536 /*-----------------------------------------------------------------*/
538 isRegPair (asmop * aop)
540 if (!aop || aop->size < 2)
542 if (aop->type == AOP_X || aop->type == AOP_Z)
544 if (aop->type != AOP_REG)
546 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
547 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
553 /*-----------------------------------------------------------------*/
554 /* aopOp - allocates an asmop for an operand : */
555 /*-----------------------------------------------------------------*/
557 aopOp (operand * op, iCode * ic, bool result)
566 /* if this a literal */
567 if (IS_OP_LITERAL (op)) {
568 op->aop = aop = newAsmop (AOP_LIT);
569 aop->aopu.aop_lit = op->operand.valOperand;
570 aop->size = getSize (operandType (op));
574 /* if already has a asmop then continue */
578 /* if the underlying symbol has a aop */
579 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
580 op->aop = OP_SYMBOL (op)->aop;
584 /* if this is a true symbol */
585 if (IS_TRUE_SYMOP (op)) {
586 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
590 /* this is a temporary : this has
596 e) can be a return use only */
598 sym = OP_SYMBOL (op);
601 /* if the type is a conditional */
602 if (sym->regType & REG_CND) {
603 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
608 /* if it is spilt then two situations
610 b) has a spill location */
611 if (sym->isspilt || sym->nRegs == 0) {
613 /* rematerialize it NOW */
615 sym->aop = op->aop = aop = aopForRemat (sym);
616 aop->size = getSize (sym->type);
621 assert ("ACC_USE cannot happen in AVR\n");
626 aop = op->aop = sym->aop = newAsmop (AOP_STR);
627 aop->size = getSize (sym->type);
628 for (i = 0; i < (int) fAVRReturnSize; i++)
629 aop->aopu.aop_str[i] = fAVRReturn[i];
633 /* else spill location */
634 sym->aop = op->aop = aop =
635 aopForSym (ic, sym->usl.spillLoc, result);
636 aop->size = getSize (sym->type);
640 /* must be in a register */
641 sym->aop = op->aop = aop = newAsmop (AOP_REG);
642 aop->size = sym->nRegs;
643 for (i = 0; i < sym->nRegs; i++)
644 aop->aopu.aop_reg[i] = sym->regs[i];
647 /*-----------------------------------------------------------------*/
648 /* freeAsmop - free up the asmop given to an operand */
649 /*----------------------------------------------------------------*/
651 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
668 /* depending on the asmop type only three cases need work AOP_RO
669 , AOP_R1 && AOP_STK */
674 emitcode ("pop", "r26");
675 emitcode ("pop", "r27");
679 bitVectUnSetBit (ic->rUsed, X_IDX);
685 emitcode ("pop", "r30");
686 emitcode ("pop", "r31");
690 bitVectUnSetBit (ic->rUsed, Z_IDX);
696 int stk = aop->aopu.aop_stk + aop->size;
697 bitVectUnSetBit (ic->rUsed, X_IDX);
698 bitVectUnSetBit (ic->rUsed, Z_IDX);
700 getFreePtr (ic, &aop, FALSE, 0);
702 emitcode ("movw", "%s,r28");
704 if (stk <= 63 && stk > 0) {
705 emitcode ("adiw", "%s,0x%02x",
706 aop->aopu.aop_ptr->name,
710 emitcode ("subi", "%s,lo8(%d)",
711 aop->aopu.aop_ptr->name,
713 emitcode ("sbci", "%s,hi8(%d)",
720 emitcode ("pop", "r24");
721 emitcode ("st", "-%s,r24",
722 aop->type == AOP_X ? "X" : "Z");
727 freeAsmop (op, NULL, ic, TRUE);
729 emitcode ("pop", "r26");
730 emitcode ("pop", "r27");
735 emitcode ("pop", "r30");
736 emitcode ("pop", "r31");
743 /* all other cases just dealloc */
747 OP_SYMBOL (op)->aop = NULL;
748 /* if the symbol has a spill */
750 SPIL_LOC (op)->aop = NULL;
755 /*-----------------------------------------------------------------*/
756 /* aopGet - for fetching value of the aop */
757 /*-----------------------------------------------------------------*/
759 aopGet (asmop * aop, int offset)
764 /* offset is greater than
766 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
769 /* depending on type */
773 if (offset > aop->coff) {
774 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
778 if (offset < aop->coff) {
779 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
784 emitcode ("ld", "%s,x",
785 (rs = ((offset & 1) ? "r25" : "r24")));
790 if (offset > aop->coff) {
791 emitcode ("adiw", "r30,%d",
795 emitcode ("sbiw", "r30,%d",
798 emitcode ("lpm", "%s,z",
799 (rs = ((offset & 1) ? "r25" : "r24")));
803 if (offset > aop->coff) {
804 emitcode ("ldd", "%s,z+%d",
806 ((offset & 1) ? "r25" : "r24")),
810 emitcode ("sbiw", "%s,%d",
811 aop->aopu.aop_ptr->name,
814 emitcode ("ld", "%s,z",
816 ((offset & 1) ? "r25" : "r24")));
823 emitcode ("lds", "%s,(%s)+%d",
824 (rs = ((offset & 1) ? "r25" : "r24")),
825 aop->aopu.aop_immd, offset);
829 emitcode ("lds", "%s,(%s)+%d",
830 (rs = ((offset & 1) ? "r25" : "r24")),
831 aop->aopu.aop_dir, offset);
835 return aop->aopu.aop_reg[offset]->name;
838 assert ("cannot be in bit space AOP_CRY\n");
842 s = aopLiteral (aop->aopu.aop_lit, offset);
843 emitcode ("ldi", "%s,lo8(%s)",
844 (rs = ((offset & 1) ? "r24" : "r25")), s);
849 return aop->aopu.aop_str[offset];
852 emitcode ("ldd", "%s,Y+%d",
853 (rs = ((offset & 1) ? "r25" : "r24")),
854 aop->aopu.aop_stk + offset);
858 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
859 "aopget got unsupported aop->type");
863 /*-----------------------------------------------------------------*/
864 /* aopPut - puts a string for a aop */
865 /*-----------------------------------------------------------------*/
867 aopPut (asmop * aop, char *s, int offset)
871 if (aop->size && offset > (aop->size - 1)) {
872 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
873 "aopPut got offset > aop->size");
877 /* will assign value to value */
878 /* depending on where it is ofcourse */
882 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
885 sprintf (d, "%s", aop->aopu.aop_dir);
888 emitcode ("sts", "%s,%s", d, s);
892 if (toupper (*s) != 'R') {
894 emitcode ("clr", "%s",
895 aop->aopu.aop_reg[offset]->name);
898 emitcode ("ldi", "r25,%s", s);
899 emitcode ("mov", "%s,r35",
900 aop->aopu.aop_reg[offset]->name);
904 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
905 emitcode ("mov", "%s,%s",
906 aop->aopu.aop_reg[offset]->name, s);
912 if (offset > aop->coff) {
913 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
917 if (offset < aop->coff) {
918 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
923 emitcode ("st", "x,%s", s);
928 if (offset > aop->coff) {
929 emitcode ("adiw", "r30,%d",
933 emitcode ("sbiw", "r30,%d",
936 emitcode ("lpm", "%s,z", s);
940 if (offset > aop->coff) {
941 emitcode ("sdd", "z+%d,%s",
942 offset - aop->coff, s);
945 emitcode ("sbiw", "%s,%d",
946 aop->aopu.aop_ptr->name,
949 emitcode ("ld", "%s,z", s);
955 emitcode ("push", "%s", s);
959 /* if used only for a condition code check */
960 assert (toupper (*s) == 'R');
962 emitcode ("xrl", "r0,r0");
963 emitcode ("cpi", "%s,0", s);
966 emitcode ("cpc", "r0,%s", s);
972 if (strcmp (aop->aopu.aop_str[offset], s))
973 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
978 emitcode ("std", "y+%d,%s", offset, s);
982 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
983 "aopPut got unsupported aop->type");
989 /*-----------------------------------------------------------------*/
990 /* reAdjustPreg - points a register back to where it should */
991 /*-----------------------------------------------------------------*/
993 reAdjustPreg (asmop * aop)
998 if ((size = aop->size) <= 1)
1001 switch (aop->type) {
1004 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
1010 #define AOP(op) op->aop
1011 #define AOP_TYPE(op) AOP(op)->type
1012 #define AOP_SIZE(op) AOP(op)->size
1013 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1014 AOP_TYPE(x) == AOP_Z))
1015 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1016 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1017 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1018 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1019 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1020 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1021 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1023 /*-----------------------------------------------------------------*/
1024 /* genNotFloat - generates not for float operations */
1025 /*-----------------------------------------------------------------*/
1027 genNotFloat (operand * op, operand * res)
1033 /* we will put 127 in the first byte of
1035 aopPut (AOP (res), "127", 0);
1036 size = AOP_SIZE (op) - 1;
1039 l = aopGet (op->aop, offset++);
1043 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1045 tlbl = newiTempLabel (NULL);
1047 tlbl = newiTempLabel (NULL);
1048 aopPut (res->aop, zero, 1);
1049 emitcode ("cpi", "r0,0");
1050 emitcode ("breq", "L%05d", tlbl->key);
1051 aopPut (res->aop, one, 1);
1052 emitcode ("", "L%05d:", tlbl->key);
1054 size = res->aop->size - 2;
1056 /* put zeros in the rest */
1058 aopPut (res->aop, zero, offset++);
1061 /*-----------------------------------------------------------------*/
1062 /* opIsGptr: returns non-zero if the passed operand is */
1063 /* a generic pointer type. */
1064 /*-----------------------------------------------------------------*/
1066 opIsGptr (operand * op)
1068 sym_link *type = operandType (op);
1070 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1076 /*-----------------------------------------------------------------*/
1077 /* getDataSize - get the operand data size */
1078 /*-----------------------------------------------------------------*/
1080 getDataSize (operand * op)
1083 size = AOP_SIZE (op);
1084 if (size == GPTRSIZE) {
1085 sym_link *type = operandType (op);
1086 if (IS_GENPTR (type)) {
1087 /* generic pointer; arithmetic operations
1088 * should ignore the high byte (pointer type).
1096 /*-----------------------------------------------------------------*/
1097 /* outAcc - output Acc */
1098 /*-----------------------------------------------------------------*/
1100 outAcc (operand * result)
1103 size = getDataSize (result);
1105 aopPut (AOP (result), "r0", 0);
1108 /* unsigned or positive */
1110 aopPut (AOP (result), zero, offset++);
1115 /*-----------------------------------------------------------------*/
1116 /* outBitC - output a bit C */
1117 /*-----------------------------------------------------------------*/
1119 outBitC (operand * result)
1121 emitcode ("clr", "r0");
1122 emitcode ("rol", "r0");
1126 /*-----------------------------------------------------------------*/
1127 /* toBoolean - emit code for orl a,operator(sizeop) */
1128 /*-----------------------------------------------------------------*/
1130 toBoolean (operand * oper, char *r, bool clr)
1132 int size = AOP_SIZE (oper);
1135 emitcode ("clr", "%s", r);
1137 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1141 /*-----------------------------------------------------------------*/
1142 /* genNot - generate code for ! operation */
1143 /*-----------------------------------------------------------------*/
1148 sym_link *optype = operandType (IC_LEFT (ic));
1149 int size, offset = 1;
1151 /* assign asmOps to operand & result */
1152 aopOp (IC_LEFT (ic), ic, FALSE);
1153 aopOp (IC_RESULT (ic), ic, TRUE);
1155 /* if type float then do float */
1156 if (IS_FLOAT (optype)) {
1157 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1160 emitcode ("clr", "r24");
1161 tlbl = newiTempLabel (NULL);
1162 size = AOP_SIZE (IC_LEFT (ic));
1165 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1170 emitcode ("cpc", "%s,r24",
1171 aopGet (AOP (IC_LEFT (ic)),
1174 emitcode ("cpi", "%s,0",
1175 aopGet (AOP (IC_LEFT (ic)),
1179 emitcode ("bne", "L%05d", tlbl->key);
1181 emitcode ("ldi", "r24,1");
1182 emitcode ("", "L%05d:", tlbl->key);
1183 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1184 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1187 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1191 /* release the aops */
1192 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1193 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1197 /*-----------------------------------------------------------------*/
1198 /* genCpl - generate code for complement */
1199 /*-----------------------------------------------------------------*/
1207 /* assign asmOps to operand & result */
1208 aopOp (IC_LEFT (ic), ic, FALSE);
1209 aopOp (IC_RESULT (ic), ic, TRUE);
1210 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1211 size = AOP_SIZE (IC_RESULT (ic));
1213 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1215 emitcode ("com", "%s", l);
1218 aopPut (AOP (IC_RESULT (ic)), l, offset);
1219 emitcode ("com", "%s",
1220 aopGet (AOP (IC_RESULT (ic)), offset));
1225 /* release the aops */
1226 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1227 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1230 /*-----------------------------------------------------------------*/
1231 /* genUminusFloat - unary minus for floating points */
1232 /*-----------------------------------------------------------------*/
1234 genUminusFloat (operand * op, operand * result)
1236 int size, offset = 0;
1238 /* for this we just need to flip the
1239 first it then copy the rest in place */
1240 size = AOP_SIZE (op) - 1;
1241 l = aopGet (AOP (op), 3);
1243 emitcode ("ldi", "r24,0x80");
1244 if (sameRegs (AOP (op), AOP (result))) {
1245 emitcode ("eor", "%s,r24", l);
1248 aopPut (AOP (result), l, 3);
1249 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1252 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1257 /*-----------------------------------------------------------------*/
1258 /* genUminus - unary minus code generation */
1259 /*-----------------------------------------------------------------*/
1261 genUminus (iCode * ic)
1264 sym_link *optype, *rtype;
1268 aopOp (IC_LEFT (ic), ic, FALSE);
1269 aopOp (IC_RESULT (ic), ic, TRUE);
1271 optype = operandType (IC_LEFT (ic));
1272 rtype = operandType (IC_RESULT (ic));
1274 /* if float then do float stuff */
1275 if (IS_FLOAT (optype)) {
1276 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1280 /* otherwise subtract from zero */
1281 size = AOP_SIZE (IC_LEFT (ic));
1283 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1286 emitcode ("neg", "%s",
1287 aopGet (AOP (IC_LEFT (ic)), 0));
1290 aopPut (AOP (IC_RESULT (ic)),
1291 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1292 emitcode ("neg", "%s",
1293 aopGet (AOP (IC_RESULT (ic)), 0));
1299 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1301 aopPut (AOP (IC_RESULT (ic)), l, offset);
1302 l = aopGet (AOP (IC_RESULT (ic)), offset);
1305 emitcode ("com", "%s", l);
1307 emitcode ("neg", "%s", l);
1310 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1313 emitcode ("sbci", "%s,lo8(-1)",
1314 aopGet (AOP (IC_RESULT (ic)), offset++));
1318 /* if any remaining bytes in the result */
1319 /* we just need to propagate the sign */
1320 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1321 symbol *tlbl = newiTempLabel (NULL);
1322 emitcode ("clr", "r0");
1323 emitcode ("brcc", "L%05d", tlbl->key);
1324 emitcode ("com", "r0");
1325 emitcode ("", "L%05d:", tlbl->key);
1327 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1331 /* release the aops */
1332 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1336 /*-----------------------------------------------------------------*/
1337 /* assignResultValue - */
1338 /*-----------------------------------------------------------------*/
1340 assignResultValue (operand * oper)
1343 int size = AOP_SIZE (oper);
1345 aopPut (AOP (oper), fAVRReturn[offset], offset);
1350 /*-----------------------------------------------------------------*/
1351 /* saveZreg - if indirect call then save z-pointer register */
1352 /*-----------------------------------------------------------------*/
1354 saveZreg (iCode * ic)
1356 /* only if live accross this call */
1357 if (ic->regsSaved == 0 &&
1358 (bitVectBitValue (ic->rMask, R30_IDX) ||
1359 bitVectBitValue (ic->rMask, R31_IDX))) {
1361 emitcode ("push", "r30");
1362 emitcode ("push", "r31");
1366 /*-----------------------------------------------------------------*/
1367 /* popZreg - restore values of zreg */
1368 /*-----------------------------------------------------------------*/
1370 popZreg (iCode * ic)
1372 if (ic->regsSaved) {
1373 emitcode ("pop", "r31");
1374 emitcode ("pop", "r30");
1378 /*-----------------------------------------------------------------*/
1379 /* genIpush - genrate code for pushing this gets a little complex */
1380 /*-----------------------------------------------------------------*/
1382 genIpush (iCode * ic)
1384 int size, offset = 0;
1388 if (!ic->parmPush) {
1389 /* and the item is spilt then do nothing */
1390 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1395 for (lic = ic->next; lic; lic = lic->next)
1396 if (lic->op == PCALL)
1402 /* this is a paramter push */
1403 aopOp (IC_LEFT (ic), ic, FALSE);
1404 size = AOP_SIZE (IC_LEFT (ic));
1406 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1407 emitcode ("push", "%s", l);
1410 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1413 /*-----------------------------------------------------------------*/
1414 /* genIpop - recover the registers: can happen only for spilling */
1415 /*-----------------------------------------------------------------*/
1417 genIpop (iCode * ic)
1422 /* if the temp was not pushed then */
1423 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1426 aopOp (IC_LEFT (ic), ic, FALSE);
1427 size = AOP_SIZE (IC_LEFT (ic));
1428 offset = (size - 1);
1430 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1432 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1435 /*-----------------------------------------------------------------*/
1436 /* genCall - generates a call statement */
1437 /*-----------------------------------------------------------------*/
1439 genCall (iCode * ic)
1442 /* if send set is not empty the assign */
1446 for (sic = setFirstItem (_G.sendSet); sic;
1447 sic = setNextItem (_G.sendSet)) {
1448 int size, offset = 0;
1449 aopOp (IC_LEFT (sic), sic, FALSE);
1450 size = AOP_SIZE (IC_LEFT (sic));
1453 aopGet (AOP (IC_LEFT (sic)), offset);
1455 sprintf (buffer, "r%d", rnum++);
1457 emitcode ("mov", "%s,%s", b, l);
1460 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1465 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1466 OP_SYMBOL (IC_LEFT (ic))->rname :
1467 OP_SYMBOL (IC_LEFT (ic))->name));
1469 /* if we need assign a result value */
1470 if ((IS_ITEMP (IC_RESULT (ic)) &&
1471 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1472 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1473 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1475 aopOp (IC_RESULT (ic), ic, FALSE);
1476 assignResultValue (IC_RESULT (ic));
1477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1480 /* adjust the stack for parameters if required */
1481 if (ic->parmBytes) {
1482 if (ic->parmBytes > 63) {
1483 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1486 emitcode ("subi", "r28,lo8(%d)",
1488 emitcode ("sbci", "r29,hi8(%d)",
1495 /*-----------------------------------------------------------------*/
1496 /* genPcall - generates a call by pointer statement */
1497 /*-----------------------------------------------------------------*/
1499 genPcall (iCode * ic)
1505 aopOp (IC_LEFT (ic), ic, FALSE);
1506 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1507 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1508 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1510 /* if send set is not empty the assign */
1514 for (sic = setFirstItem (_G.sendSet); sic;
1515 sic = setNextItem (_G.sendSet)) {
1516 int size, offset = 0;
1517 aopOp (IC_LEFT (sic), sic, FALSE);
1518 size = AOP_SIZE (IC_LEFT (sic));
1521 aopGet (AOP (IC_LEFT (sic)), offset);
1523 sprintf (b, "r%d", rnum++);
1525 emitcode ("mov", "%s,%s", b, l);
1528 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1533 emitcode ("icall", "");
1535 /* if we need assign a result value */
1536 if ((IS_ITEMP (IC_RESULT (ic)) &&
1537 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1538 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1539 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1541 aopOp (IC_RESULT (ic), ic, FALSE);
1543 assignResultValue (IC_RESULT (ic));
1544 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1547 /* adjust the stack for parameters if
1549 if (ic->parmBytes) {
1551 if (ic->parmBytes > 3) {
1552 emitcode ("mov", "a,%s", spname);
1553 emitcode ("add", "a,#0x%02x",
1554 (-ic->parmBytes) & 0xff);
1555 emitcode ("mov", "%s,a", spname);
1558 for (i = 0; i < ic->parmBytes; i++)
1559 emitcode ("dec", "%s", spname);
1563 /* adjust the stack for parameters if required */
1564 if (ic->parmBytes) {
1565 if (ic->parmBytes > 63) {
1566 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1569 emitcode ("subi", "r28,lo8(%d)",
1571 emitcode ("sbci", "r29,hi8(%d)",
1579 /*-----------------------------------------------------------------*/
1580 /* resultRemat - result is rematerializable */
1581 /*-----------------------------------------------------------------*/
1583 resultRemat (iCode * ic)
1585 if (SKIP_IC (ic) || ic->op == IFX)
1588 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1589 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1590 if (sym->remat && !POINTER_SET (ic))
1597 #if defined(__BORLANDC__) || defined(_MSC_VER)
1598 #define STRCASECMP stricmp
1600 #define STRCASECMP strcasecmp
1603 /*-----------------------------------------------------------------*/
1604 /* inExcludeList - return 1 if the string is in exclude Reg list */
1605 /*-----------------------------------------------------------------*/
1607 inExcludeList (char *s)
1611 if (options.excludeRegs[i] &&
1612 STRCASECMP (options.excludeRegs[i], "none") == 0)
1615 for (i = 0; options.excludeRegs[i]; i++) {
1616 if (options.excludeRegs[i] &&
1617 STRCASECMP (s, options.excludeRegs[i]) == 0)
1623 /*-----------------------------------------------------------------*/
1624 /* genFunction - generated code for function entry */
1625 /*-----------------------------------------------------------------*/
1627 genFunction (iCode * ic)
1634 /* create the function header */
1635 emitcode (";", "-----------------------------------------");
1636 emitcode (";", " function %s",
1637 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1638 emitcode (";", "-----------------------------------------");
1640 emitcode ("", "%s:", sym->rname);
1641 fetype = getSpec (operandType (IC_LEFT (ic)));
1643 /* if critical function then turn interrupts off */
1644 if (SPEC_CRTCL (fetype))
1645 emitcode ("cli", "");
1647 if (IS_ISR (sym->etype)) {
1650 /* save the preserved registers that are used in this function */
1651 for (i = R2_IDX; i <= R15_IDX; i++) {
1652 if (bitVectBitValue (sym->regsUsed, i)) {
1654 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1657 /* now for the pointer registers */
1658 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1660 emitcode ("push", "r26");
1662 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1664 emitcode ("push", "r27");
1666 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1668 emitcode ("push", "r30");
1670 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1672 emitcode ("push", "r31");
1674 /* adjust the stack for the function */
1676 emitcode ("push", "r28");
1677 emitcode ("push", "r29");
1678 emitcode ("in", "r28,__SP_L__");
1679 emitcode ("in", "r29,__SP_H__");
1680 if (sym->stack <= 63) {
1681 emitcode ("sbiw", "r28,%d", sym->stack);
1684 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1685 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1687 emitcode ("out", "__SP_L__,r28");
1688 emitcode ("out", "__SP_H__,r29");
1692 /*-----------------------------------------------------------------*/
1693 /* genEndFunction - generates epilogue for functions */
1694 /*-----------------------------------------------------------------*/
1696 genEndFunction (iCode * ic)
1698 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1701 /* restore stack pointer */
1703 if (sym->stack <= 63) {
1704 emitcode ("adiw", "r28,%d", sym->stack);
1707 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1708 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1710 emitcode ("out", "__SP_L__,r28");
1711 emitcode ("out", "__SP_H__,r29");
1713 /* pop frame pointer */
1714 emitcode ("pop", "r29");
1715 emitcode ("pop", "r28");
1717 /* restore preserved registers */
1718 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1720 emitcode ("pop", "r31");
1722 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1724 emitcode ("pop", "r30");
1726 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1728 emitcode ("pop", "r27");
1730 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1732 emitcode ("pop", "r26");
1734 for (i = R15_IDX; i >= R2_IDX; i--) {
1735 if (bitVectBitValue (sym->regsUsed, i)) {
1737 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1741 if (SPEC_CRTCL (sym->etype))
1742 emitcode ("sti", "");
1744 if (IS_ISR (sym->etype)) {
1745 emitcode ("rti", "");
1748 emitcode ("ret", "");
1753 /*-----------------------------------------------------------------*/
1754 /* genRet - generate code for return statement */
1755 /*-----------------------------------------------------------------*/
1759 int size, offset = 0;
1761 /* if we have no return value then
1762 just generate the "ret" */
1766 /* we have something to return then
1767 move the return value into place */
1768 aopOp (IC_LEFT (ic), ic, FALSE);
1769 size = AOP_SIZE (IC_LEFT (ic));
1772 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1773 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1775 (int) floatFromVal (AOP (IC_LEFT (ic))->
1776 aopu.aop_lit), offset);
1780 l = aopGet (AOP (IC_LEFT (ic)), offset);
1781 if (strcmp (fAVRReturn[offset], l))
1782 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1788 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1791 /* generate a jump to the return label
1792 if the next is not the return statement */
1793 if (!(ic->next && ic->next->op == LABEL &&
1794 IC_LABEL (ic->next) == returnLabel))
1796 emitcode ("rjmp", "L%05d", returnLabel->key);
1800 /*-----------------------------------------------------------------*/
1801 /* genLabel - generates a label */
1802 /*-----------------------------------------------------------------*/
1804 genLabel (iCode * ic)
1806 /* special case never generate */
1807 if (IC_LABEL (ic) == entryLabel)
1810 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1813 /*-----------------------------------------------------------------*/
1814 /* genGoto - generates a ljmp */
1815 /*-----------------------------------------------------------------*/
1817 genGoto (iCode * ic)
1819 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key + 100));
1822 /*-----------------------------------------------------------------*/
1823 /* findLabelBackwards: walks back through the iCode chain looking */
1824 /* for the given label. Returns number of iCode instructions */
1825 /* between that label and given ic. */
1826 /* Returns zero if label not found. */
1827 /*-----------------------------------------------------------------*/
1829 findLabelBackwards (iCode * ic, int key)
1837 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
1838 /* printf("findLabelBackwards = %d\n", count); */
1846 /*-----------------------------------------------------------------*/
1847 /* genPlusIncr :- does addition with increment if possible */
1848 /*-----------------------------------------------------------------*/
1850 genPlusIncr (iCode * ic)
1852 unsigned int icount;
1854 /* will try to generate an increment */
1855 /* if the right side is not a literal
1857 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1861 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1864 /* if the sizes are greater than 2 or they are not the same regs
1866 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1869 /* so we know LEFT & RESULT in the same registers and add
1871 /* for short & char types */
1872 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1874 emitcode ("inc", "%s",
1875 aopGet (AOP (IC_LEFT (ic)), 0));
1878 emitcode ("subi", "%s,lo8(%d)",
1879 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1883 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1884 /* if register pair and starts with 26/30 then adiw */
1885 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1887 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
1888 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1889 emitcode ("adiw", "%s,%d",
1890 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1895 emitcode ("subi", "%s,lo8(%d)",
1896 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1897 emitcode ("sbci", "%s,hi8(%d)",
1898 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1902 /* for 32 bit longs */
1903 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1905 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1907 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1909 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1915 /* This is the pure and virtuous version of this code.
1916 * I'm pretty certain it's right, but not enough to toss the old
1920 adjustArithmeticResult (iCode * ic)
1922 if (opIsGptr (IC_RESULT (ic)) &&
1923 opIsGptr (IC_LEFT (ic)) &&
1924 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1925 aopPut (AOP (IC_RESULT (ic)),
1926 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1930 if (opIsGptr (IC_RESULT (ic)) &&
1931 opIsGptr (IC_RIGHT (ic)) &&
1932 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1933 aopPut (AOP (IC_RESULT (ic)),
1934 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1938 if (opIsGptr (IC_RESULT (ic)) &&
1939 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1940 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1941 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1942 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1944 sprintf (buffer, "%d",
1945 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
1946 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
1950 /*-----------------------------------------------------------------*/
1951 /* genPlus - generates code for addition */
1952 /*-----------------------------------------------------------------*/
1954 genPlus (iCode * ic)
1956 int size, offset = 0;
1960 /* special cases :- */
1962 aopOp (IC_LEFT (ic), ic, FALSE);
1963 aopOp (IC_RIGHT (ic), ic, FALSE);
1964 aopOp (IC_RESULT (ic), ic, TRUE);
1966 /* if I can do an increment instead
1967 of add then GOOD for ME */
1968 if (genPlusIncr (ic) == TRUE)
1971 size = getDataSize (IC_RESULT (ic));
1972 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
1976 aopPut (AOP (IC_RESULT (ic)),
1977 aopGet (AOP (IC_LEFT (ic)), offset), offset);
1979 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
1986 emitcode (l, "%s,%s",
1987 aopGet (AOP (IC_RESULT (ic)), offset),
1988 aopGet (AOP (IC_RIGHT (ic)), offset));
1996 emitcode (l, "%s,%s(-%d)",
1997 aopGet (AOP (IC_RESULT (ic)), offset),
1999 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2005 adjustArithmeticResult (ic);
2008 freeAsmop (IC_LEFT (ic), NULL, ic,
2009 (RESULTONSTACK (ic) ? FALSE : TRUE));
2010 freeAsmop (IC_RIGHT (ic), NULL, ic,
2011 (RESULTONSTACK (ic) ? FALSE : TRUE));
2012 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2015 /*-----------------------------------------------------------------*/
2016 /* genMinusDec :- does subtraction with deccrement if possible */
2017 /*-----------------------------------------------------------------*/
2019 genMinusDec (iCode * ic)
2021 unsigned int icount;
2023 /* will try to generate an increment */
2024 /* if the right side is not a literal
2026 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2030 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2033 /* if the sizes are greater than 2 or they are not the same regs
2035 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2038 /* so we know LEFT & RESULT in the same registers and add
2040 /* for short & char types */
2041 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2043 emitcode ("dec", "%s",
2044 aopGet (AOP (IC_LEFT (ic)), 0));
2047 emitcode ("subi", "%s,lo8(%d)",
2048 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2052 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2053 /* if register pair and starts with 26/30 then adiw */
2054 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2056 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
2057 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2058 emitcode ("sbiw", "%s,%d",
2059 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2064 emitcode ("subi", "%s,lo8(%d)",
2065 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2066 emitcode ("sbci", "%s,hi8(%d)",
2067 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2070 /* for 32 bit longs */
2071 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2073 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2075 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2077 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2083 /*-----------------------------------------------------------------*/
2084 /* addSign - complete with sign */
2085 /*-----------------------------------------------------------------*/
2087 addSign (operand * result, int offset, int sign)
2089 int size = (getDataSize (result) - offset);
2092 emitcode ("rlc", "a");
2093 emitcode ("subb", "a,acc");
2095 aopPut (AOP (result), "a", offset++);
2099 aopPut (AOP (result), zero, offset++);
2103 /*-----------------------------------------------------------------*/
2104 /* genMinus - generates code for subtraction */
2105 /*-----------------------------------------------------------------*/
2107 genMinus (iCode * ic)
2109 int size, offset = 0, samer;
2112 aopOp (IC_LEFT (ic), ic, FALSE);
2113 aopOp (IC_RIGHT (ic), ic, FALSE);
2114 aopOp (IC_RESULT (ic), ic, TRUE);
2116 /* if I can do an decrement instead
2117 of subtract then GOOD for ME */
2118 if (genMinusDec (ic) == TRUE)
2121 size = getDataSize (IC_RESULT (ic));
2122 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2125 aopPut (AOP (IC_RESULT (ic)),
2126 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2128 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2135 emitcode (l, "%s,%s",
2136 aopGet (AOP (IC_RESULT (ic)), offset),
2137 aopGet (AOP (IC_RIGHT (ic)), offset));
2145 emitcode (l, "%s,%s(%d)",
2146 aopGet (AOP (IC_RESULT (ic)), offset),
2148 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2154 adjustArithmeticResult (ic);
2157 freeAsmop (IC_LEFT (ic), NULL, ic,
2158 (RESULTONSTACK (ic) ? FALSE : TRUE));
2159 freeAsmop (IC_RIGHT (ic), NULL, ic,
2160 (RESULTONSTACK (ic) ? FALSE : TRUE));
2161 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2164 /*-----------------------------------------------------------------*/
2165 /* genMultOneByte : 8 bit multiplication & division */
2166 /*-----------------------------------------------------------------*/
2168 genMultOneByte (operand * left, operand * right, operand * result)
2170 sym_link *opetype = operandType (result);
2174 /* (if two literals, the value is computed before) */
2175 /* if one literal, literal on the right */
2176 if (AOP_TYPE (left) == AOP_LIT) {
2182 size = AOP_SIZE (result);
2184 if (SPEC_USIGN (opetype)) {
2185 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2186 aopGet (AOP (right), 0));
2189 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2190 aopGet (AOP (right), 0));
2192 aopPut (AOP (result), "r0", 0);
2194 aopPut (AOP (result), "r1", 1);
2197 if (SPEC_USIGN (opetype)) {
2199 aopPut (AOP (result), zero, offset++);
2204 lbl = newiTempLabel (NULL);
2205 emitcode ("ldi", "r24,0");
2206 emitcode ("brcc", "L%05d", lbl->key);
2207 emitcode ("ldi", "r24,lo8(-1)");
2208 emitcode ("", "L%05d:", lbl->key);
2210 aopPut (AOP (result), "r24",
2218 /*-----------------------------------------------------------------*/
2219 /* genMult - generates code for multiplication */
2220 /*-----------------------------------------------------------------*/
2222 genMult (iCode * ic)
2224 operand *left = IC_LEFT (ic);
2225 operand *right = IC_RIGHT (ic);
2226 operand *result = IC_RESULT (ic);
2228 /* assign the amsops */
2229 aopOp (left, ic, FALSE);
2230 aopOp (right, ic, FALSE);
2231 aopOp (result, ic, TRUE);
2233 /* if both are of size == 1 */
2234 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2235 genMultOneByte (left, right, result);
2239 /* should have been converted to function call */
2243 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2244 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2245 freeAsmop (result, NULL, ic, TRUE);
2248 /*-----------------------------------------------------------------*/
2249 /* genDiv - generates code for division */
2250 /*-----------------------------------------------------------------*/
2254 /* should have been converted to function call */
2258 /*-----------------------------------------------------------------*/
2259 /* genMod - generates code for division */
2260 /*-----------------------------------------------------------------*/
2264 /* should have been converted to function call */
2276 /*-----------------------------------------------------------------*/
2277 /* revavrcnd - reverse a conditional for avr */
2278 /*-----------------------------------------------------------------*/
2280 revavrcnd (int type)
2292 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2293 if (rar[i].type == type)
2294 return rar[i].rtype;
2295 if (rar[i].rtype == type)
2298 assert (1); /* cannot happen */
2299 return 0; /* makes the compiler happy */
2302 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2303 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2305 /*-----------------------------------------------------------------*/
2306 /* genBranch - generate the branch instruction */
2307 /*-----------------------------------------------------------------*/
2309 genBranch (iCode * ifx, int br_type, int sign)
2311 int tj = (IC_TRUE (ifx) ? 1 : 0);
2313 if (tj) { /* if true jump */
2314 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2315 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2317 else { /* if false jump */
2318 int rtype = revavrcnd (br_type);
2319 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2320 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2325 /*-----------------------------------------------------------------*/
2326 /* genCmp - compare & jump */
2327 /*-----------------------------------------------------------------*/
2329 genCmp (iCode * ic, iCode * ifx, int br_type)
2331 operand *left, *right, *result;
2332 sym_link *letype, *retype;
2334 int sign, size, offset = 0;
2336 left = IC_LEFT (ic);
2337 right = IC_RIGHT (ic);
2338 result = IC_RESULT (ic);
2340 letype = getSpec (operandType (left));
2341 retype = getSpec (operandType (right));
2342 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2344 /* assign the amsops */
2345 aopOp (left, ic, FALSE);
2346 aopOp (right, ic, FALSE);
2347 aopOp (result, ic, TRUE);
2348 size = AOP_SIZE (left);
2352 if (AOP_TYPE (right) == AOP_LIT) {
2353 emitcode ("cpi", "%s,lo8(%d)",
2354 aopGet (AOP (left), 0),
2356 floatFromVal (AOP (IC_RIGHT (ic))->
2358 genBranch (ifx, br_type, sign);
2360 else { /* right != literal */
2361 emitcode ("cp", "%s,%s",
2362 aopGet (AOP (left), 0),
2363 aopGet (AOP (right), 0));
2364 genBranch (ifx, br_type, sign);
2367 else { /* size != 1 */
2370 emitcode ("cp", "%s,%s",
2371 aopGet (AOP (left), 0),
2372 aopGet (AOP (right), 0));
2374 emitcode ("cpc", "%s,%s",
2375 aopGet (AOP (left), offset),
2376 aopGet (AOP (right),
2380 genBranch (ifx, br_type, sign);
2384 emitcode ("clr", "r0");
2387 emitcode ("cp", "%s,%s",
2388 aopGet (AOP (left), 0),
2389 aopGet (AOP (right), 0));
2391 emitcode ("cpc", "%s,%s",
2392 aopGet (AOP (left), offset),
2393 aopGet (AOP (right), offset));
2396 lbl = newiTempLabel (NULL);
2397 br_type = revavrcnd (br_type);
2399 emitcode (br_uname[br_type], "L%05d", lbl->key);
2401 emitcode (br_name[br_type], "L%05d", lbl->key);
2402 emitcode ("inc", "r0");
2403 emitcode ("", "L%05d:", lbl->key);
2404 aopPut (AOP (result), "r0", 0);
2405 size = AOP_SIZE (result) - 1;
2408 aopPut (AOP (result), zero, offset++);
2411 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2412 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2413 freeAsmop (result, NULL, ic, TRUE);
2416 /*-----------------------------------------------------------------*/
2417 /* genCmpGt :- greater than comparison */
2418 /*-----------------------------------------------------------------*/
2420 genCmpGt (iCode * ic, iCode * ifx)
2422 /* should have transformed by the parser */
2426 /*-----------------------------------------------------------------*/
2427 /* genCmpLt - less than comparisons */
2428 /*-----------------------------------------------------------------*/
2430 genCmpLt (iCode * ic, iCode * ifx)
2432 genCmp (ic, ifx, AVR_LT);
2435 /*-----------------------------------------------------------------*/
2436 /* genCmpEq - generates code for equal to */
2437 /*-----------------------------------------------------------------*/
2439 genCmpEq (iCode * ic, iCode * ifx)
2441 genCmp (ic, ifx, AVR_EQ);
2444 /*-----------------------------------------------------------------*/
2445 /* genCmpNe - generates code for not equal to */
2446 /*-----------------------------------------------------------------*/
2448 genCmpNe (iCode * ic, iCode * ifx)
2450 genCmp (ic, ifx, AVR_NE);
2453 /*-----------------------------------------------------------------*/
2454 /* genCmpGe - generates code for greater than equal to */
2455 /*-----------------------------------------------------------------*/
2457 genCmpGe (iCode * ic, iCode * ifx)
2459 genCmp (ic, ifx, AVR_GE);
2462 /*-----------------------------------------------------------------*/
2463 /* genCmpLe - generates code for less than equal to */
2464 /*-----------------------------------------------------------------*/
2466 genCmpLe (iCode * ic, iCode * ifx)
2468 operand *left = IC_LEFT (ic);
2469 operand *right = IC_RIGHT (ic);
2471 IC_RIGHT (ic) = left;
2472 IC_LEFT (ic) = right;
2473 genCmp (ic, ifx, AVR_GE);
2476 /*-----------------------------------------------------------------*/
2477 /* ifxForOp - returns the icode containing the ifx for operand */
2478 /*-----------------------------------------------------------------*/
2480 ifxForOp (operand * op, iCode * ic)
2482 /* if true symbol then needs to be assigned */
2483 if (IS_TRUE_SYMOP (op))
2486 /* if this has register type condition and
2487 the next instruction is ifx with the same operand
2488 and live to of the operand is upto the ifx only then */
2490 ic->next->op == IFX &&
2491 IC_COND (ic->next)->key == op->key &&
2492 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2497 /*-----------------------------------------------------------------*/
2498 /* genAndOp - for && operation */
2499 /*-----------------------------------------------------------------*/
2501 genAndOp (iCode * ic)
2503 operand *left, *right, *result;
2507 /* note here that && operations that are in an
2508 if statement are taken away by backPatchLabels
2509 only those used in arthmetic operations remain */
2510 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2511 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2512 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2514 tlbl = newiTempLabel (NULL);
2515 toBoolean (left, "r0", TRUE);
2516 toBoolean (right, "r1", TRUE);
2517 emitcode ("and", "r0,r1");
2518 emitcode ("ldi", "r24,1");
2519 emitcode ("breq", "L%05d", tlbl->key);
2520 emitcode ("dec", "r24");
2521 emitcode ("", "L%05d:", tlbl->key);
2522 aopPut (AOP (result), "r24", 0);
2523 size = AOP_SIZE (result) - 1;
2526 aopPut (AOP (result), zero, offset++);
2528 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2529 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2530 freeAsmop (result, NULL, ic, TRUE);
2534 /*-----------------------------------------------------------------*/
2535 /* genOrOp - for || operation */
2536 /*-----------------------------------------------------------------*/
2538 genOrOp (iCode * ic)
2540 operand *left, *right, *result;
2544 /* note here that || operations that are in an
2545 if statement are taken away by backPatchLabels
2546 only those used in arthmetic operations remain */
2547 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2548 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2549 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2551 tlbl = newiTempLabel (NULL);
2552 toBoolean (left, "r0", TRUE);
2553 toBoolean (right, "r0", FALSE);
2554 emitcode ("ldi", "r24,1");
2555 emitcode ("breq", "L%05d", tlbl->key);
2556 emitcode ("dec", "r24");
2557 emitcode ("", "L%05d:", tlbl->key);
2558 aopPut (AOP (result), "r24", 0);
2559 size = AOP_SIZE (result) - 1;
2562 aopPut (AOP (result), zero, offset++);
2564 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2565 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2566 freeAsmop (result, NULL, ic, TRUE);
2569 /*-----------------------------------------------------------------*/
2570 /* isLiteralBit - test if lit == 2^n */
2571 /*-----------------------------------------------------------------*/
2573 isLiteralBit (unsigned long lit)
2575 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
2576 0x100L, 0x200L, 0x400L, 0x800L,
2577 0x1000L, 0x2000L, 0x4000L, 0x8000L,
2578 0x10000L, 0x20000L, 0x40000L, 0x80000L,
2579 0x100000L, 0x200000L, 0x400000L, 0x800000L,
2580 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
2581 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
2585 for (idx = 0; idx < 32; idx++)
2592 AVR_AND = 0, AVR_OR, AVR_XOR
2594 static char *bopnames_lit[] = { "andi", "ori" };
2595 static char *bopnames[] = { "and", "or", "eor" };
2596 /*-----------------------------------------------------------------*/
2597 /* genBitWise - generate bitwise operations */
2598 /*-----------------------------------------------------------------*/
2600 genBitWise (iCode * ic, iCode * ifx, int bitop)
2602 operand *left, *right, *result;
2603 int size, offset = 0;
2608 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2609 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2610 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2612 size = AOP_SIZE (left);
2614 if (ifx) { /* used only for jumps */
2615 if (AOP_TYPE (right) == AOP_LIT &&
2616 (bitop == AVR_AND || bitop == AVR_OR)) {
2618 (int) floatFromVal (AOP (right)->aopu.
2620 int p2 = powof2 (lit);
2621 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2622 l = aopGet (AOP (left), p2 / 8);
2623 if (IC_TRUE (ifx)) {
2624 emitcode ("sbrc", "%s,%d", l,
2626 emitcode ("rjmp", "L%05d",
2627 IC_TRUE (ifx)->key);
2630 emitcode ("sbrs", "%s,%d", l,
2632 emitcode ("rjmp", "L%05d",
2633 IC_FALSE (ifx)->key);
2636 else { /* right not power of two */
2637 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2639 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2640 emitcode (bopnames_lit[bitop],
2642 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2645 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2646 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2648 lbl = newiTempLabel (NULL);
2649 if (IC_TRUE (ifx)) {
2650 emitcode ("breq", "L%05d", lbl->key);
2651 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2654 emitcode ("brne", "L%05d", lbl->key);
2655 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2657 emitcode ("", "L%05d:", lbl->key);
2659 else if (size == 2) {
2660 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2661 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2662 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2663 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2664 emitcode ("sbiw", "r24,0");
2665 lbl = newiTempLabel (NULL);
2666 if (IC_TRUE (ifx)) {
2667 emitcode ("breq", "L%05d", lbl->key);
2668 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2671 emitcode ("brne", "L%05d", lbl->key);
2672 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2674 emitcode ("", "L%05d:", lbl->key);
2677 lbl = newiTempLabel (NULL);
2678 lbl1 = newiTempLabel (NULL);
2680 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2681 emitcode (bopnames_lit [bitop], "%s,lo8(%d)",
2682 aopGet (AOP (IC_LEFT (ic)), offset),
2686 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2688 emitcode ("andi", "r24,lo8(%d)", lit);
2690 emitcode ("brne", "L%05d", lbl->key);
2695 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2697 emitcode ("rjmp", "L%05d", lbl1->key);
2698 emitcode ("", "L%05d:", lbl->key);
2701 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2702 emitcode ("", "L%05d:", lbl1->key);
2707 else { /* right is not a literal */
2708 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2709 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2712 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2713 aopGet (AOP (IC_RIGHT (ic)), 0));
2716 emitcode (bopnames[bitop], "%s,%s",
2717 aopGet (AOP (IC_RIGHT (ic)), 0),
2718 aopGet (AOP (IC_LEFT (ic)), 0));
2721 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2722 emitcode (bopnames[bitop], "r0,%s",
2723 aopGet (AOP (IC_RIGHT (ic)), 0));
2725 lbl = newiTempLabel (NULL);
2726 if (IC_TRUE (ifx)) {
2727 emitcode ("breq", "L%05d", lbl->key);
2728 emitcode ("rjmp", "L%05d",
2729 IC_TRUE (ifx)->key);
2732 emitcode ("brne", "L%05d", lbl->key);
2733 emitcode ("rjmp", "L%05d",
2734 IC_FALSE (ifx)->key);
2736 emitcode ("", "L%05d:", lbl->key);
2738 else if (size == 2) {
2739 emitcode ("mov", "r24,%s",
2740 aopGet (AOP (IC_LEFT (ic)), 0));
2741 emitcode ("mov", "r25,%s",
2742 aopGet (AOP (IC_LEFT (ic)), 1));
2743 emitcode (bopnames[bitop], "r24,%s",
2744 aopGet (AOP (IC_RIGHT (ic)), 0));
2745 emitcode (bopnames[bitop], "r25,%s",
2746 aopGet (AOP (IC_RIGHT (ic)), 1));
2747 emitcode ("sbiw", "r24,0");
2748 lbl = newiTempLabel (NULL);
2749 if (IC_TRUE (ifx)) {
2750 emitcode ("breq", "L%05d", lbl->key);
2751 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2754 emitcode ("brne", "L%05d", lbl->key);
2755 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2757 emitcode ("", "L%05d:", lbl->key);
2760 lbl = newiTempLabel (NULL);
2761 lbl1 = newiTempLabel (NULL);
2764 emitcode (bopnames[bitop], "%s,%s",
2765 aopGet (AOP (IC_LEFT (ic)), offset),
2766 aopGet (AOP (IC_RIGHT (ic)), offset));
2769 emitcode (bopnames[bitop], "%s,%s",
2770 aopGet (AOP (IC_RIGHT (ic)), offset),
2771 aopGet (AOP (IC_LEFT (ic)), offset));
2774 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2775 emitcode (bopnames[bitop], "r0,%s",
2776 aopGet (AOP (IC_RIGHT (ic)), offset));
2778 emitcode ("brne", "L%05d", lbl->key);
2783 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2785 emitcode ("rjmp", "L%05d", lbl1->key);
2786 emitcode ("", "L%05d:", lbl->key);
2789 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2790 emitcode ("", "L%05d:", lbl1->key);
2797 /* result needs to go a register */
2798 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2799 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2801 if (AOP_TYPE (right) == AOP_LIT) {
2803 (int) floatFromVal (AOP (right)->aopu.
2805 if (((lit >> (8 * offset)) & 0xff) == 0) {
2806 if (bitop == AVR_AND) {
2807 aopPut (AOP (result), zero, offset++);
2810 else if (bitop == AVR_OR) {
2812 aopPut (AOP (result),
2822 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2823 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2824 (bitop == AVR_AND || bitop == AVR_OR)) {
2825 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2826 aopGet (AOP (IC_LEFT (ic)), offset),
2828 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2831 emitcode (bopnames[bitop], "%s,%s",
2832 aopGet (AOP (IC_LEFT (ic)), offset),
2833 aopGet (AOP (IC_RIGHT (ic)), offset));
2837 emitcode (bopnames[bitop], "%s,%s",
2838 aopGet (AOP (IC_RIGHT (ic)), offset),
2839 aopGet (AOP (IC_LEFT (ic)), offset));
2842 aopPut (AOP (IC_RESULT (ic)),
2843 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2844 emitcode (bopnames[bitop],
2845 aopGet (AOP (IC_RESULT (ic)), offset),
2846 aopGet (AOP (IC_RIGHT (ic)), offset));
2851 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2852 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2853 freeAsmop (result, NULL, ic, TRUE);
2856 /*-----------------------------------------------------------------*/
2857 /* genAnd - code for and */
2858 /*-----------------------------------------------------------------*/
2860 genAnd (iCode * ic, iCode * ifx)
2862 genBitWise (ic, ifx, AVR_AND);
2865 /*-----------------------------------------------------------------*/
2866 /* genOr - code for or */
2867 /*-----------------------------------------------------------------*/
2869 genOr (iCode * ic, iCode * ifx)
2871 genBitWise (ic, ifx, AVR_OR);
2874 /*-----------------------------------------------------------------*/
2875 /* genXor - code for xclusive or */
2876 /*-----------------------------------------------------------------*/
2878 genXor (iCode * ic, iCode * ifx)
2880 genBitWise (ic, ifx, AVR_XOR);
2883 /*-----------------------------------------------------------------*/
2884 /* genInline - write the inline code out */
2885 /*-----------------------------------------------------------------*/
2887 genInline (iCode * ic)
2889 char buffer[MAX_INLINEASM];
2893 _G.inLine += (!options.asmpeep);
2894 strcpy (buffer, IC_INLINE (ic));
2896 /* emit each line as a code */
2917 /* emitcode("",buffer); */
2918 _G.inLine -= (!options.asmpeep);
2921 /*-----------------------------------------------------------------*/
2922 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2923 /*-----------------------------------------------------------------*/
2925 genRotC (iCode * ic, int lr)
2927 operand *left, *result;
2928 int size, offset = 0;
2930 /* rotate right with carry */
2931 left = IC_LEFT (ic);
2932 result = IC_RESULT (ic);
2933 aopOp (left, ic, FALSE);
2934 aopOp (result, ic, FALSE);
2936 /* move it to the result */
2937 size = AOP_SIZE (result);
2938 if (!sameRegs (AOP (left), AOP (result))) {
2941 aopPut (AOP (result),
2942 aopGet (AOP (left), offset), offset);
2945 size = AOP_SIZE (result);
2953 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
2955 emitcode ("sec", "");
2958 emitcode ((lr ? "ror" : "rol"), "%s",
2959 aopGet (AOP (result), offset));
2965 freeAsmop (left, NULL, ic, TRUE);
2966 freeAsmop (result, NULL, ic, TRUE);
2969 /*-----------------------------------------------------------------*/
2970 /* genRRC - rotate right with carry */
2971 /*-----------------------------------------------------------------*/
2978 /*-----------------------------------------------------------------*/
2979 /* genRLC - generate code for rotate left with carry */
2980 /*-----------------------------------------------------------------*/
2987 /*-----------------------------------------------------------------*/
2988 /* genGetHbit - generates code get highest order bit */
2989 /*-----------------------------------------------------------------*/
2991 genGetHbit (iCode * ic)
2993 operand *left, *result;
2996 left = IC_LEFT (ic);
2997 result = IC_RESULT (ic);
2998 aopOp (left, ic, FALSE);
2999 aopOp (result, ic, FALSE);
3001 size = AOP_SIZE (result);
3002 if (!sameRegs (AOP (left), AOP (result))) {
3003 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3004 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3005 emitcode ("subi", "%s,lo8(-1)",
3006 aopGet (AOP (result), size - 1));
3009 emitcode ("clr", "r0");
3010 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3011 emitcode ("subi", "r0,lo8(-1)");
3012 aopPut (AOP (result), "r0", 0);
3017 emitcode ("clr", aopGet (AOP (result), offset++));
3019 freeAsmop (left, NULL, ic, TRUE);
3020 freeAsmop (result, NULL, ic, TRUE);
3023 /*-----------------------------------------------------------------*/
3024 /* genShiftLeftLit - shift left by a known amount */
3025 /*-----------------------------------------------------------------*/
3027 genShiftLeftLit (iCode * ic)
3029 operand *left, *right, *result;
3030 int size, shCount, offset = 0;
3033 right = IC_RIGHT (ic);
3034 left = IC_LEFT (ic);
3035 result = IC_RESULT (ic);
3037 aopOp (left, ic, FALSE);
3038 aopOp (result, ic, FALSE);
3039 size = AOP_SIZE (result);
3040 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3042 if (shCount > (size * 8 - 1)) {
3044 aopPut (AOP (result), zero, offset++);
3049 if (!sameRegs (AOP (left), AOP (result)))
3050 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3052 if (AOP_ISHIGHREG(AOP(result),0)) {
3053 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3054 emitcode ("andi", "%s,0xf0");
3056 emitcode ("ldi","r24,0xf0");
3057 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3058 emitcode ("and", "%s,r24");
3063 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3064 aopGet (AOP (result), 0));
3068 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3071 if (shCount >= 12) {
3072 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3073 aopPut (AOP (result), zero, 0);
3074 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3075 if (AOP_ISHIGHREG(AOP(result),1)) {
3076 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3078 emitcode ("ldi","r24,0xf0");
3079 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3085 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3086 aopPut (AOP (result), zero, 0);
3092 if (!sameRegs (AOP (left), AOP (result))) {
3093 aopPut (AOP (result), aopGet (AOP (left), 0),
3095 aopPut (AOP (result), aopGet (AOP (left), 1),
3098 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3099 emitcode ("andi", "r24,0x0f");
3100 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3101 emitcode("ldi","r25,0xf0");
3103 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3104 if (AOP_ISHIGHREG(AOP(result),0)) {
3105 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3107 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3109 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3110 if (AOP_ISHIGHREG(AOP(result),1)) {
3111 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3113 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3115 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3117 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3118 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3121 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3125 aopPut (AOP (result),
3126 aopGet (AOP (left), offset), offset);
3132 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3135 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3136 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3141 assert ("shifting generic pointer ?\n");
3144 /* 32 bits we do only byte boundaries */
3145 if (shCount >= 24) {
3146 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3147 aopPut (AOP (result), zero, 2);
3148 aopPut (AOP (result), zero, 1);
3149 aopPut (AOP (result), zero, 0);
3153 if (shCount >= 16) {
3154 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3155 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3156 aopPut (AOP (result), zero, 1);
3157 aopPut (AOP (result), zero, 0);
3162 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3163 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3164 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3165 aopPut (AOP (result), zero, 0);
3169 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3172 aopPut (AOP (result),
3173 aopGet (AOP (left), offset), offset);
3177 size = AOP_SIZE (result);
3183 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3184 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3185 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3186 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3191 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3192 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3193 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3198 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3199 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3204 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3212 freeAsmop (left, NULL, ic, TRUE);
3213 freeAsmop (right, NULL, ic, TRUE);
3214 freeAsmop (result, NULL, ic, TRUE);
3217 /*-----------------------------------------------------------------*/
3218 /* genLeftShift - generates code for left shifting */
3219 /*-----------------------------------------------------------------*/
3221 genLeftShift (iCode * ic)
3223 operand *left, *right, *result;
3227 right = IC_RIGHT (ic);
3228 left = IC_LEFT (ic);
3229 result = IC_RESULT (ic);
3231 aopOp (right, ic, FALSE);
3233 if (AOP_TYPE (right) == AOP_LIT) {
3234 genShiftLeftLit (ic);
3239 aopOp (left, ic, FALSE);
3240 aopOp (result, ic, FALSE);
3241 size = AOP_SIZE (result);
3243 if (AOP_SIZE (right) > 1) {
3244 if (isRegPair (AOP (right))) {
3245 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3248 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3249 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3253 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3255 if (!sameRegs (AOP (left), AOP (result))) {
3257 aopPut (AOP (result), aopGet (AOP (left), offset),
3261 size = AOP_SIZE (result);
3263 tlbl = newiTempLabel (NULL);
3264 emitcode ("", "L%05d:", tlbl->key);
3268 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3270 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3273 if (AOP_SIZE (right) > 1)
3274 emitcode ("sbiw", "r24,1");
3276 emitcode ("dec", "r24");
3277 emitcode ("brne", "L%05d", tlbl->key);
3279 freeAsmop (left, NULL, ic, TRUE);
3280 freeAsmop (right, NULL, ic, TRUE);
3281 freeAsmop (result, NULL, ic, TRUE);
3284 /*-----------------------------------------------------------------*/
3285 /* genShiftRightLit - generate for right shift with known count */
3286 /*-----------------------------------------------------------------*/
3288 genShiftRightLit (iCode * ic)
3290 operand *left = IC_LEFT (ic)
3291 , *right = IC_RIGHT (ic)
3292 , *result = IC_RESULT (ic);
3293 int size, shCount, offset = 0;
3295 sym_link *letype = getSpec (operandType (left));
3296 int sign = !SPEC_USIGN (letype);
3298 right = IC_RIGHT (ic);
3299 left = IC_LEFT (ic);
3300 result = IC_RESULT (ic);
3302 aopOp (left, ic, FALSE);
3303 aopOp (result, ic, FALSE);
3304 size = AOP_SIZE (result);
3305 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3307 /* if signed then give up and use a loop to shift */
3310 if (!sameRegs (AOP (left), AOP (result))) {
3312 aopPut (AOP (result),
3313 aopGet (AOP (left), offset), offset);
3316 size = size = AOP_SIZE (result);
3319 /* be as economical as possible */
3324 size = AOP_SIZE (result);
3326 if (offset == (size - 1))
3327 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3329 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3335 emitcode ("ldi", "r24,lo8(%d)", shCount);
3336 tlbl = newiTempLabel (NULL);
3337 emitcode ("", "L%05d:", tlbl->key);
3340 if (offset == (size - 1))
3341 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3343 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3346 emitcode ("dec", "r24");
3347 emitcode ("brne", "L%05d", tlbl->key);
3351 if (shCount > (size * 8 - 1)) {
3353 aopPut (AOP (result), zero, offset++);
3356 /* for unsigned we can much more efficient */
3359 if (!sameRegs (AOP (left), AOP (result)))
3360 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3362 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3363 if (AOP_ISHIGHREG(AOP(result),0)) {
3364 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3366 emitcode ("ldi","r24,0x0f");
3367 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3372 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3375 if (shCount >= 12) {
3376 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3377 aopPut (AOP (result), zero, 1);
3378 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3379 if (AOP_ISHIGHREG(AOP(result),0)) {
3380 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3382 emitcode ("ldi","r24,0x0f");
3383 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3389 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3390 aopPut (AOP (result), zero, 1);
3396 if (!sameRegs (AOP (left), AOP (result))) {
3397 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3398 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3400 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3401 emitcode("ldi","r25,0x0f");
3403 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3404 emitcode ("andi", "r24,0xf0");
3405 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3406 if (AOP_ISHIGHREG(AOP(result),0)) {
3407 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3409 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3411 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3412 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3413 if (AOP_ISHIGHREG(AOP(result),1)) {
3414 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3416 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3419 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3420 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3424 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3428 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3434 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3437 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3438 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3444 assert ("shifting generic pointer ?\n");
3447 /* 32 bits we do only byte boundaries */
3448 if (shCount >= 24) {
3449 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3450 aopPut (AOP (result), zero, 1);
3451 aopPut (AOP (result), zero, 2);
3452 aopPut (AOP (result), zero, 3);
3456 if (shCount >= 16) {
3457 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3458 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3459 aopPut (AOP (result), zero, 2);
3460 aopPut (AOP (result), zero, 3);
3465 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3466 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3467 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3468 aopPut (AOP (result), zero, 3);
3472 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3475 aopPut (AOP (result),
3476 aopGet (AOP (left), offset), offset);
3480 size = AOP_SIZE (result);
3486 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3487 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3488 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3489 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3494 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3495 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3496 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3501 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3502 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3507 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3514 freeAsmop (left, NULL, ic, TRUE);
3515 freeAsmop (right, NULL, ic, TRUE);
3516 freeAsmop (result, NULL, ic, TRUE);
3519 /*-----------------------------------------------------------------*/
3520 /* genRightShift - generate code for right shifting */
3521 /*-----------------------------------------------------------------*/
3523 genRightShift (iCode * ic)
3525 operand *right, *left, *result;
3528 int sign = 0, first = 1;
3531 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3533 if (AOP_TYPE (right) == AOP_LIT) {
3534 genShiftRightLit (ic);
3538 if (AOP_SIZE (right) > 1) {
3539 if (isRegPair (AOP (right))) {
3540 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3543 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3544 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3548 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3550 aopOp (left = IC_LEFT (ic), ic, FALSE);
3551 aopOp (result = IC_RESULT (ic), ic, FALSE);
3552 size = AOP_SIZE (result);
3553 tlbl = newiTempLabel (NULL);
3554 emitcode ("", "L%05d:", tlbl->key);
3556 letype = getSpec (operandType (left));
3557 sign = !SPEC_USIGN (letype);
3558 if (!sameRegs (AOP (left), AOP (result))) {
3560 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3563 size = AOP_SIZE (result);
3565 size = AOP_SIZE (result);
3569 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3571 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3575 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3578 if (AOP_SIZE (right) > 1)
3579 emitcode ("sbiw", "r24,1");
3581 emitcode ("dec", "r24");
3582 emitcode ("brne", "L%05d", tlbl->key);
3584 freeAsmop (left, NULL, ic, TRUE);
3585 freeAsmop (result, NULL, ic, TRUE);
3588 /*-----------------------------------------------------------------*/
3589 /* RRsh - shift right rn by known count */
3590 /*-----------------------------------------------------------------*/
3592 RRsh (int shCount,int reg)
3594 shCount &= 0x0007; // shCount : 0..7
3600 emitcode ("lsr", "r%d",reg);
3603 emitcode ("lsr", "r%d",reg);
3604 emitcode ("lsr", "r%d",reg);
3607 emitcode ("swap", "r%d",reg);
3608 emitcode ("lsl", "r%d",reg);
3611 emitcode ("swap", "r%d",reg);
3614 emitcode ("swap", "r%d",reg);
3615 emitcode ("lsr", "r%d",reg);
3618 emitcode ("swap","r%d",reg);
3619 emitcode ("lsr", "r%d",reg);
3620 emitcode ("lsr", "r%d",reg);
3623 emitcode ("swap","r%d",reg);
3624 emitcode ("lsr", "r%d",reg);
3625 emitcode ("lsr", "r%d",reg);
3626 emitcode ("lsr", "r%d",reg);
3631 /*-----------------------------------------------------------------*/
3632 /* RLsh - shift left rn by known count */
3633 /*-----------------------------------------------------------------*/
3635 RLsh (int shCount, int reg)
3637 shCount &= 0x0007; // shCount : 0..7
3643 emitcode ("lsl", "r%d",reg);
3646 emitcode ("lsl", "r%d",reg);
3647 emitcode ("lsl", "r%d",reg);
3650 emitcode ("swap","r%d",reg);
3651 emitcode ("lsr", "r%d",reg);
3654 emitcode ("swap", "r%d",reg);
3657 emitcode ("swap","r%d",reg);
3658 emitcode ("lsl", "r%d",reg);
3661 emitcode ("swap","r%d",reg);
3662 emitcode ("lsl", "r%d",reg);
3663 emitcode ("lsl", "r%d",reg);
3666 emitcode ("swap","r%d",reg);
3667 emitcode ("lsl", "r%d",reg);
3668 emitcode ("lsl", "r%d",reg);
3669 emitcode ("lsl", "r%d",reg);
3674 /*-----------------------------------------------------------------*/
3675 /* genUnpackBits - generates code for unpacking bits */
3676 /*-----------------------------------------------------------------*/
3678 genUnpackBits (operand * result, char *rname, int ptype)
3686 etype = getSpec (operandType (result));
3687 rsize = getSize (operandType (result));
3688 /* read the first byte */
3695 emitcode ("ld", "r24,%s+", rname);
3699 emitcode ("lpm", "r24,%s+", rname);
3703 emitcode ("call","__gptrget_pi");
3704 emitcode ("mov","r24,r0");
3708 rlen = SPEC_BLEN (etype);
3710 /* if we have bitdisplacement then it fits */
3711 /* into this byte completely or if length is */
3712 /* less than a byte */
3713 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3715 /* shift right acc */
3718 emitcode ("andi", "r24,lo(0x%x)",
3719 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3720 aopPut (AOP (result), "r24", offset++);
3724 /* bit field did not fit in a byte */
3725 aopPut (AOP (result), "r24", offset++);
3735 emitcode ("ld", "r24,%s+");
3739 emitcode ("lpm", "r24,%s+");
3743 emitcode ("call", "__gptrget_pi");
3748 /* if we are done */
3752 aopPut (AOP (result), "r24", offset++);
3757 aopPut (AOP (result), "r24", offset++);
3761 if (offset < rsize) {
3764 aopPut (AOP (result), zero, offset++);
3769 /*-----------------------------------------------------------------*/
3770 /* genDataPointerGet - generates code when ptr offset is known */
3771 /*-----------------------------------------------------------------*/
3773 genDataPointerGet (operand * left, operand * result, iCode * ic)
3777 int size, offset = 0;
3778 aopOp (result, ic, TRUE);
3780 /* get the string representation of the name */
3781 l = aopGet (AOP (left), 0);
3782 size = AOP_SIZE (result);
3785 sprintf (buffer, "(%s + %d)", l, offset);
3787 sprintf (buffer, "%s", l);
3788 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3792 freeAsmop (left, NULL, ic, TRUE);
3793 freeAsmop (result, NULL, ic, TRUE);
3796 /*-----------------------------------------------------------------*/
3797 /* genNearPointerGet - emitcode for near pointer fetch */
3798 /*-----------------------------------------------------------------*/
3800 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3805 char *rname, *frname = NULL;
3806 sym_link *rtype, *retype;
3807 sym_link *ltype = operandType (left);
3809 rtype = operandType (result);
3810 retype = getSpec (rtype);
3812 aopOp (left, ic, FALSE);
3814 /* if left is rematerialisable and
3815 result is not bit variable type and
3816 the left is pointer to data space i.e
3817 lower 128 bytes of space */
3818 if (AOP_TYPE (left) == AOP_IMMD &&
3819 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3820 genDataPointerGet (left, result, ic);
3824 /* if the value is already in a pointer register
3825 then don't need anything more */
3826 if (!AOP_INPREG (AOP (left))) {
3827 /* otherwise get a free pointer register */
3829 preg = getFreePtr (ic, &aop, FALSE, 0);
3830 if (isRegPair (AOP (left) )) {
3831 emitcode ("movw", "%s,%s",
3832 aop->aopu.aop_ptr->name,
3833 aopGet(AOP(left),0));
3835 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3836 aopGet (AOP (left), 0));
3837 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3838 aopGet (AOP (left), 1));
3844 frname = aopGet(aop,0);
3848 } else if (AOP_ISZ(aop)) {
3851 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3852 "pointer not in correct register");
3856 aopOp (result, ic, FALSE);
3858 /* if bitfield then unpack the bits */
3859 if (IS_BITVAR (retype))
3860 genUnpackBits (result, rname, POINTER);
3862 /* we have can just get the values */
3863 int size = AOP_SIZE (result);
3868 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3870 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3875 /* now some housekeeping stuff */
3877 /* we had to allocate for this iCode */
3879 if (isRegPair (AOP (left) )) {
3880 emitcode ("movw", "%s,%s",
3881 aopGet (AOP(left),0),
3882 aop->aopu.aop_ptr->name);
3884 emitcode ("mov", "%s,%s",
3885 aopGet (AOP (left), 0),
3886 aop->aopu.aop_ptr->name);
3887 emitcode ("mov", "%s,%s",
3888 aopGet (AOP (left), 1),
3889 aop->aop_ptr2->name);
3892 freeAsmop (NULL, aop, ic, TRUE);
3895 /* we did not allocate which means left
3896 already in a pointer register, then
3897 if size > 0 && this could be used again
3898 we have to point it back to where it
3900 if ((AOP_SIZE (result) > 1 &&
3901 !OP_SYMBOL (left)->remat &&
3902 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3903 int size = AOP_SIZE (result) - 1;
3904 emitcode ("sbiw", "%s,%d",frname,size);
3909 if (pi) pi->generated = 1;
3910 freeAsmop (left, NULL, ic, TRUE);
3911 freeAsmop (result, NULL, ic, TRUE);
3915 /*-----------------------------------------------------------------*/
3916 /* genCodePointerGet - gget value from code space */
3917 /*-----------------------------------------------------------------*/
3919 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3922 sym_link *retype = getSpec (operandType (result));
3926 aopOp (left, ic, FALSE);
3928 /* if the operand is already in Z register
3929 then we do nothing else we move the value to Z register */
3930 if (AOP_ISZ(AOP(left))) {
3934 getFreePtr(ic,&aop,FALSE,TRUE);
3935 if (isRegPair(AOP (left))) {
3936 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3938 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3939 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3944 aopOp (result, ic, FALSE);
3946 /* if bit then unpack */
3947 if (IS_BITVAR (retype))
3948 genUnpackBits (result, "Z", CPOINTER);
3950 size = AOP_SIZE (result);
3955 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
3957 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
3962 /* now some housekeeping stuff */
3964 /* we had to allocate for this iCode */
3966 if (isRegPair(AOP (left))) {
3967 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
3969 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
3970 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
3973 freeAsmop (NULL, aop, ic, TRUE);
3976 /* we did not allocate which means left
3977 already in a pointer register, then
3978 if size > 0 && this could be used again
3979 we have to point it back to where it
3981 if ((AOP_SIZE (result) > 1 &&
3982 !OP_SYMBOL (left)->remat &&
3983 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
3985 int size = AOP_SIZE (result) - 1;
3986 emitcode ("sbiw", "r30,%d",size);
3991 if (pi) pi->generated=1;
3992 freeAsmop (left, NULL, ic, TRUE);
3993 freeAsmop (result, NULL, ic, TRUE);
3997 /*-----------------------------------------------------------------*/
3998 /* genGenPointerGet - gget value from generic pointer space */
3999 /*-----------------------------------------------------------------*/
4001 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4005 sym_link *retype = getSpec (operandType (result));
4008 aopOp (left, ic, FALSE);
4010 /* if the operand is already in dptr
4011 then we do nothing else we move the value to dptr */
4012 if (AOP_ISZ(AOP(left))) {
4016 getFreePtr(ic,&aop,FALSE,TRUE);
4017 if (isRegPair(AOP(left))) {
4018 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4020 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4021 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4023 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4027 /* so Z register now contains the address */
4029 aopOp (result, ic, FALSE);
4031 /* if bit then unpack */
4032 if (IS_BITVAR (retype))
4033 genUnpackBits (result, "Z", GPOINTER);
4035 size = AOP_SIZE (result);
4040 emitcode ("call", "__gptrget_pi");
4042 emitcode ("call", "__gptrget");
4043 aopPut (AOP (result), "r0", offset++);
4048 /* now some housekeeping stuff */
4050 /* we had to allocate for this iCode */
4052 if (isRegPair(AOP (left))) {
4053 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4055 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4056 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4059 freeAsmop (NULL, aop, ic, TRUE);
4062 /* we did not allocate which means left
4063 already in a pointer register, then
4064 if size > 0 && this could be used again
4065 we have to point it back to where it
4067 if ((AOP_SIZE (result) > 1 &&
4068 !OP_SYMBOL (left)->remat &&
4069 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4071 int size = AOP_SIZE (result) - 1;
4072 emitcode ("sbiw", "r30,%d",size);
4075 if (pi) pi->generated=1;
4076 freeAsmop (left, NULL, ic, TRUE);
4077 freeAsmop (result, NULL, ic, TRUE);
4080 /*-----------------------------------------------------------------*/
4081 /* genPointerGet - generate code for pointer get */
4082 /*-----------------------------------------------------------------*/
4084 genPointerGet (iCode * ic, iCode *pi)
4086 operand *left, *result;
4087 sym_link *type, *etype;
4090 left = IC_LEFT (ic);
4091 result = IC_RESULT (ic);
4093 /* depending on the type of pointer we need to
4094 move it to the correct pointer register */
4095 type = operandType (left);
4096 etype = getSpec (type);
4097 /* if left is of type of pointer then it is simple */
4098 if (IS_PTR (type) && !IS_FUNC (type->next))
4099 p_type = DCL_TYPE (type);
4101 /* we have to go by the storage class */
4102 p_type = PTR_TYPE (SPEC_OCLS (etype));
4107 /* now that we have the pointer type we assign
4108 the pointer values */
4115 genMemPointerGet (left, result, ic, pi);
4119 genCodePointerGet (left, result, ic, pi);
4123 genGenPointerGet (left, result, ic, pi);
4129 /*-----------------------------------------------------------------*/
4130 /* genPackBits - generates code for packed bit storage */
4131 /*-----------------------------------------------------------------*/
4133 genPackBits (sym_link * etype,
4135 char *rname, int p_type)
4143 blen = SPEC_BLEN (etype);
4144 bstr = SPEC_BSTR (etype);
4146 l = aopGet (AOP (right), offset++);
4149 /* if the bit lenth is less than or */
4150 /* it exactly fits a byte then */
4151 if (SPEC_BLEN (etype) <= 8) {
4152 shCount = SPEC_BSTR (etype);
4154 /* shift left acc */
4157 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4164 emitcode ("ld", "r1,%s",rname);
4168 emitcode ("push", "r1");
4169 emitcode ("push", "r24");
4170 emitcode ("call", "__gptrget");
4171 emitcode ("pop", "r1");
4172 emitcode ("mov","r24,r0");
4176 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4177 ((unsigned char) (0xFF << (blen + bstr)) |
4178 (unsigned char) (0xFF >> (8 - bstr))));
4179 emitcode ("or", "r24,r1");
4180 if (p_type == GPOINTER)
4181 emitcode ("pop", "r1");
4190 emitcode("st","%s+,r24");
4194 emitcode("mov","r0,r24");
4195 emitcode ("call", "__gptrput_pi");
4200 if (SPEC_BLEN (etype) <= 8)
4203 rLen = SPEC_BLEN (etype);
4205 /* now generate for lengths greater than one byte */
4208 l = aopGet (AOP (right), offset++);
4219 emitcode ("st", "%s+,%s",rname,l);
4224 emitcode ("lcall", "__gptrput_pi");
4231 /* last last was not complete */
4233 /* save the byte & read byte */
4239 emitcode ("st","%s+,r24",rname);
4242 emitcode ("push", "r1");
4243 emitcode ("push", "r24");
4244 emitcode ("lcall", "__gptrget");
4245 emitcode ("mov","r24,r0");
4246 emitcode ("pop", "r1");
4250 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4251 emitcode ("or", "r24,r1");
4254 if (p_type == GPOINTER)
4255 emitcode ("pop", "r1");
4263 emitcode ("st", "%s,r24", rname);
4267 emitcode ("mov","r0,r24");
4268 emitcode ("call", "__gptrput");
4273 /*-----------------------------------------------------------------*/
4274 /* genDataPointerSet - remat pointer to data space */
4275 /*-----------------------------------------------------------------*/
4277 genDataPointerSet (operand * right, operand * result, iCode * ic)
4279 int size, offset = 0;
4280 char *l, buffer[256];
4282 aopOp (right, ic, FALSE);
4284 l = aopGet (AOP (result), 0);
4285 size = AOP_SIZE (right);
4288 sprintf (buffer, "(%s + %d)", l, offset);
4290 sprintf (buffer, "%s", l);
4291 emitcode ("sts", "%s,%s", buffer,
4292 aopGet (AOP (right), offset++));
4295 freeAsmop (right, NULL, ic, TRUE);
4296 freeAsmop (result, NULL, ic, TRUE);
4299 /*-----------------------------------------------------------------*/
4300 /* genNearPointerSet - emitcode for near pointer put */
4301 /*-----------------------------------------------------------------*/
4303 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4306 char *frname = NULL, *rname, *l;
4309 sym_link *ptype = operandType (result);
4311 retype = getSpec (operandType (right));
4313 aopOp (result, ic, FALSE);
4315 /* if the result is rematerializable &
4316 in data space & not a bit variable */
4317 if (AOP_TYPE (result) == AOP_IMMD &&
4318 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4319 genDataPointerSet (right, result, ic);
4322 if (!AOP_INPREG(AOP(result))) {
4323 /* otherwise get a free pointer register */
4325 getFreePtr (ic, &aop, FALSE, 0);
4326 if (isRegPair (AOP (result) )) {
4327 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4328 aopGet(AOP (result), 0));
4330 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4331 aopGet (AOP (result), 0));
4332 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4333 aopGet (AOP (result), 1));
4338 frname = aopGet(aop,0);
4341 aopOp (right, ic, FALSE);
4344 } else if (AOP_ISZ(aop)) {
4347 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4348 "pointer not in correct register");
4351 /* if bitfield then unpack the bits */
4352 if (IS_BITVAR (retype))
4353 genPackBits (retype, right, rname, POINTER);
4355 /* we have can just get the values */
4356 int size = AOP_SIZE (right);
4360 l = aopGet (AOP (right), offset);
4362 emitcode ("st", "%s+,%s", rname,l);
4364 emitcode ("st", "%s,%s", rname,l);
4369 /* now some housekeeping stuff */
4371 /* we had to allocate for this iCode */
4373 if (isRegPair (AOP (result) )) {
4374 emitcode ("movw", "%s,%s",
4375 aopGet(AOP(result),0),
4376 aop->aopu.aop_ptr->name);
4378 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4379 aopGet (AOP (result), 0));
4380 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4381 aopGet (AOP (result), 1));
4384 freeAsmop (NULL, aop, ic, TRUE);
4387 /* we did not allocate which means left
4388 already in a pointer register, then
4389 if size > 0 && this could be used again
4390 we have to point it back to where it
4392 if ((AOP_SIZE (right) > 1 &&
4393 !OP_SYMBOL (result)->remat &&
4394 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4395 int size = AOP_SIZE (right) - 1;
4396 emitcode ("sbiw", "%s,%d",frname,size);
4401 if (pi) pi->generated = 1;
4402 freeAsmop (result, NULL, ic, TRUE);
4403 freeAsmop (right, NULL, ic, TRUE);
4406 /*-----------------------------------------------------------------*/
4407 /* genGenPointerSet - set value from generic pointer space */
4408 /*-----------------------------------------------------------------*/
4410 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4414 sym_link *retype = getSpec (operandType (right));
4417 aopOp (result, ic, FALSE);
4419 /* if the operand is already in dptr
4420 then we do nothing else we move the value to dptr */
4421 if (AOP_ISZ(AOP(result))) {
4425 getFreePtr(ic,&aop,FALSE,TRUE);
4426 if (isRegPair(AOP(result))) {
4427 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4429 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4430 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4432 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4436 /* so Z register now contains the address */
4437 aopOp (right, ic, FALSE);
4439 /* if bit then unpack */
4440 if (IS_BITVAR (retype))
4441 genUnpackBits (result, "Z", GPOINTER);
4443 size = AOP_SIZE (right);
4447 char *l = aopGet(AOP (right), offset++);
4451 emitcode ("call", "__gptrput_pi");
4453 emitcode ("call", "__gptrput");
4457 /* now some housekeeping stuff */
4459 /* we had to allocate for this iCode */
4461 if (isRegPair(AOP(result))) {
4462 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4464 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4465 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4468 freeAsmop (NULL, aop, ic, TRUE);
4471 /* we did not allocate which means left
4472 already in a pointer register, then
4473 if size > 0 && this could be used again
4474 we have to point it back to where it
4476 if ((AOP_SIZE (right) > 1 &&
4477 !OP_SYMBOL (result)->remat &&
4478 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4479 int size = AOP_SIZE (right) - 1;
4480 emitcode ("sbiw", "r30,%d",size);
4483 if (pi) pi->generated = 1;
4484 freeAsmop (right, NULL, ic, TRUE);
4485 freeAsmop (result, NULL, ic, TRUE);
4488 /*-----------------------------------------------------------------*/
4489 /* genPointerSet - stores the value into a pointer location */
4490 /*-----------------------------------------------------------------*/
4492 genPointerSet (iCode * ic, iCode *pi)
4494 operand *right, *result;
4495 sym_link *type, *etype;
4498 right = IC_RIGHT (ic);
4499 result = IC_RESULT (ic);
4501 /* depending on the type of pointer we need to
4502 move it to the correct pointer register */
4503 type = operandType (result);
4504 etype = getSpec (type);
4505 /* if left is of type of pointer then it is simple */
4506 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4507 p_type = DCL_TYPE (type);
4510 /* we have to go by the storage class */
4511 p_type = PTR_TYPE (SPEC_OCLS (etype));
4515 /* now that we have the pointer type we assign
4516 the pointer values */
4523 genMemPointerSet (right, result, ic, pi);
4527 genGenPointerSet (right, result, ic, pi);
4533 /*-----------------------------------------------------------------*/
4534 /* genIfx - generate code for Ifx statement */
4535 /*-----------------------------------------------------------------*/
4537 genIfx (iCode * ic, iCode * popIc)
4539 operand *cond = IC_COND (ic);
4543 aopOp (cond, ic, FALSE);
4545 /* get the value into acc */
4546 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4547 cname = aopGet(AOP(cond),0);
4549 toBoolean (cond, "r24", 1);
4552 /* the result is now in the accumulator */
4553 freeAsmop (cond, NULL, ic, TRUE);
4555 /* if there was something to be popped then do it */
4559 emitcode("cpi","%s,0",cname);
4560 lbl = newiTempLabel(NULL);
4562 emitcode ("brne","L%05d",lbl->key);
4563 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4564 emitcode ("","L%05d:",lbl->key);
4566 emitcode ("breq","L%05d",lbl->key);
4567 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4568 emitcode ("","L%05d:",lbl->key);
4573 /*-----------------------------------------------------------------*/
4574 /* genAddrOf - generates code for address of */
4575 /*-----------------------------------------------------------------*/
4577 genAddrOf (iCode * ic)
4579 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4582 aopOp (IC_RESULT (ic), ic, FALSE);
4584 /* if the operand is on the stack then we
4585 need to get the stack offset of this
4588 /* if it has an offset then we need to compute
4591 emitcode ("mov", "a,_bp");
4592 emitcode ("add", "a,#0x%02x",
4593 ((char) sym->stack & 0xff));
4594 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4597 /* we can just move _bp */
4598 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4600 /* fill the result with zero */
4601 size = AOP_SIZE (IC_RESULT (ic)) - 1;
4604 if (options.stack10bit && size < (FPTRSIZE - 1)) {
4606 "*** warning: pointer to stack var truncated.\n");
4612 if (options.stack10bit && offset == 2) {
4613 aopPut (AOP (IC_RESULT (ic)), "0x40",
4617 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4624 /* object not on stack then we need the name */
4625 size = AOP_SIZE (IC_RESULT (ic));
4629 char s[SDCC_NAME_MAX];
4631 sprintf (s, "(%s >> %d)", sym->rname, offset * 8);
4633 sprintf (s, "%s", sym->rname);
4634 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4638 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4642 /*-----------------------------------------------------------------*/
4643 /* genFarFarAssign - assignment when both are in far space */
4644 /*-----------------------------------------------------------------*/
4646 genFarFarAssign (operand * result, operand * right, iCode * ic)
4648 int size = AOP_SIZE (right);
4651 /* first push the right side on to the stack */
4653 l = aopGet (AOP (right), offset++);
4655 emitcode ("push", "acc");
4658 freeAsmop (right, NULL, ic, FALSE);
4659 /* now assign DPTR to result */
4660 aopOp (result, ic, FALSE);
4661 size = AOP_SIZE (result);
4663 emitcode ("pop", "acc");
4664 aopPut (AOP (result), "a", --offset);
4666 freeAsmop (result, NULL, ic, FALSE);
4670 /*-----------------------------------------------------------------*/
4671 /* genAssign - generate code for assignment */
4672 /*-----------------------------------------------------------------*/
4674 genAssign (iCode * ic)
4676 operand *result, *right;
4678 unsigned long lit = 0L;
4680 result = IC_RESULT (ic);
4681 right = IC_RIGHT (ic);
4683 /* if they are the same */
4684 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4687 aopOp (right, ic, FALSE);
4689 /* special case both in far space */
4690 if (AOP_TYPE (right) == AOP_DPTR &&
4691 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4693 genFarFarAssign (result, right, ic);
4697 aopOp (result, ic, TRUE);
4699 /* if they are the same registers */
4700 if (sameRegs (AOP (right), AOP (result)))
4703 /* if the result is a bit */
4704 if (AOP_TYPE (result) == AOP_CRY) {
4706 /* if the right size is a literal then
4707 we know what the value is */
4708 if (AOP_TYPE (right) == AOP_LIT) {
4709 if (((int) operandLitValue (right)))
4710 aopPut (AOP (result), one, 0);
4712 aopPut (AOP (result), zero, 0);
4716 /* the right is also a bit variable */
4717 if (AOP_TYPE (right) == AOP_CRY) {
4718 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4719 aopPut (AOP (result), "c", 0);
4724 toBoolean (right, "", 0);
4725 aopPut (AOP (result), "a", 0);
4729 /* bit variables done */
4731 size = AOP_SIZE (result);
4733 if (AOP_TYPE (right) == AOP_LIT)
4735 (unsigned long) floatFromVal (AOP (right)->aopu.
4737 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4738 && (AOP_TYPE (right) == AOP_LIT)
4739 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4740 emitcode ("clr", "a");
4742 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4743 0) aopPut (AOP (result), "a", size);
4745 aopPut (AOP (result),
4746 aopGet (AOP (right), size), size);
4751 aopPut (AOP (result),
4752 aopGet (AOP (right), offset), offset);
4758 freeAsmop (right, NULL, ic, FALSE);
4759 freeAsmop (result, NULL, ic, TRUE);
4762 /*-----------------------------------------------------------------*/
4763 /* genJumpTab - genrates code for jump table */
4764 /*-----------------------------------------------------------------*/
4766 genJumpTab (iCode * ic)
4771 aopOp (IC_JTCOND (ic), ic, FALSE);
4772 /* get the condition into accumulator */
4773 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4775 /* multiply by three */
4776 emitcode ("add", "a,acc");
4777 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4778 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4780 jtab = newiTempLabel (NULL);
4781 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4782 emitcode ("jmp", "@a+dptr");
4783 emitcode ("", "%05d$:", jtab->key + 100);
4784 /* now generate the jump labels */
4785 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4786 jtab = setNextItem (IC_JTLABELS (ic)))
4787 emitcode ("ljmp", "%05d$", jtab->key + 100);
4791 /*-----------------------------------------------------------------*/
4792 /* genCast - gen code for casting */
4793 /*-----------------------------------------------------------------*/
4795 genCast (iCode * ic)
4797 operand *result = IC_RESULT (ic);
4798 sym_link *ctype = operandType (IC_LEFT (ic));
4799 sym_link *rtype = operandType (IC_RIGHT (ic));
4800 operand *right = IC_RIGHT (ic);
4803 /* if they are equivalent then do nothing */
4804 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4807 aopOp (right, ic, FALSE);
4808 aopOp (result, ic, FALSE);
4810 /* if the result is a bit */
4811 if (AOP_TYPE (result) == AOP_CRY) {
4812 /* if the right size is a literal then
4813 we know what the value is */
4814 if (AOP_TYPE (right) == AOP_LIT) {
4815 if (((int) operandLitValue (right)))
4816 aopPut (AOP (result), one, 0);
4818 aopPut (AOP (result), zero, 0);
4823 /* the right is also a bit variable */
4824 if (AOP_TYPE (right) == AOP_CRY) {
4825 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4826 aopPut (AOP (result), "c", 0);
4831 toBoolean (right, "", 0);
4832 aopPut (AOP (result), "a", 0);
4836 /* if they are the same size : or less */
4837 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4839 /* if they are in the same place */
4840 if (sameRegs (AOP (right), AOP (result)))
4843 /* if they in different places then copy */
4844 size = AOP_SIZE (result);
4847 aopPut (AOP (result),
4848 aopGet (AOP (right), offset), offset);
4855 /* if the result is of type pointer */
4856 if (IS_PTR (ctype)) {
4859 sym_link *type = operandType (right);
4860 sym_link *etype = getSpec (type);
4862 /* pointer to generic pointer */
4863 if (IS_GENPTR (ctype)) {
4867 p_type = DCL_TYPE (type);
4869 /* we have to go by the storage class */
4870 p_type = PTR_TYPE (SPEC_OCLS (etype));
4873 /* the first two bytes are known */
4874 size = GPTRSIZE - 1;
4877 aopPut (AOP (result),
4878 aopGet (AOP (right), offset), offset);
4881 /* the last byte depending on type */
4898 /* this should never happen */
4899 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4900 "got unknown pointer type");
4903 aopPut (AOP (result), l, GPTRSIZE - 1);
4907 /* just copy the pointers */
4908 size = AOP_SIZE (result);
4911 aopPut (AOP (result),
4912 aopGet (AOP (right), offset), offset);
4918 /* so we now know that the size of destination is greater
4919 than the size of the source */
4920 /* we move to result for the size of source */
4921 size = AOP_SIZE (right);
4924 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4928 /* now depending on the sign of the source && destination */
4929 size = AOP_SIZE (result) - AOP_SIZE (right);
4930 /* if unsigned or not an integral type */
4931 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4933 aopPut (AOP (result), zero, offset++);
4936 /* we need to extend the sign :{ */
4937 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4939 emitcode ("rlc", "a");
4940 emitcode ("subb", "a,acc");
4942 aopPut (AOP (result), "a", offset++);
4945 /* we are done hurray !!!! */
4948 freeAsmop (right, NULL, ic, TRUE);
4949 freeAsmop (result, NULL, ic, TRUE);
4953 /*-----------------------------------------------------------------*/
4954 /* genDjnz - generate decrement & jump if not zero instrucion */
4955 /*-----------------------------------------------------------------*/
4957 genDjnz (iCode * ic, iCode * ifx)
4963 /* if the if condition has a false label
4964 then we cannot save */
4968 /* if the minus is not of the form
4970 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
4971 !IS_OP_LITERAL (IC_RIGHT (ic)))
4974 if (operandLitValue (IC_RIGHT (ic)) != 1)
4977 /* if the size of this greater than one then no
4979 if (getSize (operandType (IC_RESULT (ic))) > 1)
4982 /* otherwise we can save BIG */
4983 lbl = newiTempLabel (NULL);
4984 lbl1 = newiTempLabel (NULL);
4986 aopOp (IC_RESULT (ic), ic, FALSE);
4988 if (IS_AOP_PREG (IC_RESULT (ic))) {
4989 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
4990 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
4991 emitcode ("jnz", "%05d$", lbl->key + 100);
4994 emitcode ("djnz", "%s,%05d$",
4995 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
4997 emitcode ("sjmp", "%05d$", lbl1->key + 100);
4998 emitcode ("", "%05d$:", lbl->key + 100);
4999 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5000 emitcode ("", "%05d$:", lbl1->key + 100);
5002 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5007 static char *recvregs[8] = {
5008 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5012 /*-----------------------------------------------------------------*/
5013 /* genReceive - generate code for a receive iCode */
5014 /*-----------------------------------------------------------------*/
5016 genReceive (iCode * ic)
5018 int size, offset = 0;
5019 aopOp (IC_RESULT (ic), ic, FALSE);
5020 size = AOP_SIZE (IC_RESULT (ic));
5022 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5028 /*-----------------------------------------------------------------*/
5029 /* gen51Code - generate code for 8051 based controllers */
5030 /*-----------------------------------------------------------------*/
5032 genAVRCode (iCode * lic)
5037 lineHead = lineCurr = NULL;
5039 /* print the allocation information */
5041 printAllocInfo (currFunc, codeOutFile);
5042 /* if debug information required */
5043 /* if (options.debug && currFunc) { */
5045 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5047 emitcode ("", ".type %s,@function", currFunc->name);
5050 /* stack pointer name */
5054 for (ic = lic; ic; ic = ic->next) {
5056 if (cln != ic->lineno) {
5057 if (options.debug) {
5059 emitcode ("", "C$%s$%d$%d$%d ==.",
5060 FileBaseName (ic->filename),
5061 ic->lineno, ic->level, ic->block);
5064 emitcode (";", "%s %d", ic->filename, ic->lineno);
5067 /* if the result is marked as
5068 spilt and rematerializable or code for
5069 this has already been generated then
5071 if (resultRemat (ic) || ic->generated)
5074 /* depending on the operation */
5093 /* IPOP happens only when trying to restore a
5094 spilt live range, if there is an ifx statement
5095 following this pop then the if statement might
5096 be using some of the registers being popped which
5097 would destory the contents of the register so
5098 we need to check for this condition and handle it */
5100 ic->next->op == IFX &&
5101 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5102 genIfx (ic->next, ic);
5120 genEndFunction (ic);
5140 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5157 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5161 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5165 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5169 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5173 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5177 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5189 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5193 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5197 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5224 case GET_VALUE_AT_ADDRESS:
5225 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5229 if (POINTER_SET (ic))
5230 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5256 addSet (&_G.sendSet, ic);
5265 /* now we are ready to call the
5266 peep hole optimizer */
5267 if (!options.nopeep)
5268 peepHole (&lineHead);
5270 /* now do the actual printing */
5271 printLine (lineHead, codeOutFile);