summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--backends/ChangeLog13
-rw-r--r--backends/riscv_init.c21
-rw-r--r--backends/riscv_retval.c86
3 files changed, 104 insertions, 16 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog
index ac0e3187..b48af4e1 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,16 @@
+2021-09-29 William Cohen <[email protected]>
+
+ * riscv_init.c (riscv_return_value_location_lp64f): New function
+ declaration.
+ (riscv_return_value_location_lp64): Likewise.
+ (riscv_init): Set return_value_location based on elf class and
+ ehdr flags.
+ * riscv_retval.c (riscv_return_value_location_lp64d): Renamed to...
+ (riscv_return_value_location_lp64ifd): ...this. Handle single,
+ double, float _Complex and double _Complex cases.
+ (riscv_return_value_location_lp64d): New function.
+ (riscv_return_value_location_lp64f): Likewise.
+
2021-04-19 Martin Liska <[email protected]>
* aarch64_symbol.c (aarch64_data_marker_symbol): Use startswith.
diff --git a/backends/riscv_init.c b/backends/riscv_init.c
index 551e7bb6..141e0821 100644
--- a/backends/riscv_init.c
+++ b/backends/riscv_init.c
@@ -41,6 +41,12 @@
extern __typeof (EBLHOOK (return_value_location))
riscv_return_value_location_lp64d attribute_hidden;
+extern __typeof (EBLHOOK (return_value_location))
+ riscv_return_value_location_lp64f attribute_hidden;
+
+extern __typeof (EBLHOOK (return_value_location))
+ riscv_return_value_location_lp64 attribute_hidden;
+
extern __typeof (EBLHOOK (core_note)) riscv64_core_note attribute_hidden;
Ebl *
@@ -63,10 +69,17 @@ riscv_init (Elf *elf,
eh->core_note = riscv64_core_note;
else
HOOK (eh, core_note);
- if (eh->class == ELFCLASS64
- && ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
- == EF_RISCV_FLOAT_ABI_DOUBLE))
- eh->return_value_location = riscv_return_value_location_lp64d;
+ if (eh->class == ELFCLASS64)
+ {
+ if ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
+ == EF_RISCV_FLOAT_ABI_DOUBLE)
+ eh->return_value_location = riscv_return_value_location_lp64d;
+ else if ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
+ == EF_RISCV_FLOAT_ABI_SINGLE)
+ eh->return_value_location = riscv_return_value_location_lp64f;
+ else
+ eh->return_value_location = riscv_return_value_location_lp64;
+ }
return eh;
}
diff --git a/backends/riscv_retval.c b/backends/riscv_retval.c
index 35b6010b..34761486 100644
--- a/backends/riscv_retval.c
+++ b/backends/riscv_retval.c
@@ -125,8 +125,8 @@ pass_by_flattened_arg (const Dwarf_Op **locp __attribute__ ((unused)),
}
int
-riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
- const Dwarf_Op **locp)
+riscv_return_value_location_lp64ifd (int fp, Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
@@ -211,10 +211,29 @@ riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
switch (size)
{
case 4: /* single */
- case 8: /* double */
- return pass_in_fpr_lp64d (locp, size);
-
- case 16: /* quad */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ return pass_in_fpr_lp64d (locp, size);
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ return pass_in_gpr_lp64 (locp, size);
+ default:
+ return -2;
+ }
+ case 8: /* double */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ return pass_in_fpr_lp64d (locp, size);
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ return pass_in_gpr_lp64 (locp, size);
+ default:
+ return -2;
+ }
+
+ case 16: /* quad */
return pass_in_gpr_lp64 (locp, size);
default:
@@ -227,12 +246,31 @@ riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
switch (size)
{
case 8: /* float _Complex */
- return pass_in_fpr_lp64f (locp, size);
-
- case 16: /* double _Complex */
- return pass_in_fpr_lp64d (locp, size);
-
- case 32: /* long double _Complex */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ return pass_in_fpr_lp64f (locp, size);
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ /* Double the size so the vals are two registers. */
+ return pass_in_gpr_lp64 (locp, size * 2);
+ default:
+ return -2;
+ }
+
+ case 16: /* double _Complex */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ return pass_in_fpr_lp64d (locp, size);
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ return pass_in_gpr_lp64 (locp, size);
+ default:
+ return -2;
+ }
+
+ case 32: /* long double _Complex */
return pass_by_ref (locp);
default:
@@ -249,3 +287,27 @@ riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
*locp = NULL;
return 0;
}
+
+int
+riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
+{
+ return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_DOUBLE,
+ functypedie, locp);
+}
+
+int
+riscv_return_value_location_lp64f (Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
+{
+ return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_SINGLE,
+ functypedie, locp);
+}
+
+int
+riscv_return_value_location_lp64 (Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
+{
+ return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_SOFT,
+ functypedie, locp);
+}