Add rudimentary support for atomics on RX.
Add rudimentary support for atomics on RX. It is implemented by flipping interrupts off/on around the atomic sequences. gcc/ * config/rx/rx-protos.h (is_interrupt_func, is_fast_interrupt_func): Forward declare. (rx_atomic_sequence): New class. * config/rx/rx.c (rx_print_operand): Use symbolic names for PSW bits. (is_interrupt_func, is_fast_interrupt_func): Make non-static and non-inline. (rx_atomic_sequence::rx_atomic_sequence, rx_atomic_sequence::~rx_atomic_sequence): New functions. * config/rx/rx.md (CTRLREG_PSW, CTRLREG_USP, CTRLREG_FPSW, CTRLREG_CPEN, CTRLREG_BPSW, CTRLREG_BPC, CTRLREG_ISP, CTRLREG_FINTV, CTRLREG_INTB): New constants. (FETCHOP): New code iterator. (fethcop_name, fetchop_name2): New iterator code attributes. (QIHI): New mode iterator. (atomic_exchange<mode>, atomic_exchangesi, xchg_mem<mode>, atomic_fetch_<fetchop_name>si, atomic_fetch_nandsi, atomic_<fetchop_name>_fetchsi, atomic_nand_fetchsi): New patterns. From-SVN: r236075
This commit is contained in:
parent
6f0800d418
commit
927d22fa01
4 changed files with 217 additions and 12 deletions
|
@ -1,3 +1,23 @@
|
|||
2016-05-10 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
* config/rx/rx-protos.h (is_interrupt_func, is_fast_interrupt_func):
|
||||
Forward declare.
|
||||
(rx_atomic_sequence): New class.
|
||||
* config/rx/rx.c (rx_print_operand): Use symbolic names for PSW bits.
|
||||
(is_interrupt_func, is_fast_interrupt_func): Make non-static and
|
||||
non-inline.
|
||||
(rx_atomic_sequence::rx_atomic_sequence,
|
||||
rx_atomic_sequence::~rx_atomic_sequence): New functions.
|
||||
* config/rx/rx.md (CTRLREG_PSW, CTRLREG_USP, CTRLREG_FPSW, CTRLREG_CPEN,
|
||||
CTRLREG_BPSW, CTRLREG_BPC, CTRLREG_ISP, CTRLREG_FINTV,
|
||||
CTRLREG_INTB): New constants.
|
||||
(FETCHOP): New code iterator.
|
||||
(fethcop_name, fetchop_name2): New iterator code attributes.
|
||||
(QIHI): New mode iterator.
|
||||
(atomic_exchange<mode>, atomic_exchangesi, xchg_mem<mode>,
|
||||
atomic_fetch_<fetchop_name>si, atomic_fetch_nandsi,
|
||||
atomic_<fetchop_name>_fetchsi, atomic_nand_fetchsi): New patterns.
|
||||
|
||||
2016-05-10 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* tree-inline.c (remap_dependence_clique): Do not remap
|
||||
|
|
|
@ -26,6 +26,28 @@ extern void rx_expand_epilogue (bool);
|
|||
extern void rx_expand_prologue (void);
|
||||
extern int rx_initial_elimination_offset (int, int);
|
||||
|
||||
bool is_interrupt_func (const_tree decl);
|
||||
bool is_fast_interrupt_func (const_tree decl);
|
||||
|
||||
/* rx_atomic_sequence is used to emit the header and footer
|
||||
of an atomic sequence. It's supposed to be used in a scope.
|
||||
When constructed, it will emit the atomic sequence header insns.
|
||||
When destructred (goes out of scope), it will emit the
|
||||
corresponding atomic sequence footer insns. */
|
||||
class rx_atomic_sequence
|
||||
{
|
||||
public:
|
||||
rx_atomic_sequence (const_tree fun_decl);
|
||||
~rx_atomic_sequence (void);
|
||||
|
||||
private:
|
||||
rx_atomic_sequence (void);
|
||||
rx_atomic_sequence (const rx_atomic_sequence&);
|
||||
rx_atomic_sequence& operator = (const rx_atomic_sequence&);
|
||||
|
||||
rtx m_prev_psw_reg;
|
||||
};
|
||||
|
||||
#ifdef RTX_CODE
|
||||
extern int rx_adjust_insn_length (rtx_insn *, int);
|
||||
extern int rx_align_for_label (rtx, int);
|
||||
|
|
|
@ -630,15 +630,15 @@ rx_print_operand (FILE * file, rtx op, int letter)
|
|||
gcc_assert (CONST_INT_P (op));
|
||||
switch (INTVAL (op))
|
||||
{
|
||||
case 0: fprintf (file, "psw"); break;
|
||||
case 2: fprintf (file, "usp"); break;
|
||||
case 3: fprintf (file, "fpsw"); break;
|
||||
case 4: fprintf (file, "cpen"); break;
|
||||
case 8: fprintf (file, "bpsw"); break;
|
||||
case 9: fprintf (file, "bpc"); break;
|
||||
case 0xa: fprintf (file, "isp"); break;
|
||||
case 0xb: fprintf (file, "fintv"); break;
|
||||
case 0xc: fprintf (file, "intb"); break;
|
||||
case CTRLREG_PSW: fprintf (file, "psw"); break;
|
||||
case CTRLREG_USP: fprintf (file, "usp"); break;
|
||||
case CTRLREG_FPSW: fprintf (file, "fpsw"); break;
|
||||
case CTRLREG_CPEN: fprintf (file, "cpen"); break;
|
||||
case CTRLREG_BPSW: fprintf (file, "bpsw"); break;
|
||||
case CTRLREG_BPC: fprintf (file, "bpc"); break;
|
||||
case CTRLREG_ISP: fprintf (file, "isp"); break;
|
||||
case CTRLREG_FINTV: fprintf (file, "fintv"); break;
|
||||
case CTRLREG_INTB: fprintf (file, "intb"); break;
|
||||
default:
|
||||
warning (0, "unrecognized control register number: %d - using 'psw'",
|
||||
(int) INTVAL (op));
|
||||
|
@ -1216,7 +1216,7 @@ has_func_attr (const_tree decl, const char * func_attr)
|
|||
|
||||
/* Returns true if the provided function has the "fast_interrupt" attribute. */
|
||||
|
||||
static inline bool
|
||||
bool
|
||||
is_fast_interrupt_func (const_tree decl)
|
||||
{
|
||||
return has_func_attr (decl, "fast_interrupt");
|
||||
|
@ -1224,7 +1224,7 @@ is_fast_interrupt_func (const_tree decl)
|
|||
|
||||
/* Returns true if the provided function has the "interrupt" attribute. */
|
||||
|
||||
static inline bool
|
||||
bool
|
||||
is_interrupt_func (const_tree decl)
|
||||
{
|
||||
return has_func_attr (decl, "interrupt");
|
||||
|
@ -3409,6 +3409,29 @@ rx_enable_lra (void)
|
|||
return TARGET_ENABLE_LRA;
|
||||
}
|
||||
|
||||
rx_atomic_sequence::rx_atomic_sequence (const_tree fun_decl)
|
||||
{
|
||||
if (is_fast_interrupt_func (fun_decl) || is_interrupt_func (fun_decl))
|
||||
{
|
||||
/* If we are inside an interrupt handler, assume that interrupts are
|
||||
off -- which is the default hardware behavior. In this case, there
|
||||
is no need to disable the interrupts. */
|
||||
m_prev_psw_reg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prev_psw_reg = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_mvfc (m_prev_psw_reg, GEN_INT (CTRLREG_PSW)));
|
||||
emit_insn (gen_clrpsw (GEN_INT ('I')));
|
||||
}
|
||||
}
|
||||
|
||||
rx_atomic_sequence::~rx_atomic_sequence (void)
|
||||
{
|
||||
if (m_prev_psw_reg != NULL)
|
||||
emit_insn (gen_mvtc (GEN_INT (CTRLREG_PSW), m_prev_psw_reg));
|
||||
}
|
||||
|
||||
|
||||
#undef TARGET_NARROW_VOLATILE_BITFIELD
|
||||
#define TARGET_NARROW_VOLATILE_BITFIELD rx_narrow_volatile_bitfield
|
||||
|
|
|
@ -75,6 +75,16 @@
|
|||
(UNSPEC_BUILTIN_WAIT 51)
|
||||
|
||||
(UNSPEC_PID_ADDR 52)
|
||||
|
||||
(CTRLREG_PSW 0)
|
||||
(CTRLREG_USP 2)
|
||||
(CTRLREG_FPSW 3)
|
||||
(CTRLREG_CPEN 4)
|
||||
(CTRLREG_BPSW 8)
|
||||
(CTRLREG_BPC 9)
|
||||
(CTRLREG_ISP 10)
|
||||
(CTRLREG_FINTV 11)
|
||||
(CTRLREG_INTB 12)
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -2145,7 +2155,17 @@
|
|||
FAIL;
|
||||
})
|
||||
|
||||
;; Atomic exchange operation.
|
||||
;; Atomic operations.
|
||||
|
||||
(define_code_iterator FETCHOP [plus minus ior xor and])
|
||||
|
||||
(define_code_attr fetchop_name
|
||||
[(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
|
||||
|
||||
(define_code_attr fetchop_name2
|
||||
[(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
|
||||
|
||||
(define_mode_iterator QIHI [QI HI])
|
||||
|
||||
(define_insn "sync_lock_test_and_setsi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
|
@ -2157,6 +2177,126 @@
|
|||
[(set_attr "length" "3,6")
|
||||
(set_attr "timings" "22")]
|
||||
)
|
||||
|
||||
(define_expand "atomic_exchange<mode>"
|
||||
[(match_operand:QIHI 0 "register_operand") ;; oldval output
|
||||
(match_operand:QIHI 1 "rx_restricted_mem_operand") ;; memory
|
||||
(match_operand:QIHI 2 "register_operand") ;; newval input
|
||||
(match_operand:QIHI 3 "const_int_operand")] ;; memory model
|
||||
""
|
||||
{
|
||||
emit_insn (gen_xchg_mem<mode> (operands[0], operands[1], operands[2]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_exchangesi"
|
||||
[(match_operand:SI 0 "register_operand") ;; oldval output
|
||||
(match_operand:SI 1 "rx_restricted_mem_operand") ;; memory
|
||||
(match_operand:SI 2 "register_operand") ;; newval input
|
||||
(match_operand:SI 3 "const_int_operand")] ;; memory model
|
||||
""
|
||||
{
|
||||
emit_insn (gen_sync_lock_test_and_setsi (operands[0], operands[1],
|
||||
operands[2]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "xchg_mem<mode>"
|
||||
[(set (match_operand:QIHI 0 "register_operand" "=r")
|
||||
(match_operand:QIHI 1 "rx_compare_operand" "=Q"))
|
||||
(set (match_dup 1)
|
||||
(match_operand:QIHI 2 "register_operand" "0"))]
|
||||
""
|
||||
"xchg\t%1, %0"
|
||||
[(set_attr "length" "6")
|
||||
(set_attr "timings" "22")]
|
||||
)
|
||||
|
||||
;; read - modify - write - return old value
|
||||
(define_expand "atomic_fetch_<fetchop_name>si"
|
||||
[(set (match_operand:SI 0 "register_operand")
|
||||
(match_operand:SI 1 "memory_operand"))
|
||||
(set (match_dup 1)
|
||||
(FETCHOP:SI (match_dup 1) (match_operand:SI 2 "rx_source_operand")))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; memory model
|
||||
""
|
||||
{
|
||||
{
|
||||
rx_atomic_sequence seq (current_function_decl);
|
||||
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
|
||||
rtx tmp = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_<fetchop_name2>si3 (tmp, operands[0], operands[2]));
|
||||
|
||||
emit_move_insn (operands[1], tmp);
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_fetch_nandsi"
|
||||
[(set (match_operand:SI 0 "register_operand")
|
||||
(match_operand:SI 1 "memory_operand"))
|
||||
(set (match_dup 1)
|
||||
(not:SI (and:SI (match_dup 1)
|
||||
(match_operand:SI 2 "rx_source_operand"))))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; memory model
|
||||
""
|
||||
{
|
||||
{
|
||||
rx_atomic_sequence seq (current_function_decl);
|
||||
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
|
||||
rtx tmp = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_andsi3 (tmp, operands[0], operands[2]));
|
||||
emit_insn (gen_one_cmplsi2 (tmp, tmp));
|
||||
|
||||
emit_move_insn (operands[1], tmp);
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; read - modify - write - return new value
|
||||
(define_expand "atomic_<fetchop_name>_fetchsi"
|
||||
[(set (match_operand:SI 0 "register_operand")
|
||||
(FETCHOP:SI (match_operand:SI 1 "rx_restricted_mem_operand")
|
||||
(match_operand:SI 2 "register_operand")))
|
||||
(set (match_dup 1)
|
||||
(FETCHOP:SI (match_dup 1) (match_dup 2)))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; memory model
|
||||
""
|
||||
{
|
||||
{
|
||||
rx_atomic_sequence seq (current_function_decl);
|
||||
|
||||
emit_move_insn (operands[0], operands[2]);
|
||||
emit_insn (gen_<fetchop_name2>si3 (operands[0], operands[0], operands[1]));
|
||||
emit_move_insn (operands[1], operands[0]);
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_nand_fetchsi"
|
||||
[(set (match_operand:SI 0 "register_operand")
|
||||
(not:SI (and:SI (match_operand:SI 1 "rx_restricted_mem_operand")
|
||||
(match_operand:SI 2 "register_operand"))))
|
||||
(set (match_dup 1)
|
||||
(not:SI (and:SI (match_dup 1) (match_dup 2))))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; memory model
|
||||
""
|
||||
{
|
||||
{
|
||||
rx_atomic_sequence seq (current_function_decl);
|
||||
|
||||
emit_move_insn (operands[0], operands[2]);
|
||||
emit_insn (gen_andsi3 (operands[0], operands[0], operands[1]));
|
||||
emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
|
||||
emit_move_insn (operands[1], operands[0]);
|
||||
}
|
||||
DONE;
|
||||
});
|
||||
|
||||
|
||||
;; Block move functions.
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue