m68k: uppercase pascal functions for linking

This commit is contained in:
Wolfgang Thaller
2017-04-15 23:31:48 +02:00
parent fe6f08fd7f
commit 4d0f9e202c

View File

@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h" #include "optabs.h"
#include "builtins.h" #include "builtins.h"
#include "rtl-iter.h" #include "rtl-iter.h"
#include "stringpool.h"
/* This file should be included last. */ /* This file should be included last. */
#include "target-def.h" #include "target-def.h"
@@ -191,6 +192,7 @@ static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x);
static bool m68k_output_addr_const_extra (FILE *, rtx); static bool m68k_output_addr_const_extra (FILE *, rtx);
static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
static tree m68k_mangle_decl_assembler_name (tree decl, tree id);
/* Initialize the GCC target structure. */ /* Initialize the GCC target structure. */
@@ -335,6 +337,9 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
#undef TARGET_FUNCTION_VALUE #undef TARGET_FUNCTION_VALUE
#define TARGET_FUNCTION_VALUE m68k_function_value #define TARGET_FUNCTION_VALUE m68k_function_value
#undef TARGET_MANGLE_DECL_ASSEMBLER_NAME
#define TARGET_MANGLE_DECL_ASSEMBLER_NAME m68k_mangle_decl_assembler_name
static const struct attribute_spec m68k_attribute_table[] = static const struct attribute_spec m68k_attribute_table[] =
{ {
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
@@ -344,11 +349,11 @@ static const struct attribute_spec m68k_attribute_table[] =
/* Stdcall attribute says callee is responsible for popping arguments /* Stdcall attribute says callee is responsible for popping arguments
if they are not variable. */ if they are not variable. */
{ "pascal", 0, 0, false, true, true, m68k_handle_fndecl_attribute, { "pascal", 0, 0, false, true, true, m68k_handle_fndecl_attribute,
true }, true },
{ "regparam", 1, 1, false, true, true, m68k_handle_fndecl_attribute, { "regparam", 1, 1, false, true, true, m68k_handle_fndecl_attribute,
true }, true },
{ "raw_inline", 1, 32, false, true, true, m68k_handle_fndecl_attribute, { "raw_inline", 1, 32, false, true, true, m68k_handle_fndecl_attribute,
false }, false },
{ "interrupt_handler", 0, 0, true, false, false, { "interrupt_handler", 0, 0, true, false, false,
m68k_handle_fndecl_attribute, false }, m68k_handle_fndecl_attribute, false },
{ "interrupt_thread", 0, 0, true, false, false, { "interrupt_thread", 0, 0, true, false, false,
@@ -746,7 +751,7 @@ m68k_get_function_kind (tree func)
tree a; tree a;
gcc_assert (TREE_CODE (func) == FUNCTION_DECL); gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func)); a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
if (a != NULL_TREE) if (a != NULL_TREE)
return m68k_fk_interrupt_handler; return m68k_fk_interrupt_handler;
@@ -1348,14 +1353,14 @@ m68k_expand_epilogue (bool sibcall_p)
emit_jump_insn (ret_rtx); emit_jump_insn (ret_rtx);
} }
/* Return true if X is a valid comparison operator for the dbcc /* Return true if X is a valid comparison operator for the dbcc
instruction. instruction.
Note it rejects floating point comparison operators. Note it rejects floating point comparison operators.
(In the future we could use Fdbcc). (In the future we could use Fdbcc).
It also rejects some comparisons when CC_NO_OVERFLOW is set. */ It also rejects some comparisons when CC_NO_OVERFLOW is set. */
int int
valid_dbcc_comparison_p_2 (rtx x, machine_mode mode ATTRIBUTE_UNUSED) valid_dbcc_comparison_p_2 (rtx x, machine_mode mode ATTRIBUTE_UNUSED)
{ {
@@ -1412,7 +1417,7 @@ static bool
m68k_ok_for_sibcall_p (tree decl, tree exp) m68k_ok_for_sibcall_p (tree decl, tree exp)
{ {
enum m68k_function_kind kind; enum m68k_function_kind kind;
/* We cannot use sibcalls for nested functions because we use the /* We cannot use sibcalls for nested functions because we use the
static chain register for indirect calls. */ static chain register for indirect calls. */
if (CALL_EXPR_STATIC_CHAIN (exp)) if (CALL_EXPR_STATIC_CHAIN (exp))
@@ -1451,14 +1456,14 @@ m68k_ok_for_sibcall_p (tree decl, tree exp)
the same. */ the same. */
if (decl && m68k_get_function_kind (decl) == kind) if (decl && m68k_get_function_kind (decl) == kind)
return true; return true;
return false; return false;
} }
/* On the m68k all args are always pushed - NOT. */ /* On the m68k all args are always pushed - NOT. */
void m68k_init_cumulative_args (CUMULATIVE_ARGS *cum, void m68k_init_cumulative_args (CUMULATIVE_ARGS *cum,
const_tree fntype, const_tree fntype,
rtx libname ATTRIBUTE_UNUSED, rtx libname ATTRIBUTE_UNUSED,
const_tree fndecl, const_tree fndecl,
int n_named_args) int n_named_args)
@@ -1679,8 +1684,8 @@ m68k_legitimize_address (rtx x, rtx oldx, machine_mode mode)
return x; return x;
} }
/* Output a dbCC; jCC sequence. Note we do not handle the /* Output a dbCC; jCC sequence. Note we do not handle the
floating point version of this sequence (Fdbcc). We also floating point version of this sequence (Fdbcc). We also
do not handle alternative conditions when CC_NO_OVERFLOW is do not handle alternative conditions when CC_NO_OVERFLOW is
set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
@@ -2529,19 +2534,19 @@ m68k_wrap_symbol_into_got_ref (rtx x, enum m68k_reloc reloc, rtx temp_reg)
/* Legitimize PIC addresses. If the address is already /* Legitimize PIC addresses. If the address is already
position-independent, we return ORIG. Newly generated position-independent, we return ORIG. Newly generated
position-independent addresses go to REG. If we need more position-independent addresses go to REG. If we need more
than one register, we lose. than one register, we lose.
An address is legitimized by making an indirect reference An address is legitimized by making an indirect reference
through the Global Offset Table with the name of the symbol through the Global Offset Table with the name of the symbol
used as an offset. used as an offset.
The assembler and linker are responsible for placing the The assembler and linker are responsible for placing the
address of the symbol in the GOT. The function prologue address of the symbol in the GOT. The function prologue
is responsible for initializing a5 to the starting address is responsible for initializing a5 to the starting address
of the GOT. of the GOT.
The assembler is also responsible for translating a symbol name The assembler is also responsible for translating a symbol name
into a constant displacement from the start of the GOT. into a constant displacement from the start of the GOT.
A quick example may make things a little clearer: A quick example may make things a little clearer:
@@ -2561,9 +2566,9 @@ m68k_wrap_symbol_into_got_ref (rtx x, enum m68k_reloc reloc, rtx temp_reg)
movel a5@(_foo:w), a0 movel a5@(_foo:w), a0
movel #12345, a0@ movel #12345, a0@
That (in a nutshell) is how *all* symbol and label references are
That (in a nutshell) is how *all* symbol and label references are
handled. */ handled. */
rtx rtx
@@ -2592,7 +2597,7 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
/* legitimize both operands of the PLUS */ /* legitimize both operands of the PLUS */
gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS); gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
base == reg ? 0 : reg); base == reg ? 0 : reg);
@@ -2654,13 +2659,13 @@ m68k_call_tls_get_addr (rtx x, rtx eqv, enum m68k_reloc reloc)
is the simpliest way of generating a call. The difference between is the simpliest way of generating a call. The difference between
__tls_get_addr() and libcall is that the result is returned in D0 __tls_get_addr() and libcall is that the result is returned in D0
instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p
which temporarily switches returning the result to A0. */ which temporarily switches returning the result to A0. */
m68k_libcall_value_in_a0_p = true; m68k_libcall_value_in_a0_p = true;
a0 = emit_library_call_value (m68k_get_tls_get_addr (), NULL_RTX, LCT_PURE, a0 = emit_library_call_value (m68k_get_tls_get_addr (), NULL_RTX, LCT_PURE,
Pmode, 1, x, Pmode); Pmode, 1, x, Pmode);
m68k_libcall_value_in_a0_p = false; m68k_libcall_value_in_a0_p = false;
insns = get_insns (); insns = get_insns ();
end_sequence (); end_sequence ();
@@ -2688,7 +2693,7 @@ m68k_get_m68k_read_tp (void)
/* Emit instruction sequence that calls __m68k_read_tp. /* Emit instruction sequence that calls __m68k_read_tp.
A pseudo register with result of __m68k_read_tp call is returned. */ A pseudo register with result of __m68k_read_tp call is returned. */
static rtx static rtx
m68k_call_m68k_read_tp (void) m68k_call_m68k_read_tp (void)
{ {
rtx a0; rtx a0;
@@ -2702,7 +2707,7 @@ m68k_call_m68k_read_tp (void)
is the simpliest way of generating a call. The difference between is the simpliest way of generating a call. The difference between
__m68k_read_tp() and libcall is that the result is returned in D0 __m68k_read_tp() and libcall is that the result is returned in D0
instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p
which temporarily switches returning the result to A0. */ which temporarily switches returning the result to A0. */
/* Emit the call sequence. */ /* Emit the call sequence. */
m68k_libcall_value_in_a0_p = true; m68k_libcall_value_in_a0_p = true;
@@ -2741,7 +2746,7 @@ m68k_legitimize_tls_address (rtx orig)
rtx eqv; rtx eqv;
rtx a0; rtx a0;
rtx x; rtx x;
/* Attach a unique REG_EQUIV, to allow the RTL optimizers to /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
share the LDM result with other LD model accesses. */ share the LDM result with other LD model accesses. */
eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
@@ -3211,7 +3216,7 @@ output_move_qimode (rtx *operands)
{ {
/* 68k family always modifies the stack pointer by at least 2, even for /* 68k family always modifies the stack pointer by at least 2, even for
byte pushes. The 5200 (ColdFire) does not do this. */ byte pushes. The 5200 (ColdFire) does not do this. */
/* This case is generated by pushqi1 pattern now. */ /* This case is generated by pushqi1 pattern now. */
gcc_assert (!(GET_CODE (operands[0]) == MEM gcc_assert (!(GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == PRE_DEC && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
@@ -4265,13 +4270,13 @@ notice_update_cc (rtx exp, rtx insn)
if (GET_CODE (exp) == SET) if (GET_CODE (exp) == SET)
{ {
if (GET_CODE (SET_SRC (exp)) == CALL) if (GET_CODE (SET_SRC (exp)) == CALL)
CC_STATUS_INIT; CC_STATUS_INIT;
else if (ADDRESS_REG_P (SET_DEST (exp))) else if (ADDRESS_REG_P (SET_DEST (exp)))
{ {
if (cc_status.value1 && modified_in_p (cc_status.value1, insn)) if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
cc_status.value1 = 0; cc_status.value1 = 0;
if (cc_status.value2 && modified_in_p (cc_status.value2, insn)) if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
cc_status.value2 = 0; cc_status.value2 = 0;
} }
/* fmoves to memory or data registers do not set the condition /* fmoves to memory or data registers do not set the condition
codes. Normal moves _do_ set the condition codes, but not in codes. Normal moves _do_ set the condition codes, but not in
@@ -4285,7 +4290,7 @@ notice_update_cc (rtx exp, rtx insn)
&& (FP_REG_P (SET_SRC (exp)) && (FP_REG_P (SET_SRC (exp))
|| GET_CODE (SET_SRC (exp)) == FIX || GET_CODE (SET_SRC (exp)) == FIX
|| FLOAT_MODE_P (GET_MODE (SET_DEST (exp))))) || FLOAT_MODE_P (GET_MODE (SET_DEST (exp)))))
CC_STATUS_INIT; CC_STATUS_INIT;
/* A pair of move insns doesn't produce a useful overall cc. */ /* A pair of move insns doesn't produce a useful overall cc. */
else if (!FP_REG_P (SET_DEST (exp)) else if (!FP_REG_P (SET_DEST (exp))
&& !FP_REG_P (SET_SRC (exp)) && !FP_REG_P (SET_SRC (exp))
@@ -4293,7 +4298,7 @@ notice_update_cc (rtx exp, rtx insn)
&& (GET_CODE (SET_SRC (exp)) == REG && (GET_CODE (SET_SRC (exp)) == REG
|| GET_CODE (SET_SRC (exp)) == MEM || GET_CODE (SET_SRC (exp)) == MEM
|| GET_CODE (SET_SRC (exp)) == CONST_DOUBLE)) || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
CC_STATUS_INIT; CC_STATUS_INIT;
else if (SET_DEST (exp) != pc_rtx) else if (SET_DEST (exp) != pc_rtx)
{ {
cc_status.flags = 0; cc_status.flags = 0;
@@ -4342,7 +4347,7 @@ notice_update_cc (rtx exp, rtx insn)
ends with a move insn moving r2 in r2's mode. ends with a move insn moving r2 in r2's mode.
Thus, the cc's are set for r2. Thus, the cc's are set for r2.
This can set N bit spuriously. */ This can set N bit spuriously. */
cc_status.flags |= CC_NOT_NEGATIVE; cc_status.flags |= CC_NOT_NEGATIVE;
default: default:
break; break;
@@ -4407,7 +4412,7 @@ output_move_const_single (rtx *operands)
to get the desired constant. */ to get the desired constant. */
/* This code has been fixed for cross-compilation. */ /* This code has been fixed for cross-compilation. */
static int inited_68881_table = 0; static int inited_68881_table = 0;
static const char *const strings_68881[7] = { static const char *const strings_68881[7] = {
@@ -4475,7 +4480,7 @@ standard_68881_constant_p (rtx x)
if (real_identical (r, &values_68881[i])) if (real_identical (r, &values_68881[i]))
return (codes_68881[i]); return (codes_68881[i]);
} }
if (GET_MODE (x) == SFmode) if (GET_MODE (x) == SFmode)
return 0; return 0;
@@ -4760,7 +4765,7 @@ m68k_delegitimize_address (rtx orig_x)
unspec = XEXP (addr.offset, 0); unspec = XEXP (addr.offset, 0);
if (GET_CODE (unspec) == PLUS && CONST_INT_P (XEXP (unspec, 1))) if (GET_CODE (unspec) == PLUS && CONST_INT_P (XEXP (unspec, 1)))
unspec = XEXP (unspec, 0); unspec = XEXP (unspec, 0);
if (GET_CODE (unspec) != UNSPEC if (GET_CODE (unspec) != UNSPEC
|| (XINT (unspec, 1) != UNSPEC_RELOC16 || (XINT (unspec, 1) != UNSPEC_RELOC16
&& XINT (unspec, 1) != UNSPEC_RELOC32)) && XINT (unspec, 1) != UNSPEC_RELOC32))
return orig_x; return orig_x;
@@ -4781,7 +4786,7 @@ m68k_delegitimize_address (rtx orig_x)
x = replace_equiv_address_nv (orig_x, x); x = replace_equiv_address_nv (orig_x, x);
return x; return x;
} }
/* A C compound statement to output to stdio stream STREAM the /* A C compound statement to output to stdio stream STREAM the
assembler syntax for an instruction operand that is a memory assembler syntax for an instruction operand that is a memory
@@ -4795,7 +4800,7 @@ m68k_delegitimize_address (rtx orig_x)
It is possible for PIC to generate a (plus (label_ref...) (reg...)) It is possible for PIC to generate a (plus (label_ref...) (reg...))
and we handle that just like we would a (plus (symbol_ref...) (reg...)). and we handle that just like we would a (plus (symbol_ref...) (reg...)).
This routine is responsible for distinguishing between -fpic and -fPIC This routine is responsible for distinguishing between -fpic and -fPIC
style relocations in an address. When generating -fpic code the style relocations in an address. When generating -fpic code the
offset is output in word mode (e.g. movel a5@(_foo:w), a0). When generating offset is output in word mode (e.g. movel a5@(_foo:w), a0). When generating
-fPIC code the offset is output in long mode (e.g. movel a5@(_foo:l), a0) */ -fPIC code the offset is output in long mode (e.g. movel a5@(_foo:l), a0) */
@@ -6228,7 +6233,7 @@ m68k_sched_variable_issue (FILE *sched_dump ATTRIBUTE_UNUSED,
case CPU_CFV3: case CPU_CFV3:
insn_size = sched_get_attr_size_int (insn); insn_size = sched_get_attr_size_int (insn);
/* ColdFire V3 and V4 cores have instruction buffers that can /* ColdFire V3 and V4 cores have instruction buffers that can
accumulate up to 8 instructions regardless of instructions' accumulate up to 8 instructions regardless of instructions'
sizes. So we should take care not to "prefetch" 24 one-word sizes. So we should take care not to "prefetch" 24 one-word
@@ -6732,6 +6737,34 @@ m68k_write_macsbug_name(FILE *file, const char *name)
fprintf(file, "\t.align 2,0\n\t.short 0\n"); fprintf(file, "\t.align 2,0\n\t.short 0\n");
} }
static tree
m68k_mangle_decl_assembler_name (tree decl, tree id)
{
tree new_id = NULL_TREE;
if (TREE_CODE (decl) == FUNCTION_DECL)
{
tree attrs = TYPE_ATTRIBUTES ( TREE_TYPE(decl) );
if (attrs != NULL_TREE)
{
if (lookup_attribute ("pascal", attrs))
{
const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
char *new_str, *p;
int len = strlen(old_str);
new_str = XALLOCAVEC (char, 1 + len);
for(int i = 0; i < len; i++)
new_str[i] = TOUPPER(old_str[i]);
new_str[len] = 0;
return get_identifier (new_str);
}
}
}
return id;
}