diff options
author | Alan Modra <amodra@gmail.com> | 2018-11-29 15:13:21 +1030 |
---|---|---|
committer | Alan Modra <amodra@gcc.gnu.org> | 2018-11-29 15:13:21 +1030 |
commit | ce83eeda066824074e56fbecdfcc5dd23fac6486 (patch) | |
tree | 8707ec139df15a2a40d15143b861c4d580e5109d /gcc/config/rs6000/rs6000.c | |
parent | 75a0b80599ca4326da8a203e042cb9db6c27ab08 (diff) | |
download | gcc-ce83eeda066824074e56fbecdfcc5dd23fac6486.zip gcc-ce83eeda066824074e56fbecdfcc5dd23fac6486.tar.gz gcc-ce83eeda066824074e56fbecdfcc5dd23fac6486.tar.bz2 |
[RS6000] rs6000_indirect_call_template
Like the last patch for external calls, now handle most assembly code
for indirect calls in one place. The patch also merges some insns,
correcting some !rs6000_speculate_indirect_jumps cases branching to
LR, which don't require a speculation barrier.
* config/rs6000/rs6000-protos.h (rs6000_indirect_call_template),
(rs6000_indirect_sibcall_template): Declare.
* config/rs6000/rs6000.c (rs6000_indirect_call_template_1),
(rs6000_indirect_call_template, rs6000_indirect_sibcall_template):
New functions.
* config/rs6000/rs6000.md (call_indirect_nonlocal_sysv),
(call_value_indirect_nonlocal_sysv, sibcall_nonlocal_sysv),
(call_indirect_aix, call_value_indirect_aix): Use
rs6000_indirect_call_template and rs6000_indirect_sibcall_template.
call_indirect_elfv2, call_value_indirect_elfv2): Likewise, and
handle both speculation and non-speculation cases.
(call_indirect_aix_nospec, call_value_indirect_aix_nospec): Delete.
(call_indirect_elfv2_nospec, call_value_indirect_elfv2_nospec): Delete.
From-SVN: r266601
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 7c7117c..497a157 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -21411,6 +21411,83 @@ rs6000_sibcall_template (rtx *operands, unsigned int funop, const char *arg) return rs6000_call_template_1 (operands, funop, true, arg); } +/* As above, for indirect calls. */ + +static const char * +rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop, + bool sibcall) +{ + /* -Wformat-overflow workaround, without which gcc thinks that %u + might produce 10 digits. */ + gcc_assert (funop <= MAX_RECOG_OPERANDS); + + static char str[144]; + const char *ptrload = TARGET_64BIT ? "d" : "wz"; + + /* We don't need the extra code to stop indirect call speculation if + calling via LR. */ + bool speculate = (TARGET_MACHO + || rs6000_speculate_indirect_jumps + || (REG_P (operands[funop]) + && REGNO (operands[funop]) == LR_REGNO)); + + if (DEFAULT_ABI == ABI_AIX) + { + if (speculate) + sprintf (str, + "l%s 2,%%%u\n\t" + "b%%T%ul\n\t" + "l%s 2,%%%u(1)", + ptrload, funop + 2, funop, ptrload, funop + 3); + else + sprintf (str, + "crset 2\n\t" + "l%s 2,%%%u\n\t" + "beq%%T%ul-\n\t" + "l%s 2,%%%u(1)", + ptrload, funop + 2, funop, ptrload, funop + 3); + } + else if (DEFAULT_ABI == ABI_ELFv2) + { + if (speculate) + sprintf (str, + "b%%T%ul\n\t" + "l%s 2,%%%u(1)", + funop, ptrload, funop + 2); + else + sprintf (str, + "crset 2\n\t" + "beq%%T%ul-\n\t" + "l%s 2,%%%u(1)", + funop, ptrload, funop + 2); + } + else + { + if (speculate) + sprintf (str, + "b%%T%u%s", + funop, sibcall ? "" : "l"); + else + sprintf (str, + "crset 2\n\t" + "beq%%T%u%s-%s", + funop, sibcall ? "" : "l", sibcall ? "\n\tb $" : ""); + } + return str; +} + +const char * +rs6000_indirect_call_template (rtx *operands, unsigned int funop) +{ + return rs6000_indirect_call_template_1 (operands, funop, false); +} + +const char * +rs6000_indirect_sibcall_template (rtx *operands, unsigned int funop) +{ + return rs6000_indirect_call_template_1 (operands, funop, true); +} + #if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO /* Emit an assembler directive to set symbol visibility for DECL to VISIBILITY_TYPE. */ |