Commit d713426e by Georg-Johann Lay Committed by Georg-Johann Lay

re PR target/65192 ([avr-tiny] ICE in tiny_valid_direct_memory_access_range)

	PR target/65192
	* config/avr/avr-protos.h (tiny_valid_direct_memory_access_range):
	Remove.
	* config/avr/avr.c: Same.
	(avr_legitimate_address_p) <AVR_TINY, CONSTANT_ADDRESS_P>:
	Refuse any constant address not in 0..0xbf.
	* config/avr/avr.md (*mov<mode>, *movsf): Remove
	tiny_valid_direct_memory_access_range from insn conditions.
	(mov<mode>): Don't special-case expansion of avrtiny addresses.

From-SVN: r221029
parent 7064d91e
2015-02-26 Georg-Johann Lay <avr@gjlay.de>
PR target/65192
* config/avr/avr-protos.h (tiny_valid_direct_memory_access_range):
Remove.
* config/avr/avr.c: Same.
(avr_legitimate_address_p) <AVR_TINY, CONSTANT_ADDRESS_P>:
Refuse any constant address not in 0..0xbf.
* config/avr/avr.md (*mov<mode>, *movsf): Remove
tiny_valid_direct_memory_access_range from insn conditions.
(mov<mode>): Don't special-case expansion of avrtiny addresses.
2015-02-26 Oleg Endo <olegendo@gcc.gnu.org>
PR target/61142
......
......@@ -46,7 +46,6 @@ extern void avr_init_cumulative_args (CUMULATIVE_ARGS*, tree, rtx, tree);
#ifdef RTX_CODE
extern int avr_hard_regno_call_part_clobbered (unsigned, machine_mode);
extern bool tiny_valid_direct_memory_access_range(rtx, machine_mode);
extern const char *output_movqi (rtx_insn *insn, rtx operands[], int *l);
extern const char *output_movhi (rtx_insn *insn, rtx operands[], int *l);
extern const char *output_movsisf (rtx_insn *insn, rtx operands[], int *l);
......
......@@ -1823,6 +1823,16 @@ avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
break;
}
if (AVR_TINY
&& CONSTANT_ADDRESS_P (x))
{
/* avrtiny's load / store instructions only cover addresses 0..0xbf:
IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
ok = (CONST_INT_P (x)
&& IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)));
}
if (avr_log.legitimate_address_p)
{
avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
......@@ -3210,37 +3220,6 @@ avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
}
/* AVRTC-579
If OP is a symbol or a constant expression with value > 0xbf
return FALSE, otherwise TRUE.
This check is used to avoid LDS / STS instruction with invalid memory
access range (valid range 0x40..0xbf). For I/O operand range 0x0..0x3f,
IN / OUT instruction will be generated. */
bool
tiny_valid_direct_memory_access_range (rtx op, machine_mode mode)
{
rtx x;
if (!AVR_TINY)
return true;
x = XEXP (op,0);
if (MEM_P (op) && x && GET_CODE (x) == SYMBOL_REF)
{
return false;
}
if (MEM_P (op) && x && (CONSTANT_ADDRESS_P (x))
&& !(IN_RANGE (INTVAL (x), 0, 0xC0 - GET_MODE_SIZE (mode))))
{
return false;
}
return true;
}
const char*
output_movqi (rtx_insn *insn, rtx operands[], int *plen)
{
......
......@@ -671,32 +671,6 @@
emit_insn (gen_load<mode>_libgcc (dest, src));
DONE;
}
// AVRTC-579
// If the source operand expression is out of range for LDS instruction
// copy source operand expression to register.
// For tiny core, LDS instruction's memory access range limited to 0x40..0xbf.
if (!tiny_valid_direct_memory_access_range (src, <MODE>mode))
{
rtx srcx = XEXP (src, 0);
operands[1] = src = replace_equiv_address (src, copy_to_mode_reg (GET_MODE (srcx), srcx));
emit_move_insn (dest, src);
DONE;
}
// AVRTC-579
// If the destination operand expression is out of range for STS instruction
// copy destination operand expression to register.
// For tiny core, STS instruction's memory access range limited to 0x40..0xbf.
if (!tiny_valid_direct_memory_access_range (dest, <MODE>mode))
{
rtx destx = XEXP (dest, 0);
operands[0] = dest = replace_equiv_address (dest, copy_to_mode_reg (GET_MODE (destx), destx));
emit_move_insn (dest, src);
DONE;
}
})
;;========================================================================
......@@ -713,13 +687,8 @@
(define_insn "mov<mode>_insn"
[(set (match_operand:ALL1 0 "nonimmediate_operand" "=r ,d ,Qm ,r ,q,r,*r")
(match_operand:ALL1 1 "nox_general_operand" "r Y00,n Ynn,r Y00,Qm,r,q,i"))]
"(register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))
/* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
though access range is checked during define_expand, it is required
here to avoid merging RTXes during combine pass. */
&& tiny_valid_direct_memory_access_range (operands[0], QImode)
&& tiny_valid_direct_memory_access_range (operands[1], QImode)"
"register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode)"
{
return output_movqi (insn, operands, NULL);
}
......@@ -812,13 +781,8 @@
(define_insn "*mov<mode>"
[(set (match_operand:ALL2 0 "nonimmediate_operand" "=r,r ,r,m ,d,*r,q,r")
(match_operand:ALL2 1 "nox_general_operand" "r,Y00,m,r Y00,i,i ,r,q"))]
"(register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))
/* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
though access range is checked during define_expand, it is required
here to avoid merging RTXes during combine pass. */
&& tiny_valid_direct_memory_access_range (operands[0], HImode)
&& tiny_valid_direct_memory_access_range (operands[1], HImode)"
"register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode)"
{
return output_movhi (insn, operands, NULL);
}
......@@ -966,13 +930,8 @@
(define_insn "*mov<mode>"
[(set (match_operand:ALL4 0 "nonimmediate_operand" "=r,r ,r ,Qm ,!d,r")
(match_operand:ALL4 1 "nox_general_operand" "r,Y00,Qm,r Y00,i ,i"))]
"(register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))
/* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
though access range is checked during define_expand, it is required
here to avoid merging RTXes during combine pass. */
&& tiny_valid_direct_memory_access_range (operands[0], SImode)
&& tiny_valid_direct_memory_access_range (operands[1], SImode)"
"register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode)"
{
return output_movsisf (insn, operands, NULL);
}
......@@ -986,13 +945,8 @@
(define_insn "*movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
(match_operand:SF 1 "nox_general_operand" "r,G,Qm,rG,F ,F"))]
"(register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode))
/* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
though access range is checked during define_expand, it is required
here to avoid merging rtls during combine pass. */
&& tiny_valid_direct_memory_access_range (operands[0], SFmode)
&& tiny_valid_direct_memory_access_range (operands[1], SFmode)"
"register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode)"
{
return output_movsisf (insn, operands, NULL);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment