You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
734 lines
26 KiB
Diff
734 lines
26 KiB
Diff
15 years ago
|
--- 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 =
|
||
|
|