aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2018-11-29 15:13:21 +1030
committerAlan Modra <amodra@gcc.gnu.org>2018-11-29 15:13:21 +1030
commitce83eeda066824074e56fbecdfcc5dd23fac6486 (patch)
tree8707ec139df15a2a40d15143b861c4d580e5109d /gcc/config/rs6000/rs6000.c
parent75a0b80599ca4326da8a203e042cb9db6c27ab08 (diff)
downloadgcc-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.c77
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. */