freebsd-ports/devel/avr-gcc/files/patch-xmega

892 lines
31 KiB
Text

--- ./gcc/config/avr/avr.c.orig 2010-03-08 12:55:13.000000000 +0100
+++ ./gcc/config/avr/avr.c 2010-03-08 12:55:36.000000000 +0100
@@ -55,6 +55,7 @@
static int avr_naked_function_p (tree);
static int interrupt_function_p (tree);
static int signal_function_p (tree);
+static int nmi_function_p (tree);
static int avr_OS_task_function_p (tree);
static int avr_regs_to_save (HARD_REG_SET *);
static int sequent_regs_live (void);
@@ -131,17 +132,24 @@
int avr_have_movw_lpmx_p = 0;
static const struct base_arch_s avr_arch_types[] = {
- { 1, 0, 0, 0, 0, 0, 0, 0, NULL }, /* unknown device specified */
- { 1, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=1" },
- { 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=2" },
- { 0, 0, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=25" },
- { 0, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=3" },
- { 0, 0, 1, 0, 1, 0, 0, 0, "__AVR_ARCH__=31" },
- { 0, 0, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=35" },
- { 0, 1, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=4" },
- { 0, 1, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=5" },
- { 0, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=51" },
- { 0, 1, 1, 1, 1, 1, 1, 0, "__AVR_ARCH__=6" }
+ { 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, /* Unknown device specified. */
+ { 1, 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=1" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=2" },
+ { 0, 0, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=25" },
+ { 0, 0, 1, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=3" },
+ { 0, 0, 1, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=31" },
+ { 0, 0, 1, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=35" },
+ { 0, 1, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=4" },
+ { 0, 1, 1, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=5" },
+ { 0, 1, 1, 1, 1, 1, 0, 0, 0, "__AVR_ARCH__=51" },
+ { 0, 1, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=6" },
+ { 0, 1, 0, 1, 0, 0, 0, 1, 0, "__AVR_ARCH__=101" },
+ { 0, 1, 1, 1, 0, 0, 0, 1, 0, "__AVR_ARCH__=102" },
+ { 0, 1, 1, 1, 0, 0, 0, 1, 1, "__AVR_ARCH__=103" },
+ { 0, 1, 1, 1, 1, 1, 0, 1, 0, "__AVR_ARCH__=104" },
+ { 0, 1, 1, 1, 1, 1, 0, 1, 1, "__AVR_ARCH__=105" },
+ { 0, 1, 1, 1, 1, 1, 1, 1, 0, "__AVR_ARCH__=106" },
+ { 0, 1, 1, 1, 1, 1, 1, 1, 1, "__AVR_ARCH__=107" }
};
/* These names are used as the index into the avr_arch_types[] table
@@ -159,7 +167,14 @@
ARCH_AVR4,
ARCH_AVR5,
ARCH_AVR51,
- ARCH_AVR6
+ ARCH_AVR6,
+ ARCH_AVRXMEGA1,
+ ARCH_AVRXMEGA2,
+ ARCH_AVRXMEGA3,
+ ARCH_AVRXMEGA4,
+ ARCH_AVRXMEGA5,
+ ARCH_AVRXMEGA6,
+ ARCH_AVRXMEGA7
};
struct mcu_type_s {
@@ -349,6 +364,35 @@
{ "avr6", ARCH_AVR6, NULL },
{ "atmega2560", ARCH_AVR6, "__AVR_ATmega2560__" },
{ "atmega2561", ARCH_AVR6, "__AVR_ATmega2561__" },
+ /* Enhanced, == 256K. */
+ /* Xmega, <= 8K FLASH. */
+ /* Xmega, > 8K, <= 64K FLASH, <= 64K RAM. */
+ { "avrxmega2", ARCH_AVRXMEGA2, NULL },
+ { "atxmega16a4", ARCH_AVRXMEGA2, "__AVR_ATxmega16A4__" },
+ { "atxmega16d4", ARCH_AVRXMEGA2, "__AVR_ATxmega16D4__" },
+ { "atxmega32d4", ARCH_AVRXMEGA2, "__AVR_ATxmega32D4__" },
+ /* Xmega, > 8K, <= 64K FLASH, > 64K RAM. */
+ { "avrxmega3", ARCH_AVRXMEGA3, NULL },
+ { "atxmega32a4", ARCH_AVRXMEGA3, "__AVR_ATxmega32A4__" },
+ /* Xmega, > 64K, <= 128K FLASH, <= 64K RAM. */
+ { "avrxmega4", ARCH_AVRXMEGA4, NULL },
+ { "atxmega64a3", ARCH_AVRXMEGA4, "__AVR_ATxmega64A3__" },
+ { "atxmega64d3", ARCH_AVRXMEGA4, "__AVR_ATxmega64D3__" },
+ /* Xmega, > 64K, <= 128K FLASH, > 64K RAM. */
+ { "avrxmega5", ARCH_AVRXMEGA5, NULL },
+ { "atxmega64a1", ARCH_AVRXMEGA5, "__AVR_ATxmega64A1__" },
+ /* Xmega, > 128K, <= 256K FLASH, <= 64K RAM. */
+ { "avrxmega6", ARCH_AVRXMEGA6, NULL },
+ { "atxmega128a3", ARCH_AVRXMEGA6, "__AVR_ATxmega128A3__" },
+ { "atxmega128d3", ARCH_AVRXMEGA6, "__AVR_ATxmega128D3__" },
+ { "atxmega192a3", ARCH_AVRXMEGA6, "__AVR_ATxmega192A3__" },
+ { "atxmega192d3", ARCH_AVRXMEGA6, "__AVR_ATxmega192D3__" },
+ { "atxmega256a3", ARCH_AVRXMEGA6, "__AVR_ATxmega256A3__" },
+ { "atxmega256a3b",ARCH_AVRXMEGA6, "__AVR_ATxmega256A3B__" },
+ { "atxmega256d3", ARCH_AVRXMEGA6, "__AVR_ATxmega256D3__" },
+ /* Xmega, > 128K, <= 256K FLASH, > 64K RAM. */
+ { "avrxmega7", ARCH_AVRXMEGA7, NULL },
+ { "atxmega128a1", ARCH_AVRXMEGA7, "__AVR_ATxmega128A1__" },
/* Assembler only. */
{ "avr1", ARCH_AVR1, NULL },
{ "at90s1200", ARCH_AVR1, "__AVR_AT90S1200__" },
@@ -531,6 +575,21 @@
return a != NULL_TREE;
}
+/* Return nonzero if FUNC is a nmi function as specified
+ by the "nmi" attribute. */
+
+static int
+nmi_function_p (tree func)
+{
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("nmi", DECL_ATTRIBUTES (func));
+ return a != NULL_TREE;
+}
+
/* Return nonzero if FUNC is a OS_task function. */
static int
@@ -690,6 +749,7 @@
cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
cfun->machine->is_signal = signal_function_p (current_function_decl);
+ cfun->machine->is_nmi = nmi_function_p (current_function_decl);
cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
/* Prologue: naked. */
@@ -725,17 +785,48 @@
/* Push SREG. */
insn = emit_move_insn (tmp_reg_rtx,
- gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)));
+ gen_rtx_MEM (QImode, GEN_INT (AVR_SREG_ADDR)));
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ /* Push RAMPD, RAMPX, RAMPY. */
+ if (AVR_HAVE_RAMPX_Y_D)
+ {
+ /* Push RAMPD. */
+ insn = emit_move_insn (tmp_reg_rtx,
+ gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPD_ADDR)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn = emit_move_insn (pushbyte, tmp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Push RAMPX. */
+ if (TEST_HARD_REG_BIT (set, REG_X) && TEST_HARD_REG_BIT (set, REG_X + 1))
+ {
+ insn = emit_move_insn (tmp_reg_rtx,
+ gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPX_ADDR)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn = emit_move_insn (pushbyte, tmp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Push RAMPY. */
+ if (TEST_HARD_REG_BIT (set, REG_Y) && TEST_HARD_REG_BIT (set, REG_Y + 1))
+ {
+ insn = emit_move_insn (tmp_reg_rtx,
+ gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPY_ADDR)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn = emit_move_insn (pushbyte, tmp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+
/* Push RAMPZ. */
if(AVR_HAVE_RAMPZ
&& (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)))
{
insn = emit_move_insn (tmp_reg_rtx,
- gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)));
+ gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPZ_ADDR)));
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
@@ -744,9 +835,46 @@
/* Clear zero reg. */
insn = emit_move_insn (zero_reg_rtx, const0_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
-
+
/* Prevent any attempt to delete the setting of ZERO_REG! */
emit_insn (gen_rtx_USE (VOIDmode, zero_reg_rtx));
+
+ /*
+ Clear RAMP? registers if used for data access in the interrupt/signal
+ context. Do this after the zero register has been explictly cleared.
+ */
+ if (AVR_HAVE_RAMPX_Y_D)
+ {
+ /* Set RAMPD to 0. */
+ insn = emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPD_ADDR)),
+ const0_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (TEST_HARD_REG_BIT (set, REG_X) && TEST_HARD_REG_BIT (set, REG_X + 1))
+ {
+ /* Set RAMPX to 0. */
+ insn = emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPX_ADDR)),
+ const0_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ if (TEST_HARD_REG_BIT (set, REG_Y) && TEST_HARD_REG_BIT (set, REG_Y + 1))
+ {
+ /* Set RAMPY to 0. */
+ insn = emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPY_ADDR)),
+ const0_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ if(AVR_HAVE_RAMPZ
+ && (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)))
+ {
+ /* Set RAMPZ to 0. */
+ insn = emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPZ_ADDR)),
+ const0_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
}
if (minimize && (frame_pointer_needed
|| (AVR_2_BYTE_PC && live_seq > 6)
@@ -1010,14 +1138,39 @@
&& (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)))
{
emit_insn (gen_popqi (tmp_reg_rtx));
- emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(RAMPZ_ADDR)),
+ emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(AVR_RAMPZ_ADDR)),
tmp_reg_rtx);
}
+ /* Restore RAMPY, RAMPX, RAMPD using tmp reg as scratch. */
+ if (AVR_HAVE_RAMPX_Y_D)
+ {
+ /* Pop RAMPY. */
+ if (TEST_HARD_REG_BIT (set, REG_Y) && TEST_HARD_REG_BIT (set, REG_Y + 1))
+ {
+ emit_insn (gen_popqi (tmp_reg_rtx));
+ emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPY_ADDR)),
+ tmp_reg_rtx);
+ }
+
+ /* Pop RAMPX. */
+ if (TEST_HARD_REG_BIT (set, REG_X) && TEST_HARD_REG_BIT (set, REG_X + 1))
+ {
+ emit_insn (gen_popqi (tmp_reg_rtx));
+ emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPX_ADDR)),
+ tmp_reg_rtx);
+ }
+
+ /* Pop RAMPD. */
+ emit_insn (gen_popqi (tmp_reg_rtx));
+ emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPD_ADDR)),
+ tmp_reg_rtx);
+ }
+
/* Restore SREG using tmp reg as scratch. */
emit_insn (gen_popqi (tmp_reg_rtx));
- emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(SREG_ADDR)),
+ emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(AVR_SREG_ADDR)),
tmp_reg_rtx);
/* Restore tmp REG. */
@@ -1786,8 +1939,9 @@
}
/* Use simple load of stack pointer if no interrupts are used
or inside main or signal function prologue where they disabled. */
- else if (TARGET_NO_INTERRUPTS
- || (reload_completed
+ else if (TARGET_NO_INTERRUPTS
+ || (!AVR_XMEGA
+ && reload_completed
&& cfun->machine->is_signal
&& prologue_epilogue_contains (insn)))
{
@@ -1796,7 +1950,8 @@
AS2 (out,__SP_L__,%A1));
}
/* In interrupt prolog we know interrupts are enabled. */
- else if (reload_completed
+ else if (!AVR_XMEGA
+ && reload_completed
&& cfun->machine->is_interrupt
&& prologue_epilogue_contains (insn))
{
@@ -1806,12 +1961,21 @@
"sei" CR_TAB
AS2 (out,__SP_L__,%A1));
}
- *l = 5;
- return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
- "cli" CR_TAB
- AS2 (out,__SP_H__,%B1) CR_TAB
- AS2 (out,__SREG__,__tmp_reg__) CR_TAB
- AS2 (out,__SP_L__,%A1));
+ if(AVR_XMEGA)
+ {
+ *l = 2;
+ return (AS2 (out,__SP_L__,%A1) CR_TAB
+ AS2 (out,__SP_H__,%B1));
+ }
+ else
+ {
+ *l = 5;
+ return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
+ "cli" CR_TAB
+ AS2 (out,__SP_H__,%B1) CR_TAB
+ AS2 (out,__SREG__,__tmp_reg__) CR_TAB
+ AS2 (out,__SP_L__,%A1));
+ }
}
else if (test_hard_reg_class (STACK_REG, src))
{
@@ -1946,7 +2110,7 @@
if (CONSTANT_ADDRESS_P (x))
{
- if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
+ if (CONST_INT_P (x) && INTVAL (x) == AVR_SREG_ADDR)
{
*l = 1;
return AS2 (in,%0,__SREG__);
@@ -1954,7 +2118,8 @@
if (avr_io_address_p (x, 1))
{
*l = 1;
- return AS2 (in,%0,%1-0x20);
+ op[2] = GEN_INT(AVR_IO_OFFSET);
+ return AS2 (in,%0,%1-%2);
}
*l = 2;
return AS2 (lds,%0,%1);
@@ -2142,8 +2307,9 @@
if (avr_io_address_p (base, 2))
{
*l = 2;
- return (AS2 (in,%A0,%A1-0x20) CR_TAB
- AS2 (in,%B0,%B1-0x20));
+ op[2] = GEN_INT(AVR_IO_OFFSET);
+ return (AS2 (in,%A0,%A1-%2) CR_TAB
+ AS2 (in,%B0,%B1-%2));
}
*l = 4;
return (AS2 (lds,%A0,%A1) CR_TAB
@@ -2634,7 +2800,7 @@
if (CONSTANT_ADDRESS_P (x))
{
- if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
+ if (CONST_INT_P (x) && INTVAL (x) == AVR_SREG_ADDR)
{
*l = 1;
return AS2 (out,__SREG__,%1);
@@ -2642,7 +2808,8 @@
if (avr_io_address_p (x, 1))
{
*l = 1;
- return AS2 (out,%0-0x20,%1);
+ op[2] = GEN_INT(AVR_IO_OFFSET);
+ return AS2 (out,%0-%2,%1);
}
*l = 2;
return AS2 (sts,%0,%1);
@@ -2721,11 +2888,20 @@
if (avr_io_address_p (base, 2))
{
*l = 2;
- return (AS2 (out,%B0-0x20,%B1) CR_TAB
- AS2 (out,%A0-0x20,%A1));
+ op[2] = GEN_INT(AVR_IO_OFFSET);
+ if (AVR_XMEGA)
+ return (AS2 (out,%A0-%2,%A1) CR_TAB
+ AS2 (out,%B0-%2,%B1));
+ else
+ return (AS2 (out,%B0-%2,%B1) CR_TAB
+ AS2 (out,%A0-%2,%A1));
}
- return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
- AS2 (sts,%A0,%A1));
+ if (AVR_XMEGA)
+ return *l = 4, (AS2 (sts,%A0,%A1) CR_TAB
+ AS2 (sts,%B0,%B1));
+ else
+ return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
+ AS2 (sts,%A0,%A1));
}
if (reg_base > 0)
{
@@ -2740,11 +2916,20 @@
AS2 (adiw,r26,1) CR_TAB
AS2 (st,X,__tmp_reg__));
else
- return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
- AS2 (adiw,r26,1) CR_TAB
- AS2 (st,X,__tmp_reg__) CR_TAB
- AS2 (sbiw,r26,1) CR_TAB
- AS2 (st,X,r26));
+ {
+ if (!AVR_XMEGA)
+ return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+ AS2 (adiw,r26,1) CR_TAB
+ AS2 (st,X,__tmp_reg__) CR_TAB
+ AS2 (sbiw,r26,1) CR_TAB
+ AS2 (st,X,r26));
+ else
+ return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+ AS2 (st,X,r26) CR_TAB
+ AS2 (adiw,r26,1) CR_TAB
+ AS2 (st,X,__tmp_reg__) CR_TAB
+ AS2 (sbiw,r26,1));
+ }
}
else
{
@@ -2752,14 +2937,27 @@
return *l=2, (AS2 (st,X+,%A1) CR_TAB
AS2 (st,X,%B1));
else
- return *l=3, (AS2 (adiw,r26,1) CR_TAB
- AS2 (st,X,%B1) CR_TAB
- AS2 (st,-X,%A1));
+ {
+ if (!AVR_XMEGA)
+ return *l=3, (AS2 (adiw,r26,1) CR_TAB
+ AS2 (st,X,%B1) CR_TAB
+ AS2 (st,-X,%A1));
+ else
+ return *l=3, (AS2 (st,X+,%A1) CR_TAB
+ AS2 (st,X,%B1) CR_TAB
+ AS2 (sbiw,r26,1));
+ }
}
}
else
- return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
- AS2 (st,%0,%A1));
+ {
+ if (!AVR_XMEGA)
+ return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
+ AS2 (st,%0,%A1));
+ else
+ return *l=2, (AS2 (st,%0,%A1) CR_TAB
+ AS2 (std,%0+1,%B1));
+ }
}
else if (GET_CODE (base) == PLUS)
{
@@ -2770,48 +2968,104 @@
if (reg_base != REG_Y)
fatal_insn ("incorrect insn:",insn);
- if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
- return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
- AS2 (std,Y+63,%B1) CR_TAB
- AS2 (std,Y+62,%A1) CR_TAB
- AS2 (sbiw,r28,%o0-62));
-
- return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
- AS2 (sbci,r29,hi8(-%o0)) CR_TAB
- AS2 (std,Y+1,%B1) CR_TAB
- AS2 (st,Y,%A1) CR_TAB
- AS2 (subi,r28,lo8(%o0)) CR_TAB
- AS2 (sbci,r29,hi8(%o0)));
+ if (!AVR_XMEGA)
+ {
+ if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
+ return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
+ AS2 (std,Y+63,%B1) CR_TAB
+ AS2 (std,Y+62,%A1) CR_TAB
+ AS2 (sbiw,r28,%o0-62));
+
+ return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
+ AS2 (sbci,r29,hi8(-%o0)) CR_TAB
+ AS2 (std,Y+1,%B1) CR_TAB
+ AS2 (st,Y,%A1) CR_TAB
+ AS2 (subi,r28,lo8(%o0)) CR_TAB
+ AS2 (sbci,r29,hi8(%o0)));
+ }
+ else
+ {
+ if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
+ return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
+ AS2 (std,Y+62,%A1) CR_TAB
+ AS2 (std,Y+63,%B1) CR_TAB
+ AS2 (sbiw,r28,%o0-62));
+
+ return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
+ AS2 (sbci,r29,hi8(-%o0)) CR_TAB
+ AS2 (st,Y,%A1) CR_TAB
+ AS2 (std,Y+1,%B1) CR_TAB
+ AS2 (subi,r28,lo8(%o0)) CR_TAB
+ AS2 (sbci,r29,hi8(%o0)));
+ }
}
if (reg_base == REG_X)
{
/* (X + d) = R */
if (reg_src == REG_X)
{
- *l = 7;
- return (AS2 (mov,__tmp_reg__,r26) CR_TAB
- AS2 (mov,__zero_reg__,r27) CR_TAB
- AS2 (adiw,r26,%o0+1) CR_TAB
- AS2 (st,X,__zero_reg__) CR_TAB
- AS2 (st,-X,__tmp_reg__) CR_TAB
- AS1 (clr,__zero_reg__) CR_TAB
+ if (!AVR_XMEGA)
+ {
+ *l = 7;
+ return (AS2 (mov,__tmp_reg__,r26) CR_TAB
+ AS2 (mov,__zero_reg__,r27) CR_TAB
+ AS2 (adiw,r26,%o0+1) CR_TAB
+ AS2 (st,X,__zero_reg__) CR_TAB
+ AS2 (st,-X,__tmp_reg__) CR_TAB
+ AS1 (clr,__zero_reg__) CR_TAB
+ AS2 (sbiw,r26,%o0));
+ }
+ else
+ {
+ *l = 7;
+ return (AS2 (mov,__tmp_reg__,r26) CR_TAB
+ AS2 (mov,__zero_reg__,r27) CR_TAB
+ AS2 (adiw,r26,%o0) CR_TAB
+ AS2 (st,X+,__tmp_reg__) CR_TAB
+ AS2 (st,X,__zero_reg__) CR_TAB
+ AS1 (clr,__zero_reg__) CR_TAB
+ AS2 (sbiw,r26,%o0+1));
+ }
+ }
+ if (!AVR_XMEGA)
+ {
+ *l = 4;
+ return (AS2 (adiw,r26,%o0+1) CR_TAB
+ AS2 (st,X,%B1) CR_TAB
+ AS2 (st,-X,%A1) CR_TAB
AS2 (sbiw,r26,%o0));
}
- *l = 4;
- return (AS2 (adiw,r26,%o0+1) CR_TAB
- AS2 (st,X,%B1) CR_TAB
- AS2 (st,-X,%A1) CR_TAB
- AS2 (sbiw,r26,%o0));
+ else
+ {
+ *l = 4;
+ return (AS2 (adiw,r26,%o0) CR_TAB
+ AS2 (st,X+,%A1) CR_TAB
+ AS2 (st,X,%B1) CR_TAB
+ AS2 (sbiw,r26,%o0+1));
+ }
}
- return *l=2, (AS2 (std,%B0,%B1) CR_TAB
- AS2 (std,%A0,%A1));
+
+ if (!AVR_XMEGA)
+ return *l=2, (AS2 (std,%B0,%B1) CR_TAB
+ AS2 (std,%A0,%A1));
+ else
+ return *l=2, (AS2 (std,%A0,%A1) CR_TAB
+ AS2 (std,%B0,%B1));
}
else if (GET_CODE (base) == PRE_DEC) /* (--R) */
- return *l=2, (AS2 (st,%0,%B1) CR_TAB
- AS2 (st,%0,%A1));
+ {
+ if (mem_volatile_p && AVR_XMEGA)
+ return *l = 4, (AS2 (sbiw,%r0,1) CR_TAB
+ AS2 (st,%p0+,%A1) CR_TAB
+ AS2 (st,%p0,%B1) CR_TAB
+ AS2 (sbiw,%r0,2));
+ else
+ return *l=2, (AS2 (st,%0,%B1) CR_TAB
+ AS2 (st,%0,%A1));
+ }
else if (GET_CODE (base) == POST_INC) /* (R++) */
{
- if (mem_volatile_p)
+ if (mem_volatile_p && !AVR_XMEGA)
{
if (REGNO (XEXP (base, 0)) == REG_X)
{
@@ -2832,7 +3086,7 @@
*l = 2;
return (AS2 (st,%0,%A1) CR_TAB
- AS2 (st,%0,%B1));
+ AS2 (st,%0,%B1));
}
fatal_insn ("unknown move insn:",insn);
return "";
@@ -4712,6 +4966,7 @@
{ "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
{ "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
{ "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
+ { "nmi", 0, 0, true, false, false, avr_handle_fndecl_attribute },
{ "naked", 0, 0, false, true, true, avr_handle_fntype_attribute },
{ "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute },
{ NULL, 0, 0, false, false, false, NULL }
@@ -4800,6 +5055,14 @@
func_name);
}
}
+ else if (strncmp (attr, "nmi", strlen ("nmi")) == 0)
+ {
+ if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
+ {
+ warning (0, "%qs appears to be a misspelled nmi handler",
+ func_name);
+ }
+ }
}
return NULL_TREE;
@@ -4994,7 +5257,8 @@
/* fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
fputs ("__SREG__ = 0x3f\n"
"__SP_H__ = 0x3e\n"
- "__SP_L__ = 0x3d\n", asm_out_file);
+ "__SP_L__ = 0x3d\n"
+ "__CCP__ = 0x34\n", asm_out_file);
fputs ("__tmp_reg__ = 0\n"
"__zero_reg__ = 1\n", asm_out_file);
@@ -5888,15 +6152,18 @@
return !(regno & 1);
}
-/* Returns 1 if X is a valid address for an I/O register of size SIZE
- (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
- to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
+/* Returns 1 if X is a valid address for an I/O register of size SIZE
+ (1 or 2). Used for lds/sts -> in/out optimization. */
int
avr_io_address_p (rtx x, int size)
{
- return (optimize > 0 && GET_CODE (x) == CONST_INT
- && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
+ if(AVR_XMEGA)
+ return (optimize > 0 && GET_CODE (x) == CONST_INT
+ && INTVAL (x) >= 0 && INTVAL (x) <= 0x40 - size);
+ else
+ return (optimize > 0 && GET_CODE (x) == CONST_INT
+ && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
}
const char *
@@ -6074,16 +6341,17 @@
if (GET_CODE (operands[1]) == CONST_INT)
{
- if (INTVAL (operands[1]) < 0x40)
+ operands[4] = GEN_INT(AVR_IO_OFFSET); /* operands[3] is for the jump */
+ if (low_io_address_operand (operands[1], VOIDmode))
{
if (comp == EQ)
- output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
+ output_asm_insn (AS2 (sbis,%1-%4,%2), operands);
else
- output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
+ output_asm_insn (AS2 (sbic,%1-%4,%2), operands);
}
else
{
- output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
+ output_asm_insn (AS2 (in,__tmp_reg__,%1-%4), operands);
if (comp == EQ)
output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
else
--- ./gcc/config/avr/avr.h.orig 2010-03-08 12:55:09.000000000 +0100
+++ ./gcc/config/avr/avr.h 2010-03-08 12:55:36.000000000 +0100
@@ -44,8 +44,11 @@
/* Core have 'EICALL' and 'EIJMP' instructions. */
int have_eijmp_eicall;
- /* Reserved. */
- int reserved;
+ /* Core is in Xmega family. */
+ int xmega;
+
+ /* Core have RAMPX, RAMPY and RAMPD registers. */
+ int have_rampx_y_d;
const char *const macro;
};
@@ -68,6 +71,13 @@
builtin_define ("__AVR_HAVE_ELPMX__"); \
if (avr_have_movw_lpmx_p) \
builtin_define ("__AVR_HAVE_MOVW__"); \
+ if (avr_current_arch->have_elpm) \
+ { \
+ builtin_define ("__AVR_HAVE_RAMPZ__");\
+ builtin_define ("__AVR_HAVE_ELPM__"); \
+ } \
+ if (avr_current_arch->have_elpmx) \
+ builtin_define ("__AVR_HAVE_ELPMX__"); \
if (avr_have_movw_lpmx_p) \
builtin_define ("__AVR_HAVE_LPMX__"); \
if (avr_asm_only_p) \
@@ -88,6 +98,17 @@
builtin_define ("__AVR_HAVE_EIJMP_EICALL__"); \
if (TARGET_NO_INTERRUPTS) \
builtin_define ("__NO_INTERRUPTS__"); \
+ if (avr_current_arch->xmega) \
+ { \
+ builtin_define ("__AVR_XMEGA__"); \
+ builtin_define ("__AVR_HAVE_SPMX__"); \
+ } \
+ if (avr_current_arch->have_rampx_y_d) \
+ { \
+ builtin_define ("__AVR_HAVE_RAMPX__");\
+ builtin_define ("__AVR_HAVE_RAMPY__");\
+ builtin_define ("__AVR_HAVE_RAMPD__");\
+ } \
} \
while (0)
@@ -107,10 +128,19 @@
#define AVR_HAVE_LPMX (avr_have_movw_lpmx_p)
#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
+#define AVR_XMEGA (avr_current_arch->xmega)
+#define AVR_HAVE_RAMPX_Y_D (avr_current_arch->have_rampx_y_d)
#define AVR_2_BYTE_PC (!AVR_HAVE_EIJMP_EICALL)
#define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL)
+#define AVR_IO_OFFSET (AVR_XMEGA ? 0 : 0x20)
+#define AVR_RAMPD_ADDR (AVR_XMEGA ? 0x38 : 0)
+#define AVR_RAMPX_ADDR (AVR_XMEGA ? 0x39 : 0)
+#define AVR_RAMPY_ADDR (AVR_XMEGA ? 0x3A : 0)
+#define AVR_RAMPZ_ADDR (AVR_XMEGA ? 0x3B : 0x5B)
+#define AVR_SREG_ADDR (AVR_XMEGA ? 0x3F: 0x5F)
+
#define TARGET_VERSION fprintf (stderr, " (GNU assembler syntax)");
#define OVERRIDE_OPTIONS avr_override_options ()
@@ -935,6 +965,20 @@
mmcu=m3000*|\
mmcu=m3001*: -m avr5}\
%{mmcu=atmega256*:-m avr6}\
+%{mmcu=atxmega16a4|\
+ mmcu=atxmega16d4|\
+ mmcu=atxmega32d4:-m avrxmega2}\
+%{mmcu=atxmega32a4:-m avrxmega3} \
+%{mmcu=atxmega64a3|\
+ mmcu=atxmega64d3:-m avrxmega4} \
+%{mmcu=atxmega64a1:-m avrxmega5} \
+%{mmcu=atxmega128a3|\
+ mmcu=atxmega128d3|\
+ mmcu=atxmega192a3|\
+ mmcu=atxmega192d3|\
+ mmcu=atxmega256a3*|\
+ mmcu=atxmega256d3:-m avrxmega6} \
+%{mmcu=atxmega128a1:-m avrxmega7} \
%{mmcu=atmega324a|\
mmcu=atmega324p|\
mmcu=atmega324pa|\
@@ -1190,7 +1234,22 @@
%{mmcu=m3000s:crtm3000s.o%s} \
%{mmcu=m3001b:crtm3001b.o%s} \
%{mmcu=atmega2560|mmcu=avr6:crtm2560.o%s} \
-%{mmcu=atmega2561:crtm2561.o%s}"
+%{mmcu=atmega2561:crtm2561.o%s} \
+%{mmcu=avrxmega2|mmcu=atxmega32d4:crtx32d4.o%s} \
+%{mmcu=atxmega16a4:crtx16a4.o%s} \
+%{mmcu=atxmega16d4:crtx16d4.o%s} \
+%{mmcu=atxmega3|mmcu=atxmega32a4:crtx32a4.o%s} \
+%{mmcu=atxmega4|mmcu=atxmega64a3:crtx64a3.o%s} \
+%{mmcu=atxmega64d3:crtx64d3.o%s} \
+%{mmcu=atxmega5|mmcu=atxmega64a1:crtx64a1.o%s} \
+%{mmcu=atxmega6|mmcu=atxmega128a3:crtx128a3.o%s} \
+%{mmcu=atxmega128d3:crtx128d3.o%s}\
+%{mmcu=atxmega192a3:crtx192a3.o%s}\
+%{mmcu=atxmega192d3:crtx192d3.o%s}\
+%{mmcu=atxmega256a3:crtx256a3.o%s} \
+%{mmcu=atxmega256a3b:crtx256a3b.o%s} \
+%{mmcu=atxmega256d3:crtx256d3.o%s} \
+%{mmcu=atxmega7|mmcu=atxmega128a1:crtx128a1.o%s}"
#define EXTRA_SPECS {"crt_binutils", CRT_BINUTILS_SPECS},
@@ -1252,8 +1311,12 @@
/* 'true' - if current function is a signal function
as specified by the "signal" attribute. */
int is_signal;
-
+
/* 'true' - if current function is a signal function
+ as specified by the "nmi" attribute. */
+ int is_nmi;
+
+ /* 'true' - if current function is a task function
as specified by the "OS_task" attribute. */
int is_OS_task;
};
--- ./gcc/config/avr/t-avr.orig 2010-03-08 12:55:09.000000000 +0100
+++ ./gcc/config/avr/t-avr 2010-03-08 12:55:36.000000000 +0100
@@ -37,8 +37,8 @@
FPBIT = fp-bit.c
-MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6
-MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6
+MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega3/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7
+MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7
# The many avr2 matches are not listed here - this is the default.
MULTILIB_MATCHES = \
@@ -182,7 +182,22 @@
mmcu?avr51=mmcu?m3000s \
mmcu?avr51=mmcu?m3001b \
mmcu?avr6=mmcu?atmega2560 \
- mmcu?avr6=mmcu?atmega2561
+ mmcu?avr6=mmcu?atmega2561 \
+ mmcu?avrxmega2=mmcu?atxmega16a4 \
+ mmcu?avrxmega2=mmcu?atxmega16d4 \
+ mmcu?avrxmega2=mmcu?atxmega32d4 \
+ mmcu?avrxmega3=mmcu?atxmega32a4 \
+ mmcu?avrxmega4=mmcu?atxmega64a3 \
+ mmcu?avrxmega4=mmcu?atxmega64d3 \
+ mmcu?avrxmega5=mmcu?atxmega64a1 \
+ mmcu?avrxmega6=mmcu?atxmega128a3 \
+ mmcu?avrxmega6=mmcu?atxmega128d3 \
+ mmcu?avrxmega6=mmcu?atxmega192a3 \
+ mmcu?avrxmega6=mmcu?atxmega192d3 \
+ mmcu?avrxmega6=mmcu?atxmega256a3 \
+ mmcu?avrxmega6=mmcu?atxmega256a3b \
+ mmcu?avrxmega6=mmcu?atxmega256d3 \
+ mmcu?avrxmega7=mmcu?atxmega128a1
MULTILIB_EXCEPTIONS =
LIBGCC = stmp-multilib
--- ./gcc/config/avr/avr.md.orig 2010-03-08 12:54:57.000000000 +0100
+++ ./gcc/config/avr/avr.md 2010-03-08 12:55:36.000000000 +0100
@@ -47,9 +47,6 @@
(TMP_REGNO 0) ; temporary register r0
(ZERO_REGNO 1) ; zero register r1
- (SREG_ADDR 0x5F)
- (RAMPZ_ADDR 0x5B)
-
(UNSPEC_STRLEN 0)
(UNSPEC_INDEX_JMP 1)
(UNSPEC_SWAP 2)
@@ -2677,7 +2674,8 @@
"(optimize > 0)"
{
operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
- return AS2 (cbi,%0-0x20,%2);
+ operands[3] = GEN_INT(AVR_IO_OFFSET);
+ return AS2 (cbi,%0-%3,%2);
}
[(set_attr "length" "1")
(set_attr "cc" "none")])
@@ -2689,7 +2687,8 @@
"(optimize > 0)"
{
operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
- return AS2 (sbi,%0-0x20,%2);
+ operands[3] = GEN_INT(AVR_IO_OFFSET);
+ return AS2 (sbi,%0-%3,%2);
}
[(set_attr "length" "1")
(set_attr "cc" "none")])
--- ./gcc/config/avr/predicates.md.orig 2010-03-08 12:54:57.000000000 +0100
+++ ./gcc/config/avr/predicates.md 2010-03-08 12:55:36.000000000 +0100
@@ -50,12 +50,16 @@
;; Return true if OP is a valid address for lower half of I/O space.
(define_predicate "low_io_address_operand"
(and (match_code "const_int")
- (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)")))
+ (if_then_else (match_test "AVR_XMEGA")
+ (match_test "IN_RANGE((INTVAL (op)), 0x00, 0x1F)")
+ (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)"))))
;; Return true if OP is a valid address for high half of I/O space.
(define_predicate "high_io_address_operand"
(and (match_code "const_int")
- (match_test "IN_RANGE((INTVAL (op)), 0x40, 0x5F)")))
+ (if_then_else (match_test "AVR_XMEGA")
+ (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)")
+ (match_test "IN_RANGE((INTVAL (op)), 0x40, 0x5F)"))))
;; Return 1 if OP is the zero constant for MODE.
(define_predicate "const0_operand"