Commit b26fa4f9 by Kuan-Lin Chen Committed by Chung-Ju Wu

[NDS32] Support PIC and TLS.

gcc/
	* config/nds32/constants.md: Add TP_REGNUM constant.
	(unspec_element): Add UNSPEC_GOTINIT, UNSPEC_GOT, UNSPEC_GOTOFF,
	UNSPEC_PLT, UNSPEC_TLSGD, UNSPEC_TLSLD, UNSPEC_TLSIE, UNSPEC_TLSLE and
	UNSPEC_ADD32.
	* config/nds32/nds32-doubleword.md: Consider flag_pic.
	* config/nds32/nds32-dspext.md (mov<mode>): Expand TLS and PIC cases.
	* config/nds32/nds32-predicates.c (nds32_const_unspec_p): New.
	* config/nds32/nds32-md-auxiliary.c: Implementation that support TLS
	and PIC code generation.
	* config/nds32/nds32-protos.h: Declarations that support TLS and PIC
	code generation.
	* config/nds32/nds32-relax-opt.c: Consider TLS and PIC for relax
	optimization.
	* config/nds32/nds32.md: Support TLS and PIC.
	* config/nds32/nds32.c: Support TLS and PIC.
	* config/nds32/nds32.h (nds32_relax_insn_type): New enum type.
	* config/nds32/predicates.md (nds32_nonunspec_symbolic_operand): New
	predicate.

Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>

From-SVN: r260393
parent dc32bc72
2018-05-19 Kuan-Lin Chen <kuanlinchentw@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/constants.md: Add TP_REGNUM constant.
(unspec_element): Add UNSPEC_GOTINIT, UNSPEC_GOT, UNSPEC_GOTOFF,
UNSPEC_PLT, UNSPEC_TLSGD, UNSPEC_TLSLD, UNSPEC_TLSIE, UNSPEC_TLSLE and
UNSPEC_ADD32.
* config/nds32/nds32-doubleword.md: Consider flag_pic.
* config/nds32/nds32-dspext.md (mov<mode>): Expand TLS and PIC cases.
* config/nds32/nds32-predicates.c (nds32_const_unspec_p): New.
* config/nds32/nds32-md-auxiliary.c: Implementation that support TLS
and PIC code generation.
* config/nds32/nds32-protos.h: Declarations that support TLS and PIC
code generation.
* config/nds32/nds32-relax-opt.c: Consider TLS and PIC for relax
optimization.
* config/nds32/nds32.md: Support TLS and PIC.
* config/nds32/nds32.c: Support TLS and PIC.
* config/nds32/nds32.h (nds32_relax_insn_type): New enum type.
* config/nds32/predicates.md (nds32_nonunspec_symbolic_operand): New
predicate.
2018-05-19 Chung-Ju Wu <jasonwucj@gmail.com> 2018-05-19 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32-predicates.c (const_vector_to_hwint): Use machine * config/nds32/nds32-predicates.c (const_vector_to_hwint): Use machine
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
(define_constants (define_constants
[(R8_REGNUM 8) [(R8_REGNUM 8)
(TA_REGNUM 15) (TA_REGNUM 15)
(TP_REGNUM 25)
(FP_REGNUM 28) (FP_REGNUM 28)
(GP_REGNUM 29) (GP_REGNUM 29)
(LP_REGNUM 30) (LP_REGNUM 30)
...@@ -72,6 +73,14 @@ ...@@ -72,6 +73,14 @@
UNSPEC_UASTORE_HW UNSPEC_UASTORE_HW
UNSPEC_UASTORE_W UNSPEC_UASTORE_W
UNSPEC_UASTORE_DW UNSPEC_UASTORE_DW
UNSPEC_GOTINIT
UNSPEC_GOT
UNSPEC_GOTOFF
UNSPEC_PLT
UNSPEC_TLSGD
UNSPEC_TLSLD
UNSPEC_TLSIE
UNSPEC_TLSLE
UNSPEC_ROUND UNSPEC_ROUND
UNSPEC_VEC_COMPARE UNSPEC_VEC_COMPARE
UNSPEC_KHM UNSPEC_KHM
...@@ -83,6 +92,7 @@ ...@@ -83,6 +92,7 @@
UNSPEC_LOOP_END UNSPEC_LOOP_END
UNSPEC_TLS_DESC UNSPEC_TLS_DESC
UNSPEC_TLS_IE UNSPEC_TLS_IE
UNSPEC_ADD32
UNSPEC_ICT UNSPEC_ICT
UNSPEC_KADDH UNSPEC_KADDH
UNSPEC_KSUBH UNSPEC_KSUBH
......
...@@ -139,7 +139,7 @@ ...@@ -139,7 +139,7 @@
(define_split (define_split
[(set (match_operand:DIDF 0 "register_operand" "") [(set (match_operand:DIDF 0 "register_operand" "")
(match_operand:DIDF 1 "const_double_operand" ""))] (match_operand:DIDF 1 "const_double_operand" ""))]
"reload_completed" "flag_pic || reload_completed"
[(set (match_dup 2) (match_dup 3)) [(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))] (set (match_dup 4) (match_dup 5))]
{ {
......
...@@ -44,6 +44,20 @@ ...@@ -44,6 +44,20 @@
convert_move (operands[0], tmp_rtx, false); convert_move (operands[0], tmp_rtx, false);
DONE; DONE;
} }
if (REG_P (operands[0]) && SYMBOLIC_CONST_P (operands[1]))
{
if (nds32_tls_referenced_p (operands [1]))
{
nds32_expand_tls_move (operands);
DONE;
}
else if (flag_pic)
{
nds32_expand_pic_move (operands);
DONE;
}
}
}) })
(define_insn "*mov<mode>" (define_insn "*mov<mode>"
......
...@@ -519,6 +519,42 @@ nds32_const_double_range_ok_p (rtx op, machine_mode mode, ...@@ -519,6 +519,42 @@ nds32_const_double_range_ok_p (rtx op, machine_mode mode,
return val >= lower && val < upper; return val >= lower && val < upper;
} }
bool
nds32_const_unspec_p (rtx x)
{
if (GET_CODE (x) == CONST)
{
x = XEXP (x, 0);
if (GET_CODE (x) == PLUS)
x = XEXP (x, 0);
if (GET_CODE (x) == UNSPEC)
{
switch (XINT (x, 1))
{
case UNSPEC_GOTINIT:
case UNSPEC_GOT:
case UNSPEC_GOTOFF:
case UNSPEC_PLT:
case UNSPEC_TLSGD:
case UNSPEC_TLSLD:
case UNSPEC_TLSIE:
case UNSPEC_TLSLE:
return false;
default:
return true;
}
}
}
if (GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (x))
return false;
return true;
}
HOST_WIDE_INT HOST_WIDE_INT
const_vector_to_hwint (rtx op) const_vector_to_hwint (rtx op)
{ {
......
...@@ -151,6 +151,8 @@ extern int nds32_can_use_bitci_p (int); ...@@ -151,6 +151,8 @@ extern int nds32_can_use_bitci_p (int);
extern bool nds32_const_double_range_ok_p (rtx, machine_mode, extern bool nds32_const_double_range_ok_p (rtx, machine_mode,
HOST_WIDE_INT, HOST_WIDE_INT); HOST_WIDE_INT, HOST_WIDE_INT);
extern bool nds32_const_unspec_p (rtx x);
/* Auxiliary function for 'Computing the Length of an Insn'. */ /* Auxiliary function for 'Computing the Length of an Insn'. */
extern int nds32_adjust_insn_length (rtx_insn *, int); extern int nds32_adjust_insn_length (rtx_insn *, int);
...@@ -183,6 +185,26 @@ extern void nds32_expand_float_movcc (rtx *); ...@@ -183,6 +185,26 @@ extern void nds32_expand_float_movcc (rtx *);
extern enum nds32_expand_result_type nds32_expand_extv (rtx *); extern enum nds32_expand_result_type nds32_expand_extv (rtx *);
extern enum nds32_expand_result_type nds32_expand_insv (rtx *); extern enum nds32_expand_result_type nds32_expand_insv (rtx *);
/* Auxiliary functions for expand PIC instruction. */
extern void nds32_expand_pic_move (rtx *);
/* Auxiliary functions to legitimize PIC address. */
extern rtx nds32_legitimize_pic_address (rtx);
/* Auxiliary functions for expand TLS instruction. */
extern void nds32_expand_tls_move (rtx *);
/* Auxiliary functions to legitimize TLS address. */
extern rtx nds32_legitimize_tls_address (rtx);
/* Auxiliary functions to identify thread-local symbol. */
extern bool nds32_tls_referenced_p (rtx);
/* Auxiliary functions for expand ICT instruction. */ /* Auxiliary functions for expand ICT instruction. */
extern void nds32_expand_ict_move (rtx *); extern void nds32_expand_ict_move (rtx *);
...@@ -236,7 +258,8 @@ extern const char *nds32_output_unpkd8 (rtx, rtx, rtx, rtx, bool); ...@@ -236,7 +258,8 @@ extern const char *nds32_output_unpkd8 (rtx, rtx, rtx, rtx, bool);
extern const char *nds32_output_call (rtx, rtx *, rtx, extern const char *nds32_output_call (rtx, rtx *, rtx,
const char *, const char *, bool); const char *, const char *, bool);
extern const char *nds32_output_tls_desc (rtx *);
extern const char *nds32_output_tls_ie (rtx *);
/* Auxiliary functions to output stack push/pop instruction. */ /* Auxiliary functions to output stack push/pop instruction. */
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
#include "cfgrtl.h" #include "cfgrtl.h"
#include "tree-pass.h" #include "tree-pass.h"
using namespace nds32;
/* This is used to create unique relax hint id value. /* This is used to create unique relax hint id value.
The initial value is 0. */ The initial value is 0. */
static int relax_group_id = 0; static int relax_group_id = 0;
...@@ -196,6 +198,110 @@ nds32_ict_const_p (rtx x) ...@@ -196,6 +198,110 @@ nds32_ict_const_p (rtx x)
} }
return FALSE; return FALSE;
} }
/* Group the following pattern as relax candidates:
GOT:
sethi $ra, hi20(sym)
ori $ra, $ra, lo12(sym)
lw $rb, [$ra + $gp]
GOTOFF, TLSLE:
sethi $ra, hi20(sym)
ori $ra, $ra, lo12(sym)
LS $rb, [$ra + $gp]
GOTOFF, TLSLE:
sethi $ra, hi20(sym)
ori $ra, $ra, lo12(sym)
add $rb, $ra, $gp($tp)
Initial GOT table:
sethi $gp,hi20(sym)
ori $gp, $gp, lo12(sym)
add5.pc $gp */
static auto_vec<rtx_insn *, 32> nds32_group_infos;
/* Group the PIC and TLS relax candidate instructions for linker. */
static bool
nds32_pic_tls_group (rtx_insn *def_insn,
enum nds32_relax_insn_type relax_type,
int sym_type)
{
df_ref def_record;
df_link *link;
rtx_insn *use_insn = NULL;
rtx pat, new_pat;
def_record = DF_INSN_DEFS (def_insn);
for (link = DF_REF_CHAIN (def_record); link; link = link->next)
{
if (!DF_REF_INSN_INFO (link->ref))
continue;
use_insn = DF_REF_INSN (link->ref);
/* Skip if define insn and use insn not in the same basic block. */
if (!dominated_by_p (CDI_DOMINATORS,
BLOCK_FOR_INSN (use_insn),
BLOCK_FOR_INSN (def_insn)))
return FALSE;
/* Skip if use_insn not active insn. */
if (!active_insn_p (use_insn))
return FALSE;
switch (relax_type)
{
case RELAX_ORI:
/* GOTOFF, TLSLE:
sethi $ra, hi20(sym)
ori $ra, $ra, lo12(sym)
add $rb, $ra, $gp($tp) */
if ((sym_type == UNSPEC_TLSLE
|| sym_type == UNSPEC_GOTOFF)
&& (recog_memoized (use_insn) == CODE_FOR_addsi3))
{
pat = XEXP (PATTERN (use_insn), 1);
new_pat =
gen_rtx_UNSPEC (SImode,
gen_rtvec (2, XEXP (pat, 0), XEXP (pat, 1)),
UNSPEC_ADD32);
validate_replace_rtx (pat, new_pat, use_insn);
nds32_group_infos.safe_push (use_insn);
}
else if (nds32_plus_reg_load_store_p (use_insn)
&& !nds32_sp_base_or_plus_load_store_p (use_insn))
nds32_group_infos.safe_push (use_insn);
else
return FALSE;
break;
default:
return FALSE;
}
}
return TRUE;
}
static int
nds32_pic_tls_symbol_type (rtx x)
{
x = XEXP (SET_SRC (PATTERN (x)), 1);
if (GET_CODE (x) == CONST)
{
x = XEXP (x, 0);
if (GET_CODE (x) == PLUS)
x = XEXP (x, 0);
return XINT (x, 1);
}
return XINT (x, 1);
}
/* Group the relax candidates with group id. */ /* Group the relax candidates with group id. */
static void static void
nds32_group_insns (rtx sethi) nds32_group_insns (rtx sethi)
...@@ -204,6 +310,7 @@ nds32_group_insns (rtx sethi) ...@@ -204,6 +310,7 @@ nds32_group_insns (rtx sethi)
df_link *link; df_link *link;
rtx_insn *use_insn = NULL; rtx_insn *use_insn = NULL;
rtx group_id; rtx group_id;
bool valid;
def_record = DF_INSN_DEFS (sethi); def_record = DF_INSN_DEFS (sethi);
...@@ -253,6 +360,132 @@ nds32_group_insns (rtx sethi) ...@@ -253,6 +360,132 @@ nds32_group_insns (rtx sethi)
/* Insert .relax_* directive. */ /* Insert .relax_* directive. */
if (active_insn_p (use_insn)) if (active_insn_p (use_insn))
emit_insn_before (gen_relax_group (group_id), use_insn); emit_insn_before (gen_relax_group (group_id), use_insn);
/* Find ori ra, ra, unspec(symbol) instruction. */
if (use_insn != NULL
&& recog_memoized (use_insn) == CODE_FOR_lo_sum
&& !nds32_const_unspec_p (XEXP (SET_SRC (PATTERN (use_insn)), 1)))
{
int sym_type = nds32_pic_tls_symbol_type (use_insn);
valid = nds32_pic_tls_group (use_insn, RELAX_ORI, sym_type);
/* Insert .relax_* directive. */
while (!nds32_group_infos.is_empty ())
{
use_insn = nds32_group_infos.pop ();
if (valid)
emit_insn_before (gen_relax_group (group_id), use_insn);
}
}
}
relax_group_id++;
}
/* Convert relax group id in rtl. */
static void
nds32_group_tls_insn (rtx insn)
{
rtx pat = PATTERN (insn);
rtx unspec_relax_group = XEXP (XVECEXP (pat, 0, 1), 0);
while (GET_CODE (pat) != SET && GET_CODE (pat) == PARALLEL)
{
pat = XVECEXP (pat, 0, 0);
}
if (GET_CODE (unspec_relax_group) == UNSPEC
&& XINT (unspec_relax_group, 1) == UNSPEC_VOLATILE_RELAX_GROUP)
{
XVECEXP (unspec_relax_group, 0, 0) = GEN_INT (relax_group_id);
}
relax_group_id++;
}
static bool
nds32_float_reg_load_store_p (rtx_insn *insn)
{
rtx pat = PATTERN (insn);
if (get_attr_type (insn) == TYPE_FLOAD
&& GET_CODE (pat) == SET
&& (GET_MODE (XEXP (pat, 0)) == SFmode
|| GET_MODE (XEXP (pat, 0)) == DFmode)
&& MEM_P (XEXP (pat, 1)))
{
rtx addr = XEXP (XEXP (pat, 1), 0);
/* [$ra] */
if (REG_P (addr))
return true;
/* [$ra + offset] */
if (GET_CODE (addr) == PLUS
&& REG_P (XEXP (addr, 0))
&& CONST_INT_P (XEXP (addr, 1)))
return true;
}
return false;
}
/* Group float load-store instructions:
la $ra, symbol
flsi $rt, [$ra + offset] */
static void
nds32_group_float_insns (rtx insn)
{
df_ref def_record, use_record;
df_link *link;
rtx_insn *use_insn = NULL;
rtx group_id;
def_record = DF_INSN_DEFS (insn);
for (link = DF_REF_CHAIN (def_record); link; link = link->next)
{
if (!DF_REF_INSN_INFO (link->ref))
continue;
use_insn = DF_REF_INSN (link->ref);
/* Skip if define insn and use insn not in the same basic block. */
if (!dominated_by_p (CDI_DOMINATORS,
BLOCK_FOR_INSN (use_insn),
BLOCK_FOR_INSN (insn)))
return;
/* Skip if the low-part used register is from different high-part
instructions. */
use_record = DF_INSN_USES (use_insn);
if (DF_REF_CHAIN (use_record) && DF_REF_CHAIN (use_record)->next)
return;
/* Skip if use_insn not active insn. */
if (!active_insn_p (use_insn))
return;
if (!nds32_float_reg_load_store_p (use_insn)
|| find_post_update_rtx (use_insn) != -1)
return;
}
group_id = GEN_INT (relax_group_id);
/* Insert .relax_* directive for insn. */
emit_insn_before (gen_relax_group (group_id), insn);
/* Scan the use insns and insert the directive. */
for (link = DF_REF_CHAIN (def_record); link; link = link->next)
{
if (!DF_REF_INSN_INFO (link->ref))
continue;
use_insn = DF_REF_INSN (link->ref);
/* Insert .relax_* directive. */
emit_insn_before (gen_relax_group (group_id), use_insn);
} }
relax_group_id++; relax_group_id++;
...@@ -285,6 +518,18 @@ nds32_relax_group (void) ...@@ -285,6 +518,18 @@ nds32_relax_group (void)
SImode) SImode)
&& !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0))) && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0)))
nds32_group_insns (insn); nds32_group_insns (insn);
else if (recog_memoized (insn) == CODE_FOR_tls_ie)
nds32_group_tls_insn (insn);
else if (TARGET_FPU_SINGLE
&& recog_memoized (insn) == CODE_FOR_move_addr
&& !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0)))
{
nds32_group_float_insns (insn);
}
}
else if (CALL_P (insn) && recog_memoized (insn) == CODE_FOR_tls_desc)
{
nds32_group_tls_insn (insn);
} }
} }
......
...@@ -36,6 +36,16 @@ ...@@ -36,6 +36,16 @@
#define NDS32_SYMBOL_REF_RODATA_P(x) \ #define NDS32_SYMBOL_REF_RODATA_P(x) \
((SYMBOL_REF_FLAGS (x) & NDS32_SYMBOL_FLAG_RODATA) != 0) ((SYMBOL_REF_FLAGS (x) & NDS32_SYMBOL_FLAG_RODATA) != 0)
enum nds32_relax_insn_type
{
RELAX_ORI,
RELAX_PLT_ADD,
RELAX_TLS_ADD_or_LW,
RELAX_TLS_ADD_LW,
RELAX_TLS_LW_JRAL,
RELAX_DONE
};
/* Classifies expand result for expand helper function. */ /* Classifies expand result for expand helper function. */
enum nds32_expand_result_type enum nds32_expand_result_type
{ {
......
...@@ -225,6 +225,16 @@ ...@@ -225,6 +225,16 @@
nds32_expand_ict_move (operands); nds32_expand_ict_move (operands);
DONE; DONE;
} }
else if (nds32_tls_referenced_p (operands [1]))
{
nds32_expand_tls_move (operands);
DONE;
}
else if (flag_pic)
{
nds32_expand_pic_move (operands);
DONE;
}
} }
}) })
...@@ -288,8 +298,8 @@ ...@@ -288,8 +298,8 @@
;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF ;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF
;; are able to match such instruction template. ;; are able to match such instruction template.
(define_insn "move_addr" (define_insn "move_addr"
[(set (match_operand:SI 0 "register_operand" "=l, r") [(set (match_operand:SI 0 "nds32_general_register_operand" "=l, r")
(match_operand:SI 1 "nds32_symbolic_operand" " i, i"))] (match_operand:SI 1 "nds32_nonunspec_symbolic_operand" " i, i"))]
"" ""
"la\t%0, %1" "la\t%0, %1"
[(set_attr "type" "alu") [(set_attr "type" "alu")
...@@ -1555,9 +1565,11 @@ ...@@ -1555,9 +1565,11 @@
(const_int 2) (const_int 2)
(const_int 4)) (const_int 4))
;; Alternative 1 ;; Alternative 1
(if_then_else (match_test "nds32_long_call_p (operands[0])") (if_then_else (match_test "flag_pic")
(const_int 12) (const_int 16)
(const_int 4)) (if_then_else (match_test "nds32_long_call_p (operands[0])")
(const_int 12)
(const_int 4)))
])] ])]
) )
...@@ -1641,9 +1653,11 @@ ...@@ -1641,9 +1653,11 @@
(const_int 2) (const_int 2)
(const_int 4)) (const_int 4))
;; Alternative 1 ;; Alternative 1
(if_then_else (match_test "nds32_long_call_p (operands[1])") (if_then_else (match_test "flag_pic")
(const_int 12) (const_int 16)
(const_int 4)) (if_then_else (match_test "nds32_long_call_p (operands[1])")
(const_int 12)
(const_int 4)))
])] ])]
) )
...@@ -1731,9 +1745,11 @@ ...@@ -1731,9 +1745,11 @@
(const_int 2) (const_int 2)
(const_int 4)) (const_int 4))
;; Alternative 1 ;; Alternative 1
(if_then_else (match_test "nds32_long_call_p (operands[0])") (if_then_else (match_test "flag_pic")
(const_int 12) (const_int 16)
(const_int 4)) (if_then_else (match_test "nds32_long_call_p (operands[0])")
(const_int 12)
(const_int 4)))
])] ])]
) )
...@@ -1793,9 +1809,11 @@ ...@@ -1793,9 +1809,11 @@
(const_int 2) (const_int 2)
(const_int 4)) (const_int 4))
;; Alternative 1 ;; Alternative 1
(if_then_else (match_test "nds32_long_call_p (operands[1])") (if_then_else (match_test "flag_pic")
(const_int 12) (const_int 16)
(const_int 4)) (if_then_else (match_test "nds32_long_call_p (operands[1])")
(const_int 12)
(const_int 4)))
])] ])]
) )
...@@ -1993,6 +2011,7 @@ ...@@ -1993,6 +2011,7 @@
{ {
rtx add_tmp; rtx add_tmp;
rtx reg, test; rtx reg, test;
rtx tmp_reg;
/* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */ /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */
if (operands[1] != const0_rtx) if (operands[1] != const0_rtx)
...@@ -2014,9 +2033,14 @@ ...@@ -2014,9 +2033,14 @@
emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2],
operands[4])); operands[4]));
/* Step C, D, E, and F, using another temporary register. */ tmp_reg = gen_reg_rtx (SImode);
rtx tmp = gen_reg_rtx (SImode); /* Step C, D, E, and F, using another temporary register tmp_reg. */
emit_jump_insn (gen_casesi_internal (operands[0], operands[3], tmp)); if (flag_pic)
emit_use (pic_offset_table_rtx);
emit_jump_insn (gen_casesi_internal (operands[0],
operands[3],
tmp_reg));
DONE; DONE;
}) })
...@@ -2052,8 +2076,11 @@ ...@@ -2052,8 +2076,11 @@
else else
return nds32_output_casesi (operands); return nds32_output_casesi (operands);
} }
[(set_attr "length" "20") [(set_attr "type" "branch")
(set_attr "type" "branch")]) (set (attr "length")
(if_then_else (match_test "flag_pic")
(const_int 28)
(const_int 20)))])
;; ---------------------------------------------------------------------------- ;; ----------------------------------------------------------------------------
...@@ -2129,6 +2156,16 @@ ...@@ -2129,6 +2156,16 @@
[(set_attr "length" "0")] [(set_attr "length" "0")]
) )
;; Add pc
(define_insn "add_pc"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 1 "register_operand" "0")
(pc)))]
"flag_pic"
"add5.pc\t%0"
[(set_attr "type" "alu")
(set_attr "length" "4")]
)
;; ---------------------------------------------------------------------------- ;; ----------------------------------------------------------------------------
;; Patterns for exception handling ;; Patterns for exception handling
...@@ -2193,3 +2230,57 @@ ...@@ -2193,3 +2230,57 @@
}) })
;; ---------------------------------------------------------------------------- ;; ----------------------------------------------------------------------------
;; Patterns for TLS.
;; The following two tls patterns don't be expanded directly because the
;; intermediate value may be spilled into the stack. As a result, it is
;; hard to analyze the define-use chain in the relax_opt pass.
;; There is a unspec operand to record RELAX_GROUP number because each
;; emitted instruction need a relax_hint above it.
(define_insn "tls_desc"
[(set (reg:SI 0)
(call (unspec_volatile:SI [(match_operand:SI 0 "nds32_symbolic_operand" "i")] UNSPEC_TLS_DESC)
(const_int 1)))
(use (unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
(use (reg:SI GP_REGNUM))
(clobber (reg:SI LP_REGNUM))
(clobber (reg:SI TA_REGNUM))]
""
{
return nds32_output_tls_desc (operands);
}
[(set_attr "length" "20")
(set_attr "type" "branch")]
)
;; There is a unspec operand to record RELAX_GROUP number because each
;; emitted instruction need a relax_hint above it.
(define_insn "tls_ie"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE))
(use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
(use (reg:SI GP_REGNUM))]
""
{
return nds32_output_tls_ie (operands);
}
[(set (attr "length") (if_then_else (match_test "flag_pic")
(const_int 12)
(const_int 8)))
(set_attr "type" "misc")]
)
;; The pattern is for some relaxation groups that have to keep addsi3 in 32-bit mode.
(define_insn "addsi3_32bit"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(match_operand:SI 1 "register_operand" "%r")
(match_operand:SI 2 "register_operand" " r")] UNSPEC_ADD32))]
""
"add\t%0, %1, %2";
[(set_attr "type" "alu")
(set_attr "length" "4")
(set_attr "feature" "v1")])
;; ----------------------------------------------------------------------------
...@@ -44,6 +44,12 @@ ...@@ -44,6 +44,12 @@
(match_test "!(TARGET_ICT_MODEL_LARGE (match_test "!(TARGET_ICT_MODEL_LARGE
&& nds32_indirect_call_referenced_p (op))"))) && nds32_indirect_call_referenced_p (op))")))
(define_predicate "nds32_nonunspec_symbolic_operand"
(and (match_code "const,symbol_ref,label_ref")
(match_test "!flag_pic && nds32_const_unspec_p (op)
&& !(TARGET_ICT_MODEL_LARGE
&& nds32_indirect_call_referenced_p (op))")))
(define_predicate "nds32_reg_constant_operand" (define_predicate "nds32_reg_constant_operand"
(ior (match_operand 0 "register_operand") (ior (match_operand 0 "register_operand")
(match_operand 0 "const_int_operand"))) (match_operand 0 "const_int_operand")))
......
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