mirror of git://gcc.gnu.org/git/gcc.git
AVR: target 113927 - Simple code triggers stack frame for Reduced Tiny.
The -mmcu=avrtiny cores have no ADIW and SBIW instructions. This was implemented by clearing all regs out of regclass ADDW_REGS so that constraint "w" never matched. This corrupted the subset relations of the register classes as they appear in enum reg_class. This patch keeps ADDW_REGS like for all other cores, i.e. it contains R24...R31. Instead of tests like test_hard_reg_class (ADDW_REGS, *) the code now uses avr_adiw_reg_p (*). And all insns with constraint "w" get "isa" insn attribute value of "adiw". Plus, a new built-in macro __AVR_HAVE_ADIW__ is provided, which is more specific than __AVR_TINY__. gcc/ PR target/113927 * config/avr/avr.h (AVR_HAVE_ADIW): New macro. * config/avr/avr-protos.h (avr_adiw_reg_p): New proto. * config/avr/avr.cc (avr_adiw_reg_p): New function. (avr_conditional_register_usage) [AVR_TINY]: Don't clear ADDW_REGS. Replace test_hard_reg_class (ADDW_REGS, ...) with calls to * config/avr/avr.md: Same. (attr "isa") <tiny, no_tiny>: Remove. <adiw, no_adiw>: Add. (define_insn, define_insn_and_split): When an alternative has constraint "w", then set attribute "isa" to "adiw". * config/avr/avr-c.cc (avr_cpu_cpp_builtins) [AVR_HAVE_ADIW]: Built-in define __AVR_HAVE_ADIW__. * doc/invoke.texi (AVR Options): Document it.
This commit is contained in:
parent
84da9bca72
commit
5cff288c2d
|
@ -307,6 +307,7 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
|
|||
if (AVR_HAVE_ELPMX) cpp_define (pfile, "__AVR_HAVE_ELPMX__");
|
||||
if (AVR_HAVE_MOVW) cpp_define (pfile, "__AVR_HAVE_MOVW__");
|
||||
if (AVR_HAVE_LPMX) cpp_define (pfile, "__AVR_HAVE_LPMX__");
|
||||
if (AVR_HAVE_ADIW) cpp_define (pfile, "__AVR_HAVE_ADIW__");
|
||||
|
||||
if (avr_arch->asm_only)
|
||||
cpp_define (pfile, "__AVR_ASM_ONLY__");
|
||||
|
|
|
@ -123,6 +123,7 @@ extern enum reg_class avr_mode_code_base_reg_class (machine_mode, addr_space_t,
|
|||
extern bool avr_regno_mode_code_ok_for_base_p (int, machine_mode, addr_space_t, RTX_CODE, RTX_CODE);
|
||||
extern rtx avr_incoming_return_addr_rtx (void);
|
||||
extern rtx avr_legitimize_reload_address (rtx*, machine_mode, int, int, int, int, rtx (*)(rtx,int));
|
||||
extern bool avr_adiw_reg_p (rtx);
|
||||
extern bool avr_mem_flash_p (rtx);
|
||||
extern bool avr_mem_memx_p (rtx);
|
||||
extern bool avr_load_libgcc_p (rtx);
|
||||
|
|
|
@ -292,6 +292,17 @@ avr_to_int_mode (rtx x)
|
|||
: simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Return true if hard register REG supports the ADIW and SBIW instructions. */
|
||||
|
||||
bool
|
||||
avr_adiw_reg_p (rtx reg)
|
||||
{
|
||||
return (AVR_HAVE_ADIW
|
||||
&& test_hard_reg_class (ADDW_REGS, reg));
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
static const pass_data avr_pass_data_recompute_notes =
|
||||
|
@ -6272,7 +6283,7 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
|
|||
/* Word registers >= R24 can use SBIW/ADIW with 0..63. */
|
||||
|
||||
if (i == 0
|
||||
&& test_hard_reg_class (ADDW_REGS, reg8))
|
||||
&& avr_adiw_reg_p (reg8))
|
||||
{
|
||||
int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
|
||||
|
||||
|
@ -8186,7 +8197,7 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
|
|||
if (!started
|
||||
&& i % 2 == 0
|
||||
&& i + 2 <= n_bytes
|
||||
&& test_hard_reg_class (ADDW_REGS, reg8))
|
||||
&& avr_adiw_reg_p (reg8))
|
||||
{
|
||||
rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
|
||||
unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
|
||||
|
@ -8678,7 +8689,7 @@ avr_out_plus_set_ZN (rtx *xop, int *plen)
|
|||
}
|
||||
|
||||
if (n_bytes == 2
|
||||
&& test_hard_reg_class (ADDW_REGS, xreg)
|
||||
&& avr_adiw_reg_p (xreg)
|
||||
&& IN_RANGE (INTVAL (xval), 1, 63))
|
||||
{
|
||||
// Add 16-bit value in [1..63] to a w register.
|
||||
|
@ -8705,7 +8716,7 @@ avr_out_plus_set_ZN (rtx *xop, int *plen)
|
|||
|
||||
if (i == 0
|
||||
&& n_bytes >= 2
|
||||
&& test_hard_reg_class (ADDW_REGS, op[0]))
|
||||
&& avr_adiw_reg_p (op[0]))
|
||||
{
|
||||
op[1] = simplify_gen_subreg (HImode, xval, mode, 0);
|
||||
if (IN_RANGE (INTVAL (op[1]), 0, 63))
|
||||
|
@ -13312,7 +13323,6 @@ avr_conditional_register_usage (void)
|
|||
reg_alloc_order[i] = tiny_reg_alloc_order[i];
|
||||
}
|
||||
|
||||
CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
|
||||
CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
|
||||
}
|
||||
}
|
||||
|
@ -14043,7 +14053,7 @@ avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
|
|||
{
|
||||
addr_space_t as = (addr_space_t) INTVAL (op[0]);
|
||||
machine_mode loop_mode = GET_MODE (op[1]);
|
||||
bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
|
||||
bool sbiw_p = avr_adiw_reg_p (op[1]);
|
||||
rtx xop[3];
|
||||
|
||||
if (plen)
|
||||
|
|
|
@ -65,6 +65,7 @@ enum
|
|||
#define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call && ! AVR_SHORT_CALLS)
|
||||
#define AVR_HAVE_MUL (avr_arch->have_mul)
|
||||
#define AVR_HAVE_MOVW (avr_arch->have_movw_lpmx)
|
||||
#define AVR_HAVE_ADIW (!AVR_TINY)
|
||||
#define AVR_HAVE_LPM (!AVR_TINY)
|
||||
#define AVR_HAVE_LPMX (avr_arch->have_movw_lpmx)
|
||||
#define AVR_HAVE_ELPM (avr_arch->have_elpm)
|
||||
|
|
|
@ -176,10 +176,11 @@
|
|||
;; lpm : ISA has no LPMX lpmx : ISA has LPMX
|
||||
;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX
|
||||
;; no_xmega: non-XMEGA core xmega : XMEGA core
|
||||
;; no_tiny: non-TINY core tiny : TINY core
|
||||
;; no_adiw: ISA has no ADIW, SBIW adiw : ISA has ADIW, SBIW
|
||||
|
||||
(define_attr "isa"
|
||||
"mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega, no_tiny,tiny,
|
||||
"mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega,
|
||||
no_adiw,adiw,
|
||||
standard"
|
||||
(const_string "standard"))
|
||||
|
||||
|
@ -231,16 +232,16 @@
|
|||
(match_test "AVR_XMEGA"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "tiny")
|
||||
(match_test "AVR_TINY"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "no_xmega")
|
||||
(match_test "!AVR_XMEGA"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "no_tiny")
|
||||
(match_test "!AVR_TINY"))
|
||||
(and (eq_attr "isa" "adiw")
|
||||
(match_test "AVR_HAVE_ADIW"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "no_adiw")
|
||||
(match_test "!AVR_HAVE_ADIW"))
|
||||
(const_int 1)
|
||||
|
||||
] (const_int 0)))
|
||||
|
@ -1325,7 +1326,9 @@
|
|||
(use (match_dup 2))
|
||||
(clobber (match_dup 3))
|
||||
(clobber (match_dup 4))
|
||||
(clobber (reg:CC REG_CC))])])
|
||||
(clobber (reg:CC REG_CC))])]
|
||||
""
|
||||
[(set_attr "isa" "adiw,*")])
|
||||
|
||||
|
||||
(define_insn "*clrmemhi"
|
||||
|
@ -1340,7 +1343,8 @@
|
|||
"@
|
||||
0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
|
||||
0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
|
||||
[(set_attr "length" "3,4")])
|
||||
[(set_attr "length" "3,4")
|
||||
(set_attr "isa" "adiw,*")])
|
||||
|
||||
(define_expand "strlenhi"
|
||||
[(set (match_dup 4)
|
||||
|
@ -1627,7 +1631,9 @@
|
|||
[(parallel [(set (match_dup 0)
|
||||
(plus:ALL2 (match_dup 1)
|
||||
(match_dup 2)))
|
||||
(clobber (reg:CC REG_CC))])])
|
||||
(clobber (reg:CC REG_CC))])]
|
||||
""
|
||||
[(set_attr "isa" "*,*,adiw,*")])
|
||||
|
||||
(define_insn "*add<mode>3"
|
||||
[(set (match_operand:ALL2 0 "register_operand" "=??r,d,!w ,d")
|
||||
|
@ -1639,6 +1645,7 @@
|
|||
return avr_out_plus (insn, operands);
|
||||
}
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "isa" "*,*,adiw,*")
|
||||
(set_attr "adjust_len" "plus")])
|
||||
|
||||
;; Adding a constant to NO_LD_REGS might have lead to a reload of
|
||||
|
@ -2306,7 +2313,9 @@
|
|||
(const_int 0))
|
||||
(match_dup 2)))
|
||||
(clobber (match_dup 3))
|
||||
(clobber (reg:CC REG_CC))])])
|
||||
(clobber (reg:CC REG_CC))])]
|
||||
""
|
||||
[(set_attr "isa" "adiw,*")])
|
||||
|
||||
(define_insn "*addhi3.lt0"
|
||||
[(set (match_operand:HI 0 "register_operand" "=w,r")
|
||||
|
@ -2319,7 +2328,8 @@
|
|||
"@
|
||||
sbrc %1,7\;adiw %0,1
|
||||
lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__"
|
||||
[(set_attr "length" "2,3")])
|
||||
[(set_attr "length" "2,3")
|
||||
(set_attr "isa" "adiw,*")])
|
||||
|
||||
(define_insn_and_split "*addpsi3.lt0_split"
|
||||
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||
|
@ -6634,6 +6644,7 @@
|
|||
return avr_out_compare (insn, operands, NULL);
|
||||
}
|
||||
[(set_attr "length" "2,2,2,3,4,2,4")
|
||||
(set_attr "isa" "adiw,*,*,*,*,*,*")
|
||||
(set_attr "adjust_len" "tsthi,tsthi,*,*,*,compare,compare")])
|
||||
|
||||
(define_insn "*cmppsi"
|
||||
|
@ -7607,7 +7618,7 @@
|
|||
{
|
||||
const char *op;
|
||||
int jump_mode;
|
||||
if (test_hard_reg_class (ADDW_REGS, operands[0]))
|
||||
if (avr_adiw_reg_p (operands[0]))
|
||||
output_asm_insn ("sbiw %0,1" CR_TAB
|
||||
"sbc %C0,__zero_reg__" CR_TAB
|
||||
"sbc %D0,__zero_reg__", operands);
|
||||
|
@ -7650,7 +7661,7 @@
|
|||
{
|
||||
const char *op;
|
||||
int jump_mode;
|
||||
if (test_hard_reg_class (ADDW_REGS, operands[0]))
|
||||
if (avr_adiw_reg_p (operands[0]))
|
||||
output_asm_insn ("sbiw %0,1", operands);
|
||||
else
|
||||
output_asm_insn ("subi %A0,1" CR_TAB
|
||||
|
@ -7691,7 +7702,7 @@
|
|||
{
|
||||
const char *op;
|
||||
int jump_mode;
|
||||
if (test_hard_reg_class (ADDW_REGS, operands[0]))
|
||||
if (avr_adiw_reg_p (operands[0]))
|
||||
output_asm_insn ("sbiw %0,1", operands);
|
||||
else
|
||||
output_asm_insn ("subi %A0,1" CR_TAB
|
||||
|
@ -8065,7 +8076,7 @@
|
|||
(clobber (match_dup 2))
|
||||
(clobber (reg:CC REG_CC))])]
|
||||
""
|
||||
[(set_attr "isa" "no_tiny,tiny")])
|
||||
[(set_attr "isa" "adiw,no_adiw")])
|
||||
|
||||
(define_insn "*delay_cycles_2"
|
||||
[(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n,n")
|
||||
|
@ -8080,7 +8091,7 @@
|
|||
ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\n1: sbiw %A2,1\;brne 1b
|
||||
ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\n1: subi %A2,1\;sbci %B2,0\;brne 1b"
|
||||
[(set_attr "length" "4,5")
|
||||
(set_attr "isa" "no_tiny,tiny")])
|
||||
(set_attr "isa" "adiw,no_adiw")])
|
||||
|
||||
(define_insn_and_split "delay_cycles_3"
|
||||
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
|
||||
|
|
|
@ -24146,6 +24146,9 @@ If @var{device} is not a device but only a core architecture like
|
|||
@item __AVR_XMEGA__
|
||||
The device / architecture belongs to the XMEGA family of devices.
|
||||
|
||||
@item __AVR_HAVE_ADIW__
|
||||
The device has the @code{ADIW} and @code{SBIW} instructions.
|
||||
|
||||
@item __AVR_HAVE_ELPM__
|
||||
The device has the @code{ELPM} instruction.
|
||||
|
||||
|
@ -24153,14 +24156,14 @@ The device has the @code{ELPM} instruction.
|
|||
The device has the @code{ELPM R@var{n},Z} and @code{ELPM
|
||||
R@var{n},Z+} instructions.
|
||||
|
||||
@item __AVR_HAVE_MOVW__
|
||||
The device has the @code{MOVW} instruction to perform 16-bit
|
||||
register-register moves.
|
||||
|
||||
@item __AVR_HAVE_LPMX__
|
||||
The device has the @code{LPM R@var{n},Z} and
|
||||
@code{LPM R@var{n},Z+} instructions.
|
||||
|
||||
@item __AVR_HAVE_MOVW__
|
||||
The device has the @code{MOVW} instruction to perform 16-bit
|
||||
register-register moves.
|
||||
|
||||
@item __AVR_HAVE_MUL__
|
||||
The device has a hardware multiplier.
|
||||
|
||||
|
|
Loading…
Reference in New Issue