ports/devel/avr-gcc-devel/files/patch-xmega
Joerg Wunsch c25da1631f This is a "sneak preview" port of GCC 4.3.1 for the Atmel AVR
microcontrollers.  It includes patches from the WinAVR project to
support the ATmega32C1, ATmega32M1, ATmega32U4, and ATtiny167
controllers, and in particular the next generation AVRs ATxmega64A1
and ATxmega128A1.

The port has been carefully crafted to peacefully coexist with the
non-devel avr-gcc port.  All executables installed have the suffix
"-43" added for that reason.
2008-07-28 21:25:39 +00:00

733 lines
26 KiB
Text

--- gcc/config/avr/avr.c.orig 2008-06-08 10:24:28.171355800 -0600
+++ gcc/config/avr/avr.c 2008-06-08 10:29:42.276013800 -0600
@@ -51,6 +51,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);
@@ -118,17 +119,24 @@ int avr_asm_only_p = 0;
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
@@ -146,7 +154,14 @@ enum avr_arch
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 {
@@ -279,6 +294,18 @@ static const struct mcu_type_s avr_mcu_t
{ "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. */
+ /* Xmega, > 8K, <= 64K FLASH, > 64K RAM. */
+ /* Xmega, > 64K, <= 128K FLASH, <= 64K RAM. */
+ /* Xmega, > 64K, <= 128K FLASH, > 64K RAM. */
+ { "avrxmega5", ARCH_AVRXMEGA5, NULL },
+ { "atxmega64a1", ARCH_AVRXMEGA5, "__AVR_ATxmega64A1__" },
+ /* Xmega, > 128K, <= 256K FLASH, <= 64K RAM. */
+ /* 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__" },
@@ -452,6 +479,21 @@ signal_function_p (tree func)
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
@@ -611,6 +653,7 @@ expand_prologue (void)
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. */
@@ -646,7 +689,7 @@ expand_prologue (void)
/* 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;
@@ -656,7 +699,7 @@ expand_prologue (void)
&& (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;
@@ -929,14 +972,14 @@ expand_epilogue (void)
&& (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 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. */
@@ -1705,8 +1748,9 @@ output_movhi (rtx insn, rtx operands[],
}
/* 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)))
{
@@ -1715,7 +1759,8 @@ output_movhi (rtx insn, rtx operands[],
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))
{
@@ -1725,12 +1770,25 @@ output_movhi (rtx insn, rtx operands[],
"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 = 6;
+ return (AS2 (mov,__tmp_reg__,r24) CR_TAB
+ AS2 (ldi,r24,0xD8) CR_TAB
+ AS2 (out,__CCP__,r24) CR_TAB
+ AS2 (out,__SP_H__,%B1) CR_TAB
+ AS2 (out,__SP_L__,%A1) CR_TAB
+ AS2 (mov,r24,__tmp_reg__));
+ }
+ 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))
{
@@ -1865,7 +1923,7 @@ out_movqi_r_mr (rtx insn, rtx op[], int
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__);
@@ -1873,7 +1931,8 @@ out_movqi_r_mr (rtx insn, rtx op[], int
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);
@@ -2061,8 +2120,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int
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
@@ -2553,7 +2613,7 @@ out_movqi_mr_r (rtx insn, rtx op[], int
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);
@@ -2561,7 +2621,8 @@ out_movqi_mr_r (rtx insn, rtx op[], int
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);
@@ -2640,11 +2701,20 @@ out_movhi_mr_r (rtx insn, rtx op[], int
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,%B1) CR_TAB
+ AS2 (out,%B0-%2,%A1));
+ 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)
{
@@ -2659,11 +2729,20 @@ out_movhi_mr_r (rtx insn, rtx op[], int
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
{
@@ -2671,14 +2750,27 @@ out_movhi_mr_r (rtx insn, rtx op[], int
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)
{
@@ -2689,48 +2781,104 @@ out_movhi_mr_r (rtx insn, rtx op[], int
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)
{
@@ -2751,7 +2899,7 @@ out_movhi_mr_r (rtx insn, rtx op[], int
*l = 2;
return (AS2 (st,%0,%A1) CR_TAB
- AS2 (st,%0,%B1));
+ AS2 (st,%0,%B1));
}
fatal_insn ("unknown move insn:",insn);
return "";
@@ -4631,6 +4779,7 @@ const struct attribute_spec avr_attribut
{ "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 }
@@ -4719,6 +4868,14 @@ avr_handle_fndecl_attribute (tree *node,
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;
@@ -4844,7 +5001,8 @@ avr_file_start (void)
/* 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);
@@ -5708,15 +5866,18 @@ avr_hard_regno_mode_ok (int regno, enum
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 *
@@ -5877,16 +6038,17 @@ avr_out_sbxx_branch (rtx insn, rtx opera
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 2008-06-08 10:24:28.186941800 -0600
+++ gcc/config/avr/avr.h 2008-06-08 10:28:40.274905800 -0600
@@ -44,8 +44,11 @@ struct base_arch_s {
/* 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 @@ extern const struct base_arch_s *avr_cur
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 @@ extern const struct base_arch_s *avr_cur
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,15 @@ extern GTY(()) section *progmem_section;
#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_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_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 ()
@@ -849,6 +875,8 @@ mmcu=*:-mmcu=%*}"
mmcu=at90usb128*|\
mmcu=at94k: -m avr5}\
%{mmcu=atmega256*:-m avr6}\
+%{mmcu=atxmega64a1:-m avrxmega5} \
+%{mmcu=atxmega128a1:-m avrxmega7} \
%{mmcu=atmega324*|\
mmcu=atmega325*|\
mmcu=atmega328p|\
@@ -994,7 +1022,9 @@ mmcu=*:-mmcu=%*}"
%{mmcu=atmega2561:crtm2561.o%s} \
%{mmcu=at90can128:crtcan128.o%s} \
%{mmcu=at90usb1286:crtusb1286.o%s} \
-%{mmcu=at90usb1287:crtusb1287.o%s}"
+%{mmcu=at90usb1287:crtusb1287.o%s} \
+%{mmcu=atxmega5|mmcu=atxmega64a1:crtx64a1.o%s} \
+%{mmcu=atxmega7|mmcu=atxmega128a1:crtx128a1.o%s}"
#define EXTRA_SPECS {"crt_binutils", CRT_BINUTILS_SPECS},
@@ -1050,8 +1080,12 @@ struct machine_function GTY(())
/* '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/avr.md.orig 2008-06-08 10:24:28.171355800 -0600
+++ gcc/config/avr/avr.md 2008-06-08 10:29:58.610141800 -0600
@@ -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_SEI 2)
@@ -2681,7 +2678,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")])
@@ -2693,7 +2691,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")])
Index: gcc/config/avr/predicates.md
===================================================================
--- gcc/config/avr/predicates.md (revision 132445)
+++ gcc/config/avr/predicates.md (working copy)
@@ -45,12 +45,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"
--- gcc/config/avr/t-avr.orig 2008-02-19 17:25:31.546827500 -0700
+++ gcc/config/avr/t-avr 2008-02-20 09:22:51.709554900 -0700
@@ -37,8 +37,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c $(sr
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=avrxmega5/mmcu=avrxmega7
+MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega5 avrxmega7
# The many avr2 matches are not listed here - this is the default.
MULTILIB_MATCHES = \
@@ -125,7 +125,9 @@ MULTILIB_MATCHES = \
mmcu?avr51=mmcu?at90usb1286 \
mmcu?avr51=mmcu?at90usb1287 \
mmcu?avr6=mmcu?atmega2560 \
- mmcu?avr6=mmcu?atmega2561
+ mmcu?avr6=mmcu?atmega2561 \
+ mmcu?avrxmega5=mmcu?atxmega64a1 \
+ mmcu?avrxmega7=mmcu?atxmega128a1
MULTILIB_EXCEPTIONS =