summaryrefslogtreecommitdiffstats
path: root/backends
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2018-06-13 12:28:00 +0200
committerMark Wielaard <mark@klomp.org>2018-06-20 13:02:48 +0200
commit6ad1343200116145aae9e3f04f4973a7aaf3a999 (patch)
tree3351f37ff095a6c55ca92744dd973d63f616456a /backends
parent9e16a100bf8e0d43415253fe8cfd3ba1d8e637d1 (diff)
backends: add abi_cfi and register_info callbacks for RISC-V
From https://github.com/riscv/riscv-isa-manual/raw/master/release/riscv-spec-v2.2.pdf and GCC source. Signed-off-by: Andreas Schwab <schwab@suse.de>
Diffstat (limited to 'backends')
-rw-r--r--backends/ChangeLog7
-rw-r--r--backends/Makefile.am2
-rw-r--r--backends/riscv_cfi.c75
-rw-r--r--backends/riscv_init.c4
-rw-r--r--backends/riscv_regs.c177
5 files changed, 264 insertions, 1 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 0dde0ff3..b34918fa 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,10 @@
+2018-06-13 Andreas Schwab <schwab@suse.de>
+
+ * Makefile.am (riscv_SRCS): Add riscv_cfi.c and riscv_regs.c.
+ * riscv_cfi.c: New file.
+ * riscv_regs.c: Likewise.
+ * riscv_init.c (riscv_init): Hook register_info and abi_cfi.
+
2018-05-15 Andreas Schwab <schwab@suse.de>
* riscv_init.c (riscv_init): Hook check_special_symbol.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 80aa00e7..0c14ec86 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -131,7 +131,7 @@ cpu_bpf = ../libcpu/libcpu_bpf.a
libebl_bpf_pic_a_SOURCES = $(bpf_SRCS)
am_libebl_bpf_pic_a_OBJECTS = $(bpf_SRCS:.c=.os)
-riscv_SRCS = riscv_init.c riscv_symbol.c
+riscv_SRCS = riscv_init.c riscv_symbol.c riscv_cfi.c riscv_regs.c
libebl_riscv_pic_a_SOURCES = $(riscv_SRCS)
am_libebl_riscv_pic_a_OBJECTS = $(riscv_SRCS:.c=.os)
diff --git a/backends/riscv_cfi.c b/backends/riscv_cfi.c
new file mode 100644
index 00000000..1a84a382
--- /dev/null
+++ b/backends/riscv_cfi.c
@@ -0,0 +1,75 @@
+/* RISC-V ABI-specified defaults for DWARF CFI.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+
+int
+riscv_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+ static const uint8_t abi_cfi[] =
+ {
+ /* The initial Canonical Frame Address is the value of the
+ Stack Pointer (r2) as setup in the previous frame. */
+ DW_CFA_def_cfa, ULEB128_7 (2), ULEB128_7 (0),
+
+ /* The Stack Pointer (r2) is restored from CFA address by default. */
+ DW_CFA_val_offset, ULEB128_7 (2), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+ /* The return address register contains the return address setup by
+ caller. */
+ SV (1),
+
+ /* Callee-saved registers s0-s11, fs0-fs11. */
+ SV(8), SV (9), SV (18), SV (19), SV (20), SV (21),
+ SV (22), SV (23), SV (24), SV (25), SV (26), SV (27),
+
+ SV (40), SV (41), SV (50), SV (51), SV (52), SV (53),
+ SV (54), SV (55), SV (56), SV (57), SV (58), SV (59),
+#undef SV
+
+ /* XXX Note: registers intentionally unused by the program,
+ for example as a consequence of the procedure call standard
+ should be initialized as if by DW_CFA_same_value. */
+ };
+
+ abi_info->initial_instructions = abi_cfi;
+ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+ abi_info->data_alignment_factor = -4;
+
+ abi_info->return_address_register = 1; /* ra. */
+
+ return 0;
+}
diff --git a/backends/riscv_init.c b/backends/riscv_init.c
index 80be86d3..5588a6b7 100644
--- a/backends/riscv_init.c
+++ b/backends/riscv_init.c
@@ -51,6 +51,10 @@ riscv_init (Elf *elf __attribute__ ((unused)),
eh->name = "RISC-V";
riscv_init_reloc (eh);
HOOK (eh, reloc_simple_type);
+ HOOK (eh, register_info);
+ HOOK (eh, abi_cfi);
+ /* gcc/config/ #define DWARF_FRAME_REGISTERS. */
+ eh->frame_nregs = 66;
HOOK (eh, check_special_symbol);
HOOK (eh, machine_flag_check);
diff --git a/backends/riscv_regs.c b/backends/riscv_regs.c
new file mode 100644
index 00000000..7b577ca0
--- /dev/null
+++ b/backends/riscv_regs.c
@@ -0,0 +1,177 @@
+/* Register names and numbers for RISC-V DWARF.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND riscv_
+#include "libebl_CPU.h"
+
+ssize_t
+riscv_register_info (Ebl *ebl, int regno, char *name, size_t namelen,
+ const char **prefix, const char **setname,
+ int *bits, int *type)
+{
+ if (name == NULL)
+ return 64;
+
+ *prefix = "";
+
+ if (regno < 32)
+ {
+ *setname = "integer";
+ *type = DW_ATE_signed;
+ *bits = ebl->class == ELFCLASS64 ? 64 : 32;
+ }
+ else
+ {
+ *setname = "FPU";
+ *type = DW_ATE_float;
+ *bits = 64;
+ }
+
+ switch (regno)
+ {
+ case 0:
+ return stpcpy (name, "zero") + 1 - name;
+
+ case 1:
+ *type = DW_ATE_address;
+ return stpcpy (name, "ra") + 1 - name;
+
+ case 2:
+ *type = DW_ATE_address;
+ return stpcpy (name, "sp") + 1 - name;
+
+ case 3:
+ *type = DW_ATE_address;
+ return stpcpy (name, "gp") + 1 - name;
+
+ case 4:
+ *type = DW_ATE_address;
+ return stpcpy (name, "tp") + 1 - name;
+
+ case 5 ... 7:
+ name[0] = 't';
+ name[1] = regno - 5 + '0';
+ namelen = 2;
+ break;
+
+ case 8 ... 9:
+ name[0] = 's';
+ name[1] = regno - 8 + '0';
+ namelen = 2;
+ break;
+
+ case 10 ... 17:
+ name[0] = 'a';
+ name[1] = regno - 10 + '0';
+ namelen = 2;
+ break;
+
+ case 18 ... 25:
+ name[0] = 's';
+ name[1] = regno - 18 + '2';
+ namelen = 2;
+ break;
+
+ case 26 ... 27:
+ name[0] = 's';
+ name[1] = '1';
+ name[1] = regno - 26 + '0';
+ namelen = 3;
+ break;
+
+ case 28 ... 31:
+ name[0] = 't';
+ name[1] = regno - 28 + '3';
+ namelen = 2;
+ break;
+
+ case 32 ... 39:
+ name[0] = 'f';
+ name[1] = 't';
+ name[2] = regno - 32 + '0';
+ namelen = 3;
+ break;
+
+ case 40 ... 41:
+ name[0] = 'f';
+ name[1] = 's';
+ name[2] = regno - 40 + '0';
+ namelen = 3;
+ break;
+
+ case 42 ... 49:
+ name[0] = 'f';
+ name[1] = 'a';
+ name[2] = regno - 42 + '0';
+ namelen = 3;
+ break;
+
+ case 50 ... 57:
+ name[0] = 'f';
+ name[1] = 's';
+ name[2] = regno - 50 + '2';
+ namelen = 3;
+ break;
+
+ case 58 ... 59:
+ name[0] = 'f';
+ name[1] = 's';
+ name[2] = '1';
+ name[3] = regno - 58 + '0';
+ namelen = 4;
+ break;
+
+ case 60 ... 61:
+ name[0] = 'f';
+ name[1] = 't';
+ name[2] = regno - 60 + '8';
+ namelen = 3;
+ break;
+
+ case 62 ... 63:
+ name[0] = 'f';
+ name[1] = 't';
+ name[2] = '1';
+ name[3] = regno - 62 + '0';
+ namelen = 4;
+ break;
+
+ default:
+ *setname = NULL;
+ return 0;
+ }
+
+ name[namelen++] = '\0';
+ return namelen;
+}