nios2-protos.h (nios2_adjust_call_address): Adjust function parameter declaration.
2015-03-21 Chung-Lin Tang <cltang@codesourcery.com> Sandra Loosemore <sandra@codesourcery.com> gcc/ * config/nios2/nios2-protos.h (nios2_adjust_call_address): Adjust function parameter declaration. * config/nios2/nios2.md (call,call_value,sibcall,sibcall_value): Update arguments to nios2_adjust_call_address(). (sibcall_internal): Rename from *sibcall. (sibcall_value_internal): Rename from *sibcall_value. * config/nios2/nios2.c (nios2_emit_add_constant): New function. (nios2_large_got_address): Add target temp reg parameter. (nios2_got_address): Adjust call to nios2_large_got_address, add force_reg around it. (nios2_load_pic_address): Add target temp reg parameter, replace call to nios2_got_address with corresponding code. (nios2_legitimize_constant_address): Update call to nios2_load_pic_address. (nios2_adjust_call_address): Add temp reg parameter, update PIC case to use temp reg for PIC loading purposes. (nios2_asm_output_mi_thunk): Implement TARGET_ASM_OUTPUT_MI_THUNK. (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Define. (TARGET_ASM_OUTPUT_MI_THUNK): Likewise. Co-Authored-By: Sandra Loosemore <sandra@codesourcery.com> From-SVN: r221569
This commit is contained in:
parent
f409ce4cd7
commit
a866d527fe
4 changed files with 146 additions and 24 deletions
|
@ -1,3 +1,26 @@
|
|||
2015-03-21 Chung-Lin Tang <cltang@codesourcery.com>
|
||||
Sandra Loosemore <sandra@codesourcery.com>
|
||||
|
||||
* config/nios2/nios2-protos.h (nios2_adjust_call_address): Adjust
|
||||
function parameter declaration.
|
||||
* config/nios2/nios2.md (call,call_value,sibcall,sibcall_value):
|
||||
Update arguments to nios2_adjust_call_address().
|
||||
(sibcall_internal): Rename from *sibcall.
|
||||
(sibcall_value_internal): Rename from *sibcall_value.
|
||||
* config/nios2/nios2.c (nios2_emit_add_constant): New function.
|
||||
(nios2_large_got_address): Add target temp reg parameter.
|
||||
(nios2_got_address): Adjust call to nios2_large_got_address, add
|
||||
force_reg around it.
|
||||
(nios2_load_pic_address): Add target temp reg parameter, replace call
|
||||
to nios2_got_address with corresponding code.
|
||||
(nios2_legitimize_constant_address): Update call to
|
||||
nios2_load_pic_address.
|
||||
(nios2_adjust_call_address): Add temp reg parameter, update PIC case
|
||||
to use temp reg for PIC loading purposes.
|
||||
(nios2_asm_output_mi_thunk): Implement TARGET_ASM_OUTPUT_MI_THUNK.
|
||||
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): Define.
|
||||
(TARGET_ASM_OUTPUT_MI_THUNK): Likewise.
|
||||
|
||||
2015-03-21 Sandra Loosemore <sandra@codesourcery.com>
|
||||
|
||||
* doc/invoke.texi (-fno-diagnostics-show-caret): Fix
|
||||
|
|
|
@ -31,7 +31,7 @@ extern void nios2_function_profiler (FILE *, int);
|
|||
#ifdef RTX_CODE
|
||||
extern int nios2_emit_move_sequence (rtx *, machine_mode);
|
||||
extern void nios2_emit_expensive_div (rtx *, machine_mode);
|
||||
extern void nios2_adjust_call_address (rtx *);
|
||||
extern void nios2_adjust_call_address (rtx *, rtx);
|
||||
|
||||
extern rtx nios2_get_return_address (int);
|
||||
extern void nios2_set_return_address (rtx, rtx);
|
||||
|
|
|
@ -489,6 +489,21 @@ nios2_emit_stack_limit_check (void)
|
|||
/* Temp regno used inside prologue/epilogue. */
|
||||
#define TEMP_REG_NUM 8
|
||||
|
||||
static rtx
|
||||
nios2_emit_add_constant (rtx reg, HOST_WIDE_INT immed)
|
||||
{
|
||||
rtx insn;
|
||||
if (SMALL_INT (immed))
|
||||
insn = emit_insn (gen_add2_insn (reg, gen_int_mode (immed, Pmode)));
|
||||
else
|
||||
{
|
||||
rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
|
||||
emit_move_insn (tmp, gen_int_mode (immed, Pmode));
|
||||
insn = emit_insn (gen_add2_insn (reg, tmp));
|
||||
}
|
||||
return insn;
|
||||
}
|
||||
|
||||
void
|
||||
nios2_expand_prologue (void)
|
||||
{
|
||||
|
@ -1229,12 +1244,12 @@ nios2_unspec_offset (rtx loc, int unspec)
|
|||
|
||||
/* Generate GOT pointer based address with large offset. */
|
||||
static rtx
|
||||
nios2_large_got_address (rtx offset)
|
||||
nios2_large_got_address (rtx offset, rtx tmp)
|
||||
{
|
||||
rtx addr = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_add3_insn (addr, pic_offset_table_rtx,
|
||||
force_reg (Pmode, offset)));
|
||||
return addr;
|
||||
if (!tmp)
|
||||
tmp = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (tmp, offset);
|
||||
return gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
|
||||
}
|
||||
|
||||
/* Generate a GOT pointer based address. */
|
||||
|
@ -1245,7 +1260,7 @@ nios2_got_address (rtx loc, int unspec)
|
|||
crtl->uses_pic_offset_table = 1;
|
||||
|
||||
if (nios2_large_offset_p (unspec))
|
||||
return nios2_large_got_address (offset);
|
||||
return force_reg (Pmode, nios2_large_got_address (offset, NULL_RTX));
|
||||
|
||||
return gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
|
||||
}
|
||||
|
@ -1784,13 +1799,17 @@ nios2_load_pic_register (void)
|
|||
|
||||
/* Generate a PIC address as a MEM rtx. */
|
||||
static rtx
|
||||
nios2_load_pic_address (rtx sym, int unspec)
|
||||
nios2_load_pic_address (rtx sym, int unspec, rtx tmp)
|
||||
{
|
||||
if (flag_pic == 2
|
||||
&& GET_CODE (sym) == SYMBOL_REF
|
||||
&& nios2_symbol_binds_local_p (sym))
|
||||
/* Under -fPIC, generate a GOTOFF address for local symbols. */
|
||||
return nios2_got_address (sym, UNSPEC_PIC_GOTOFF_SYM);
|
||||
{
|
||||
rtx offset = nios2_unspec_offset (sym, UNSPEC_PIC_GOTOFF_SYM);
|
||||
crtl->uses_pic_offset_table = 1;
|
||||
return nios2_large_got_address (offset, tmp);
|
||||
}
|
||||
|
||||
return gen_const_mem (Pmode, nios2_got_address (sym, unspec));
|
||||
}
|
||||
|
@ -1828,7 +1847,7 @@ nios2_legitimize_constant_address (rtx addr)
|
|||
if (nios2_tls_symbol_p (base))
|
||||
base = nios2_legitimize_tls_address (base);
|
||||
else if (flag_pic)
|
||||
base = nios2_load_pic_address (base, UNSPEC_PIC_SYM);
|
||||
base = nios2_load_pic_address (base, UNSPEC_PIC_SYM, NULL_RTX);
|
||||
else
|
||||
return addr;
|
||||
|
||||
|
@ -1943,18 +1962,24 @@ nios2_emit_move_sequence (rtx *operands, machine_mode mode)
|
|||
|
||||
/* The function with address *ADDR is being called. If the address
|
||||
needs to be loaded from the GOT, emit the instruction to do so and
|
||||
update *ADDR to point to the rtx for the loaded value. */
|
||||
update *ADDR to point to the rtx for the loaded value.
|
||||
If REG != NULL_RTX, it is used as the target/scratch register in the
|
||||
GOT address calculation. */
|
||||
void
|
||||
nios2_adjust_call_address (rtx *call_op)
|
||||
nios2_adjust_call_address (rtx *call_op, rtx reg)
|
||||
{
|
||||
rtx addr;
|
||||
gcc_assert (MEM_P (*call_op));
|
||||
addr = XEXP (*call_op, 0);
|
||||
if (MEM_P (*call_op))
|
||||
call_op = &XEXP (*call_op, 0);
|
||||
|
||||
rtx addr = *call_op;
|
||||
if (flag_pic && CONSTANT_P (addr))
|
||||
{
|
||||
rtx reg = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (reg, nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM));
|
||||
XEXP (*call_op, 0) = reg;
|
||||
rtx tmp = reg ? reg : NULL_RTX;
|
||||
if (!reg)
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
addr = nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM, tmp);
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, addr));
|
||||
*call_op = reg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3319,6 +3344,73 @@ nios2_merge_decl_attributes (tree olddecl, tree newdecl)
|
|||
DECL_ATTRIBUTES (newdecl));
|
||||
}
|
||||
|
||||
/* Implement TARGET_ASM_OUTPUT_MI_THUNK. */
|
||||
static void
|
||||
nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
|
||||
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
|
||||
tree function)
|
||||
{
|
||||
rtx this_rtx, funexp;
|
||||
rtx_insn *insn;
|
||||
|
||||
/* Pretend to be a post-reload pass while generating rtl. */
|
||||
reload_completed = 1;
|
||||
|
||||
if (flag_pic)
|
||||
nios2_load_pic_register ();
|
||||
|
||||
/* Mark the end of the (empty) prologue. */
|
||||
emit_note (NOTE_INSN_PROLOGUE_END);
|
||||
|
||||
/* Find the "this" pointer. If the function returns a structure,
|
||||
the structure return pointer is in $5. */
|
||||
if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
|
||||
this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO + 1);
|
||||
else
|
||||
this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
|
||||
|
||||
/* Add DELTA to THIS_RTX. */
|
||||
nios2_emit_add_constant (this_rtx, delta);
|
||||
|
||||
/* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
|
||||
if (vcall_offset)
|
||||
{
|
||||
rtx tmp;
|
||||
|
||||
tmp = gen_rtx_REG (Pmode, 2);
|
||||
emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
|
||||
nios2_emit_add_constant (tmp, vcall_offset);
|
||||
emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
|
||||
emit_insn (gen_add2_insn (this_rtx, tmp));
|
||||
}
|
||||
|
||||
/* Generate a tail call to the target function. */
|
||||
if (!TREE_USED (function))
|
||||
{
|
||||
assemble_external (function);
|
||||
TREE_USED (function) = 1;
|
||||
}
|
||||
funexp = XEXP (DECL_RTL (function), 0);
|
||||
/* Function address needs to be constructed under PIC,
|
||||
provide r2 to use here. */
|
||||
nios2_adjust_call_address (&funexp, gen_rtx_REG (Pmode, 2));
|
||||
insn = emit_call_insn (gen_sibcall_internal (funexp, const0_rtx));
|
||||
SIBLING_CALL_P (insn) = 1;
|
||||
|
||||
/* Run just enough of rest_of_compilation to get the insns emitted.
|
||||
There's not really enough bulk here to make other passes such as
|
||||
instruction scheduling worth while. Note that use_thunk calls
|
||||
assemble_start_function and assemble_end_function. */
|
||||
insn = get_insns ();
|
||||
shorten_branches (insn);
|
||||
final_start_function (insn, file, 1);
|
||||
final (insn, file, 1);
|
||||
final_end_function ();
|
||||
|
||||
/* Stop pretending to be a post-reload pass. */
|
||||
reload_completed = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||
|
@ -3439,6 +3531,13 @@ nios2_merge_decl_attributes (tree olddecl, tree newdecl)
|
|||
#undef TARGET_MERGE_DECL_ATTRIBUTES
|
||||
#define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
|
||||
|
||||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
|
||||
hook_bool_const_tree_hwi_hwi_const_tree_true
|
||||
|
||||
#undef TARGET_ASM_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_OUTPUT_MI_THUNK nios2_asm_output_mi_thunk
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
#include "gt-nios2.h"
|
||||
|
|
|
@ -726,7 +726,7 @@
|
|||
(match_operand 1 "" ""))
|
||||
(clobber (reg:SI RA_REGNO))])]
|
||||
""
|
||||
"nios2_adjust_call_address (&operands[0]);")
|
||||
"nios2_adjust_call_address (&operands[0], NULL_RTX);")
|
||||
|
||||
(define_expand "call_value"
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
|
@ -734,7 +734,7 @@
|
|||
(match_operand 2 "" "")))
|
||||
(clobber (reg:SI RA_REGNO))])]
|
||||
""
|
||||
"nios2_adjust_call_address (&operands[1]);")
|
||||
"nios2_adjust_call_address (&operands[1], NULL_RTX);")
|
||||
|
||||
(define_insn "*call"
|
||||
[(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
|
||||
|
@ -762,7 +762,7 @@
|
|||
(match_operand 1 "" ""))
|
||||
(return)])]
|
||||
""
|
||||
"nios2_adjust_call_address (&operands[0]);")
|
||||
"nios2_adjust_call_address (&operands[0], NULL_RTX);")
|
||||
|
||||
(define_expand "sibcall_value"
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
|
@ -770,9 +770,9 @@
|
|||
(match_operand 2 "" "")))
|
||||
(return)])]
|
||||
""
|
||||
"nios2_adjust_call_address (&operands[1]);")
|
||||
"nios2_adjust_call_address (&operands[1], NULL_RTX);")
|
||||
|
||||
(define_insn "*sibcall"
|
||||
(define_insn "sibcall_internal"
|
||||
[(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
|
||||
(match_operand 1 "" ""))
|
||||
(return)]
|
||||
|
@ -782,7 +782,7 @@
|
|||
jmp\\t%0"
|
||||
[(set_attr "type" "control")])
|
||||
|
||||
(define_insn "*sibcall_value"
|
||||
(define_insn "sibcall_value_internal"
|
||||
[(set (match_operand 0 "register_operand" "")
|
||||
(call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
|
||||
(match_operand 2 "" "")))
|
||||
|
|
Loading…
Add table
Reference in a new issue