* config/nds32/constants.md (unspec_element): Add UNSPEC_ICT.
* config/nds32/nds32-md-auxiliary.c
(symbolic_reference_mentioned_p): New.
(nds32_legitimize_ict_address): New.
(nds32_expand_ict_move): New.
(nds32_indirect_call_referenced_p): New.
(nds32_symbol_binds_local_p): Delete.
(nds32_long_call_p): Modify.
* config/nds32/nds32-opts.h (nds32_ict_model_type): New enum type.
* config/nds32/nds32-protos.h
(symbolic_reference_mentioned_p): Declare.
(nds32_legitimize_ict_address): Declare.
(nds32_expand_ict_move): Declare.
(nds32_indirect_call_referenced_p): Declare.
* config/nds32/nds32-relax-opt.c (nds32_ict_const_p): New.
(nds32_relax_group): Use nds32_ict_const_p as condition.
* config/nds32/nds32.c (nds32_attribute_table): Add "indirect_call".
(nds32_asm_file_start): Output ict_model directive in asm code.
(nds32_legitimate_address_p): Consider indirect call.
(nds32_print_operand): Consider indirect call.
(nds32_print_operand_address): Consider indirect call.
(nds32_insert_attributes): Handle "indirect_call" attribute.
(TARGET_LEGITIMATE_ADDRESS_P): Define.
(TARGET_LEGITIMATE_CONSTANT_P): Define.
(TARGET_CANNOT_FORCE_CONST_MEM): Define.
(TARGET_DELEGITIMIZE_ADDRESS): Define.
(TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Define.
* config/nds32/nds32.h (SYMBOLIC_CONST_P): Define.
(TARGET_ICT_MODEL_SMALL): Define.
(TARGET_ICT_MODEL_LARGE): Define.
* config/nds32/nds32.md (movsi): Consider ict model.
(call, call_value): Consider ict model.
(sibcall, sibcall_value): Consider ict model.
* config/nds32/nds32.opt (mict-model): New option.
* config/nds32/predicates.md (nds32_symbolic_operand): Consider ict
model.
Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>
From-SVN: r260390
+2018-05-19 Kuan-Lin Chen <kuanlinchentw@gmail.com>
+ Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * config/nds32/constants.md (unspec_element): Add UNSPEC_ICT.
+ * config/nds32/nds32-md-auxiliary.c
+ (symbolic_reference_mentioned_p): New.
+ (nds32_legitimize_ict_address): New.
+ (nds32_expand_ict_move): New.
+ (nds32_indirect_call_referenced_p): New.
+ (nds32_symbol_binds_local_p): Delete.
+ (nds32_long_call_p): Modify.
+ * config/nds32/nds32-opts.h (nds32_ict_model_type): New enum type.
+ * config/nds32/nds32-protos.h
+ (symbolic_reference_mentioned_p): Declare.
+ (nds32_legitimize_ict_address): Declare.
+ (nds32_expand_ict_move): Declare.
+ (nds32_indirect_call_referenced_p): Declare.
+ * config/nds32/nds32-relax-opt.c (nds32_ict_const_p): New.
+ (nds32_relax_group): Use nds32_ict_const_p as condition.
+ * config/nds32/nds32.c (nds32_attribute_table): Add "indirect_call".
+ (nds32_asm_file_start): Output ict_model directive in asm code.
+ (nds32_legitimate_address_p): Consider indirect call.
+ (nds32_print_operand): Consider indirect call.
+ (nds32_print_operand_address): Consider indirect call.
+ (nds32_insert_attributes): Handle "indirect_call" attribute.
+ (TARGET_LEGITIMATE_ADDRESS_P): Define.
+ (TARGET_LEGITIMATE_CONSTANT_P): Define.
+ (TARGET_CANNOT_FORCE_CONST_MEM): Define.
+ (TARGET_DELEGITIMIZE_ADDRESS): Define.
+ (TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Define.
+ * config/nds32/nds32.h (SYMBOLIC_CONST_P): Define.
+ (TARGET_ICT_MODEL_SMALL): Define.
+ (TARGET_ICT_MODEL_LARGE): Define.
+ * config/nds32/nds32.md (movsi): Consider ict model.
+ (call, call_value): Consider ict model.
+ (sibcall, sibcall_value): Consider ict model.
+ * config/nds32/nds32.opt (mict-model): New option.
+ * config/nds32/predicates.md (nds32_symbolic_operand): Consider ict
+ model.
+
2018-05-18 Kito Cheng <kito.cheng@gmail.com>
Monk Chiang <sh.chiang04@gmail.com>
Jim Wilson <jimw@sifive.com>
UNSPEC_LOOP_END
UNSPEC_TLS_DESC
UNSPEC_TLS_IE
+ UNSPEC_ICT
UNSPEC_KADDH
UNSPEC_KSUBH
])
#include "expr.h"
#include "emit-rtl.h"
#include "explow.h"
+#include "stringpool.h"
+#include "attribs.h"
+
/* ------------------------------------------------------------------------ */
return "";
}
-/* Return true if SYMBOL_REF X binds locally. */
-
-static bool
-nds32_symbol_binds_local_p (const_rtx x)
-{
- return (SYMBOL_REF_DECL (x)
- ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
- : SYMBOL_REF_LOCAL_P (x));
-}
-
const char *
nds32_output_call (rtx insn, rtx *operands, rtx symbol, const char *long_call,
const char *call, bool align_p)
emit_insn (gen_cmovnsi (dst_high_part, select_reg,
dst_high_part_l32, dst_high_part_g32));
}
+
+/* Return true if OP contains a symbol reference. */
+bool
+symbolic_reference_mentioned_p (rtx op)
+{
+ const char *fmt;
+ int i;
+
+ if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
+ return true;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (op));
+ for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ int j;
+
+ for (j = XVECLEN (op, i) - 1; j >= 0; j--)
+ if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
+ return true;
+ }
+
+ else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
+ return true;
+ }
+
+ return false;
+}
+
+/* Expand ICT symbol.
+ Example for @ICT and ICT model=large:
+
+ la $r0, symbol@ICT
+ -> sethi $rt, hi20(symbol@ICT)
+ lwi $r0, [$rt + lo12(symbol@ICT)]
+
+*/
+rtx
+nds32_legitimize_ict_address (rtx x)
+{
+ rtx symbol = x;
+ rtx addr = x;
+ rtx reg = gen_reg_rtx (Pmode);
+ gcc_assert (GET_CODE (x) == SYMBOL_REF
+ && nds32_indirect_call_referenced_p (x));
+
+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, symbol), UNSPEC_ICT);
+ addr = gen_rtx_CONST (SImode, addr);
+ emit_insn (gen_sethi (reg, addr));
+
+ x = gen_const_mem (SImode, gen_rtx_LO_SUM (Pmode, reg, addr));
+
+ return x;
+}
+
+void
+nds32_expand_ict_move (rtx *operands)
+{
+ rtx src = operands[1];
+
+ src = nds32_legitimize_ict_address (src);
+
+ emit_move_insn (operands[0], src);
+}
+
+/* Return true X is a indirect call symbol. */
+bool
+nds32_indirect_call_referenced_p (rtx x)
+{
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_ICT)
+ x = XVECEXP (x, 0, 0);
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ tree decl = SYMBOL_REF_DECL (x);
+
+ return decl
+ && (lookup_attribute("indirect_call",
+ DECL_ATTRIBUTES(decl))
+ != NULL);
+ }
+
+ return false;
+}
+
/* Return true X is need use long call. */
bool
nds32_long_call_p (rtx symbol)
{
- return TARGET_CMODEL_LARGE;
+ if (nds32_indirect_call_referenced_p (symbol))
+ return TARGET_ICT_MODEL_LARGE;
+ else
+ return TARGET_CMODEL_LARGE;
}
void
CMODEL_LARGE
};
+/* The code model defines the address generation strategy. */
+enum nds32_ict_model_type
+{
+ ICT_MODEL_SMALL,
+ ICT_MODEL_LARGE
+};
+
/* Multiply instruction configuration. */
enum nds32_mul_type
{
extern enum nds32_expand_result_type nds32_expand_extv (rtx *);
extern enum nds32_expand_result_type nds32_expand_insv (rtx *);
+/* Auxiliary functions for expand ICT instruction. */
+
+extern void nds32_expand_ict_move (rtx *);
+
+/* Auxiliary functions to legitimize address for indirect-call symbol. */
+
+extern rtx nds32_legitimize_ict_address (rtx);
+
+/* Auxiliary functions to identify indirect-call symbol. */
+
+extern bool nds32_indirect_call_referenced_p (rtx);
+
/* Auxiliary functions to identify long-call symbol. */
extern bool nds32_long_call_p (rtx);
+/* Auxiliary functions to identify SYMBOL_REF and LABEL_REF pattern. */
+
+extern bool symbolic_reference_mentioned_p (rtx);
+
/* Auxiliary functions to identify conditional move comparison operand. */
extern int nds32_cond_move_p (rtx);
return false;
}
+/* Return true if x is const and the referance is ict symbol. */
+static bool
+nds32_ict_const_p (rtx x)
+{
+ if (GET_CODE (x) == CONST)
+ {
+ x = XEXP (x, 0);
+ return nds32_indirect_call_referenced_p (x);
+ }
+ return FALSE;
+}
/* Group the relax candidates with group id. */
static void
nds32_group_insns (rtx sethi)
/* Find sethi ra, symbol instruction. */
if (recog_memoized (insn) == CODE_FOR_sethi
&& nds32_symbolic_operand (XEXP (SET_SRC (PATTERN (insn)), 0),
- SImode))
+ SImode)
+ && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0)))
nds32_group_insns (insn);
}
}
/* The attribute telling no prologue/epilogue. */
{ "naked", 0, 0, false, false, false, false, NULL, NULL },
+ /* The attribute is used to tell this function to be ROM patch. */
+ { "indirect_call",0, 0, false, false, false, false, NULL, NULL },
+
/* The last attribute spec is set to be NULL. */
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
case SYMBOL_REF:
/* (mem (symbol_ref A)) => [symbol_ref] */
+ if (TARGET_ICT_MODEL_LARGE && nds32_indirect_call_referenced_p (x))
+ return false;
+
/* If -mcmodel=large, the 'symbol_ref' is not a valid address
during or after LRA/reload phase. */
if (TARGET_CMODEL_LARGE
case LO_SUM:
/* (mem (lo_sum (reg) (symbol_ref))) */
- /* (mem (lo_sum (reg) (const))) */
- gcc_assert (REG_P (XEXP (x, 0)));
- if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
- || GET_CODE (XEXP (x, 1)) == CONST)
- return nds32_legitimate_address_p (mode, XEXP (x, 1), strict);
- else
- return false;
+ /* (mem (lo_sum (reg) (const (plus (symbol_ref) (reg)))) */
+ {
+ rtx sym = NULL_RTX;
+
+ if (!REG_P (XEXP (x, 0)))
+ return false;
+
+ if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
+ sym = XEXP (x, 1);
+ else if (GET_CODE (XEXP (x, 1)) == CONST)
+ {
+ rtx plus = XEXP(XEXP (x, 1), 0);
+ if (GET_CODE (plus) == PLUS)
+ sym = XEXP (plus, 0);
+ else if (GET_CODE (plus) == UNSPEC)
+ sym = XVECEXP (plus, 0, 0);
+ }
+ else
+ return false;
+
+ gcc_assert (GET_CODE (sym) == SYMBOL_REF);
+
+ if (TARGET_ICT_MODEL_LARGE
+ && nds32_indirect_call_referenced_p (sym))
+ return true;
+
+ if (TARGET_CMODEL_LARGE)
+ return true;
+ else if (TARGET_CMODEL_MEDIUM
+ && NDS32_SYMBOL_REF_RODATA_P (sym))
+ return true;
+ else
+ return false;
+ }
default:
return false;
}
}
+static rtx
+nds32_legitimize_address (rtx x,
+ rtx oldx ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if (TARGET_ICT_MODEL_LARGE && nds32_indirect_call_referenced_p (x))
+ x = nds32_legitimize_ict_address (x);
+
+ return x;
+}
+
+static bool
+nds32_legitimate_constant_p (machine_mode mode, rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_DOUBLE:
+ if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
+ && (mode == DFmode || mode == SFmode))
+ return false;
+ break;
+ case CONST:
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) == PLUS)
+ {
+ if (!CONST_INT_P (XEXP (x, 1)))
+ return false;
+ x = XEXP (x, 0);
+ }
+
+ if (GET_CODE (x) == UNSPEC)
+ {
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_ICT:
+ return false;
+ default:
+ return true;
+ }
+ }
+ break;
+ default:
+ return true;
+ }
+
+ return true;
+}
+
+/* Reorgnize the UNSPEC CONST and return its direct symbol. */
+static rtx
+nds32_delegitimize_address (rtx x)
+{
+ x = delegitimize_mem_from_attrs (x);
+
+ if (GET_CODE(x) == CONST)
+ {
+ rtx inner = XEXP (x, 0);
+
+ /* Handle for GOTOFF. */
+ if (GET_CODE (inner) == PLUS)
+ inner = XEXP (inner, 0);
+
+ if (GET_CODE (inner) == UNSPEC)
+ {
+ switch (XINT (inner, 1))
+ {
+ case UNSPEC_ICT:
+ x = XVECEXP (inner, 0, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return x;
+}
+
static machine_mode
nds32_vectorize_preferred_simd_mode (scalar_mode mode)
{
}
}
+static bool
+nds32_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ return !nds32_legitimate_constant_p (mode, x);
+ case SYMBOL_REF:
+ /* All symbols have to be accessed through gp-relative in PIC mode. */
+ /* We don't want to force symbol as constant pool in .text section,
+ because we use the gp-relatived instruction to load in small
+ or medium model. */
+ if (SYMBOL_REF_TLS_MODEL (x)
+ || TARGET_CMODEL_SMALL
+ || TARGET_CMODEL_MEDIUM)
+ return true;
+ break;
+ default:
+ return false;
+ }
+ return false;
+}
+
\f
/* Condition Code Status. */
/* Tell assembler that this asm code is generated by compiler. */
fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
fprintf (asm_out_file, "\t.flag\tverbatim\n");
+
+ if (TARGET_ICT_MODEL_LARGE)
+ fprintf (asm_out_file, "\t.ict_model\tlarge\n");
+ else
+ fprintf (asm_out_file, "\t.ict_model\tsmall\n");
/* Give assembler the size of each vector for interrupt handler. */
fprintf (asm_out_file, "\t! This vector size directive is required "
"for checking inconsistency on interrupt handler\n");
fprintf (asm_out_file, "\t! ------------------------------------\n");
}
+static bool
+nds32_asm_output_addr_const_extra (FILE *file, rtx x)
+{
+ if (GET_CODE (x) == UNSPEC)
+ {
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_ICT:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fputs ("@ICT", file);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+ else
+ return false;
+}
+
/* -- Output and Generation of Labels. */
static void
switch (GET_CODE (x))
{
case LABEL_REF:
+ output_addr_const (stream, x);
+ break;
+
case SYMBOL_REF:
output_addr_const (stream, x);
+
+ if (nds32_indirect_call_referenced_p (x))
+ fprintf (stream, "@ICT");
+
break;
case REG:
fprintf (stream, HOST_WIDE_INT_PRINT_HEX, const_vector_to_hwint (x));
break;
+ case LO_SUM:
+ /* This is a special case for inline assembly using memory address 'p'.
+ The inline assembly code is expected to use pesudo instruction
+ for the operand. EX: la */
+ output_addr_const (stream, XEXP(x, 1));
+ break;
+
default:
/* Generally, output_addr_const () is able to handle most cases.
We want to see what CODE could appear,
}
static void
-nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
+nds32_print_operand_address (FILE *stream,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x)
{
rtx op0, op1;
fputs ("]", stream);
break;
+ case LO_SUM:
+ /* This is a special case for inline assembly using memory operand 'm'.
+ The inline assembly code is expected to use pesudo instruction
+ for the operand. EX: [ls].[bhw] */
+ fputs ("[ + ", stream);
+ op1 = XEXP (x, 1);
+ output_addr_const (stream, op1);
+ fputs ("]", stream);
+ break;
+
case REG:
/* Forbid using static chain register ($r16)
on reduced-set registers configuration. */
static void
nds32_insert_attributes (tree decl, tree *attributes)
{
+ /* A "indirect_call" function attribute implies "noinline" and "noclone"
+ for elf toolchain to support ROM patch mechanism. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("indirect_call", *attributes) != NULL)
+ {
+ tree new_attrs = *attributes;
+
+ if (lookup_attribute ("noinline", new_attrs) == NULL)
+ new_attrs = tree_cons (get_identifier ("noinline"), NULL, new_attrs);
+ if (lookup_attribute ("noclone", new_attrs) == NULL)
+ new_attrs = tree_cons (get_identifier ("noclone"), NULL, new_attrs);
+
+ if (!TREE_PUBLIC (decl))
+ error("indirect_call attribute can't apply for static function");
+
+ *attributes = new_attrs;
+ }
+
/* For function declaration, we need to check isr-specific attributes:
1. Call nds32_check_isr_attrs_conflict() to check any conflict.
2. Check valid integer value for interrupt/exception.
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS nds32_legitimize_address
+
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P nds32_legitimate_constant_p
+
#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE nds32_vectorize_preferred_simd_mode
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM nds32_cannot_force_const_mem
+
+#undef TARGET_DELEGITIMIZE_ADDRESS
+#define TARGET_DELEGITIMIZE_ADDRESS nds32_delegitimize_address
+
\f
/* Anchored Addresses. */
#undef TARGET_ASM_ALIGNED_SI_OP
#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
+#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nds32_asm_output_addr_const_extra
+
/* -- Output of Uninitialized Variables. */
/* -- Output and Generation of Labels. */
#define TARGET_CMODEL_LARGE \
(nds32_cmodel_option == CMODEL_LARGE)
+#define TARGET_ICT_MODEL_SMALL \
+ (nds32_ict_model == ICT_MODEL_SMALL)
+
+#define TARGET_ICT_MODEL_LARGE \
+ (nds32_ict_model == ICT_MODEL_LARGE)
+
/* When -mcmodel=small or -mcmodel=medium,
compiler may generate gp-base instruction directly. */
#define TARGET_GP_DIRECT \
#define PIC_OFFSET_TABLE_REGNUM GP_REGNUM
+#define SYMBOLIC_CONST_P(X) \
+(GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
+
\f
/* Defining the Output Assembler Language. */
low12_int));
DONE;
}
+
+ if ((REG_P (operands[0]) || GET_CODE (operands[0]) == SUBREG)
+ && SYMBOLIC_CONST_P (operands[1]))
+ {
+ if (TARGET_ICT_MODEL_LARGE
+ && nds32_indirect_call_referenced_p (operands[1]))
+ {
+ nds32_expand_ict_move (operands);
+ DONE;
+ }
+ }
})
(define_insn "*mov<mode>"
(clobber (reg:SI LP_REGNUM))
(clobber (reg:SI TA_REGNUM))])]
""
- ""
+ {
+ rtx insn;
+ rtx sym = XEXP (operands[0], 0);
+
+ if (TARGET_ICT_MODEL_LARGE
+ && nds32_indirect_call_referenced_p (sym))
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_move_insn (reg, sym);
+ operands[0] = gen_const_mem (Pmode, reg);
+ }
+
+ if (flag_pic)
+ {
+ insn = emit_call_insn (gen_call_internal
+ (XEXP (operands[0], 0), GEN_INT (0)));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ DONE;
+ }
+ }
)
(define_insn "call_internal"
(match_operand 2)))
(clobber (reg:SI LP_REGNUM))
(clobber (reg:SI TA_REGNUM))])]
- "")
+ ""
+ {
+ rtx insn;
+ rtx sym = XEXP (operands[1], 0);
+
+ if (TARGET_ICT_MODEL_LARGE
+ && nds32_indirect_call_referenced_p (sym))
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_move_insn (reg, sym);
+ operands[1] = gen_const_mem (Pmode, reg);
+ }
+
+ if (flag_pic)
+ {
+ insn =
+ emit_call_insn (gen_call_value_internal
+ (operands[0], XEXP (operands[1], 0), GEN_INT (0)));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ DONE;
+ }
+ }
+)
(define_insn "call_value_internal"
[(parallel [(set (match_operand 0)
(const_int 0))
(clobber (reg:SI TA_REGNUM))
(return)])]
- "")
+ ""
+{
+ rtx sym = XEXP (operands[0], 0);
+
+ if (TARGET_ICT_MODEL_LARGE
+ && nds32_indirect_call_referenced_p (sym))
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_move_insn (reg, sym);
+ operands[0] = gen_const_mem (Pmode, reg);
+ }
+})
(define_insn "sibcall_internal"
[(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i"))
(const_int 0)))
(clobber (reg:SI TA_REGNUM))
(return)])]
- "")
+ ""
+{
+ rtx sym = XEXP (operands[1], 0);
+
+ if (TARGET_ICT_MODEL_LARGE
+ && nds32_indirect_call_referenced_p (sym))
+ {
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_move_insn (reg, sym);
+ operands[1] = gen_const_mem (Pmode, reg);
+ }
+})
(define_insn "sibcall_value_internal"
[(parallel [(set (match_operand 0)
Target Undocumented RejectNegative Negative(mbig-endian) InverseMask(BIG_ENDIAN)
Generate code in little-endian mode.
+mict-model=
+Target Undocumented RejectNegative Joined Enum(nds32_ict_model_type) Var(nds32_ict_model) Init(ICT_MODEL_SMALL)
+Specify the address generation strategy for ICT call's code model.
+
+Enum
+Name(nds32_ict_model_type) Type(enum nds32_ict_model_type)
+Known cmodel types (for use with the -mict-model= option):
+
+EnumValue
+Enum(nds32_ict_model_type) String(small) Value(ICT_MODEL_SMALL)
+
+EnumValue
+Enum(nds32_ict_model_type) String(large) Value(ICT_MODEL_LARGE)
mcmov
Target Report Mask(CMOV)
(match_code "mult,and,ior,xor"))
(define_predicate "nds32_symbolic_operand"
- (match_code "const,symbol_ref,label_ref"))
+ (and (match_code "const,symbol_ref,label_ref")
+ (match_test "!(TARGET_ICT_MODEL_LARGE
+ && nds32_indirect_call_referenced_p (op))")))
(define_predicate "nds32_reg_constant_operand"
(ior (match_operand 0 "register_operand")