7979 lines
254 KiB
Diff
7979 lines
254 KiB
Diff
|
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
|
|||
|
index 435b30b..488c4ab 100644
|
|||
|
--- a/bfd/Makefile.am
|
|||
|
+++ b/bfd/Makefile.am
|
|||
|
@@ -92,6 +92,7 @@ ALL_MACHINES = \
|
|||
|
cpu-maxq.lo \
|
|||
|
cpu-mcore.lo \
|
|||
|
cpu-mips.lo \
|
|||
|
+ cpu-nios2.lo \
|
|||
|
cpu-mmix.lo \
|
|||
|
cpu-mt.lo \
|
|||
|
cpu-msp430.lo \
|
|||
|
@@ -156,6 +157,7 @@ ALL_MACHINES_CFILES = \
|
|||
|
cpu-maxq.c \
|
|||
|
cpu-mcore.c \
|
|||
|
cpu-mips.c \
|
|||
|
+ cpu-nios2.c \
|
|||
|
cpu-mmix.c \
|
|||
|
cpu-mt.c \
|
|||
|
cpu-msp430.c \
|
|||
|
@@ -270,6 +272,7 @@ BFD32_BACKENDS = \
|
|||
|
elf32-mips.lo \
|
|||
|
elf32-mt.lo \
|
|||
|
elf32-msp430.lo \
|
|||
|
+ elf32-nios2.lo \
|
|||
|
elf32-openrisc.lo \
|
|||
|
elf32-or32.lo \
|
|||
|
elf32-pj.lo \
|
|||
|
@@ -446,6 +449,7 @@ BFD32_BACKENDS_CFILES = \
|
|||
|
elf32-mips.c \
|
|||
|
elf32-mt.c \
|
|||
|
elf32-msp430.c \
|
|||
|
+ elf32-nios2.c \
|
|||
|
elf32-openrisc.c \
|
|||
|
elf32-or32.c \
|
|||
|
elf32-pj.c \
|
|||
|
@@ -1065,6 +1069,7 @@ cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-maxq.lo: cpu-maxq.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mcore.lo: cpu-mcore.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mips.lo: cpu-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
+cpu-nios2.lo: cpu-nios2.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mmix.lo: cpu-mmix.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mt.lo: cpu-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-msp430.lo: cpu-msp430.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
@@ -1428,6 +1433,10 @@ elf32-msp430.lo: elf32-msp430.c $(INCDIR)/filenames.h \
|
|||
|
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
|
|||
|
$(INCDIR)/bfdlink.h $(INCDIR)/elf/msp430.h $(INCDIR)/elf/reloc-macros.h \
|
|||
|
elf32-target.h
|
|||
|
+elf32-nios2.lo: elf32-nios2.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
|
|||
|
+ genlink.h elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
|
|||
|
+ $(INCDIR)/elf/external.h $(INCDIR)/elf/nios2.h \
|
|||
|
+ $(INCDIR)/elf/reloc-macros.h elf32-target.h
|
|||
|
elf32-openrisc.lo: elf32-openrisc.c $(INCDIR)/filenames.h \
|
|||
|
$(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
|
|||
|
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
|
|||
|
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
|
|||
|
index 5bde689..5e57321 100644
|
|||
|
--- a/bfd/Makefile.in
|
|||
|
+++ b/bfd/Makefile.in
|
|||
|
@@ -327,6 +327,7 @@ ALL_MACHINES = \
|
|||
|
cpu-mt.lo \
|
|||
|
cpu-msp430.lo \
|
|||
|
cpu-or32.lo \
|
|||
|
+ cpu-nios2.lo \
|
|||
|
cpu-ns32k.lo \
|
|||
|
cpu-openrisc.lo \
|
|||
|
cpu-pdp11.lo \
|
|||
|
@@ -391,6 +392,7 @@ ALL_MACHINES_CFILES = \
|
|||
|
cpu-mt.c \
|
|||
|
cpu-msp430.c \
|
|||
|
cpu-or32.c \
|
|||
|
+ cpu-nios2.c \
|
|||
|
cpu-ns32k.c \
|
|||
|
cpu-openrisc.c \
|
|||
|
cpu-pdp11.c \
|
|||
|
@@ -502,6 +504,7 @@ BFD32_BACKENDS = \
|
|||
|
elf32-mips.lo \
|
|||
|
elf32-mt.lo \
|
|||
|
elf32-msp430.lo \
|
|||
|
+ elf32-nios2.lo \
|
|||
|
elf32-openrisc.lo \
|
|||
|
elf32-or32.lo \
|
|||
|
elf32-pj.lo \
|
|||
|
@@ -678,6 +681,7 @@ BFD32_BACKENDS_CFILES = \
|
|||
|
elf32-mips.c \
|
|||
|
elf32-mt.c \
|
|||
|
elf32-msp430.c \
|
|||
|
+ elf32-nios2.c \
|
|||
|
elf32-openrisc.c \
|
|||
|
elf32-or32.c \
|
|||
|
elf32-pj.c \
|
|||
|
@@ -1626,6 +1630,7 @@ cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-maxq.lo: cpu-maxq.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mcore.lo: cpu-mcore.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mips.lo: cpu-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
+cpu-nios2.lo: cpu-nios2.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mmix.lo: cpu-mmix.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-mt.lo: cpu-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
cpu-msp430.lo: cpu-msp430.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
|
|||
|
@@ -1989,6 +1994,10 @@ elf32-msp430.lo: elf32-msp430.c $(INCDIR)/filenames.h \
|
|||
|
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
|
|||
|
$(INCDIR)/bfdlink.h $(INCDIR)/elf/msp430.h $(INCDIR)/elf/reloc-macros.h \
|
|||
|
elf32-target.h
|
|||
|
+elf32-nios2.lo: elf32-nios2.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
|
|||
|
+ genlink.h elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
|
|||
|
+ $(INCDIR)/elf/external.h $(INCDIR)/elf/nios2.h \
|
|||
|
+ $(INCDIR)/elf/reloc-macros.h elf32-target.h
|
|||
|
elf32-openrisc.lo: elf32-openrisc.c $(INCDIR)/filenames.h \
|
|||
|
$(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
|
|||
|
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
|
|||
|
diff --git a/bfd/archures.c b/bfd/archures.c
|
|||
|
index 5029cb0..ece60b4 100644
|
|||
|
--- a/bfd/archures.c
|
|||
|
+++ b/bfd/archures.c
|
|||
|
@@ -381,6 +381,8 @@ DESCRIPTION
|
|||
|
. bfd_arch_maxq, {* Dallas MAXQ 10/20 *}
|
|||
|
.#define bfd_mach_maxq10 10
|
|||
|
.#define bfd_mach_maxq20 20
|
|||
|
+. bfd_arch_nios2,
|
|||
|
+.#define bfd_mach_nios2 1
|
|||
|
. bfd_arch_z80,
|
|||
|
.#define bfd_mach_z80strict 1 {* No undocumented opcodes. *}
|
|||
|
.#define bfd_mach_z80 3 {* With ixl, ixh, iyl, and iyh. *}
|
|||
|
@@ -462,6 +464,7 @@ extern const bfd_arch_info_type bfd_mn10300_arch;
|
|||
|
extern const bfd_arch_info_type bfd_msp430_arch;
|
|||
|
extern const bfd_arch_info_type bfd_mt_arch;
|
|||
|
extern const bfd_arch_info_type bfd_ns32k_arch;
|
|||
|
+extern const bfd_arch_info_type bfd_nios2_arch;
|
|||
|
extern const bfd_arch_info_type bfd_openrisc_arch;
|
|||
|
extern const bfd_arch_info_type bfd_or32_arch;
|
|||
|
extern const bfd_arch_info_type bfd_pdp11_arch;
|
|||
|
@@ -530,6 +533,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
|
|||
|
&bfd_mn10300_arch,
|
|||
|
&bfd_mt_arch,
|
|||
|
&bfd_msp430_arch,
|
|||
|
+ &bfd_nios2_arch,
|
|||
|
&bfd_ns32k_arch,
|
|||
|
&bfd_openrisc_arch,
|
|||
|
&bfd_or32_arch,
|
|||
|
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
|
|||
|
index 8f2af8b..f5c51d6 100644
|
|||
|
--- a/bfd/bfd-in2.h
|
|||
|
+++ b/bfd/bfd-in2.h
|
|||
|
@@ -2010,6 +2010,8 @@ enum bfd_architecture
|
|||
|
bfd_arch_maxq, /* Dallas MAXQ 10/20 */
|
|||
|
#define bfd_mach_maxq10 10
|
|||
|
#define bfd_mach_maxq20 20
|
|||
|
+ bfd_arch_nios2,
|
|||
|
+#define bfd_mach_nios2 1
|
|||
|
bfd_arch_z80,
|
|||
|
#define bfd_mach_z80strict 1 /* No undocumented opcodes. */
|
|||
|
#define bfd_mach_z80 3 /* With ixl, ixh, iyl, and iyh. */
|
|||
|
@@ -4271,6 +4273,23 @@ internally by the linker after analysis of a
|
|||
|
BFD_RELOC_XTENSA_ASM_EXPAND. */
|
|||
|
BFD_RELOC_XTENSA_ASM_SIMPLIFY,
|
|||
|
|
|||
|
+/* Relocations used by the Altera New Jersey core */
|
|||
|
+ BFD_RELOC_NIOS2_S16,
|
|||
|
+ BFD_RELOC_NIOS2_U16,
|
|||
|
+ BFD_RELOC_NIOS2_CALL26,
|
|||
|
+ BFD_RELOC_NIOS2_IMM5,
|
|||
|
+ BFD_RELOC_NIOS2_CACHE_OPX,
|
|||
|
+ BFD_RELOC_NIOS2_IMM6,
|
|||
|
+ BFD_RELOC_NIOS2_IMM8,
|
|||
|
+ BFD_RELOC_NIOS2_HI16,
|
|||
|
+ BFD_RELOC_NIOS2_LO16,
|
|||
|
+ BFD_RELOC_NIOS2_HIADJ16,
|
|||
|
+ BFD_RELOC_NIOS2_GPREL,
|
|||
|
+ BFD_RELOC_NIOS2_UJMP,
|
|||
|
+ BFD_RELOC_NIOS2_CJMP,
|
|||
|
+ BFD_RELOC_NIOS2_CALLR,
|
|||
|
+ BFD_RELOC_NIOS2_ALIGN,
|
|||
|
+
|
|||
|
/* 8 bit signed offset in (ix+d) or (iy+d). */
|
|||
|
BFD_RELOC_Z80_DISP8,
|
|||
|
|
|||
|
diff --git a/bfd/config.bfd b/bfd/config.bfd
|
|||
|
old mode 100755
|
|||
|
new mode 100644
|
|||
|
index 9b81db7..fa86103
|
|||
|
--- a/bfd/config.bfd
|
|||
|
+++ b/bfd/config.bfd
|
|||
|
@@ -88,6 +88,7 @@ m68*) targ_archs=bfd_m68k_arch ;;
|
|||
|
m88*) targ_archs=bfd_m88k_arch ;;
|
|||
|
maxq*) targ_archs=bfd_maxq_arch ;;
|
|||
|
mips*) targ_archs=bfd_mips_arch ;;
|
|||
|
+nios2*) targ_archs=bfd_nios2_arch ;;
|
|||
|
or32*) targ_archs=bfd_or32_arch ;;
|
|||
|
pdp11*) targ_archs=bfd_pdp11_arch ;;
|
|||
|
pj*) targ_archs="bfd_pj_arch bfd_i386_arch";;
|
|||
|
@@ -985,6 +986,21 @@ case "${targ}" in
|
|||
|
targ_underscore=yes
|
|||
|
;;
|
|||
|
|
|||
|
+ nios2eb-*-*)
|
|||
|
+ targ_defvec=bfd_elf32_bignios2_vec
|
|||
|
+ targ_selvecs=bfd_elf32_littlenios2_vec
|
|||
|
+ ;;
|
|||
|
+
|
|||
|
+ nios2el-*-*)
|
|||
|
+ targ_defvec=bfd_elf32_littlenios2_vec
|
|||
|
+ targ_selvecs=bfd_elf32_bignios2_vec
|
|||
|
+ ;;
|
|||
|
+
|
|||
|
+ nios2-*-*)
|
|||
|
+ targ_defvec=bfd_elf32_littlenios2_vec
|
|||
|
+ targ_selvecs=bfd_elf32_bignios2_vec
|
|||
|
+ ;;
|
|||
|
+
|
|||
|
openrisc-*-elf)
|
|||
|
targ_defvec=bfd_elf32_openrisc_vec
|
|||
|
;;
|
|||
|
diff --git a/bfd/configure b/bfd/configure
|
|||
|
index bc138ff..a64fef5 100755
|
|||
|
--- a/bfd/configure
|
|||
|
+++ b/bfd/configure
|
|||
|
@@ -10846,6 +10846,8 @@ do
|
|||
|
bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
|
|||
|
bfd_elf32_littlemips_vxworks_vec)
|
|||
|
tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
|
|||
|
+ bfd_elf32_littlenios2_vec) tb="$tb elf32-nios2.lo elf32.lo $elf" ;;
|
|||
|
+ bfd_elf32_bignios2_vec) tb="$tb elf32-nios2.lo elf32.lo $elf" ;;
|
|||
|
bfd_elf32_m32c_vec) tb="$tb elf32-m32c.lo elf32.lo $elf" ;;
|
|||
|
bfd_elf32_m32r_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
|
|||
|
bfd_elf32_m32rle_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
|
|||
|
diff --git a/bfd/configure.in b/bfd/configure.in
|
|||
|
index fa0d50f..eb1e5f6 100644
|
|||
|
--- a/bfd/configure.in
|
|||
|
+++ b/bfd/configure.in
|
|||
|
@@ -655,6 +655,8 @@ do
|
|||
|
bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
|
|||
|
bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
|
|||
|
bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
|
|||
|
+ bfd_elf32_littlenios2_vec) tb="$tb elf32-nios2.lo elf32.lo $elf" ;;
|
|||
|
+ bfd_elf32_bignios2_vec) tb="$tb elf32-nios2.lo elf32.lo $elf" ;;
|
|||
|
bfd_elf32_openrisc_vec) tb="$tb elf32-openrisc.lo elf32.lo $elf" ;;
|
|||
|
bfd_elf32_or32_big_vec) tb="$tb elf32-or32.lo elf32.lo $elf" ;;
|
|||
|
bfd_elf32_pj_vec) tb="$tb elf32-pj.lo elf32.lo $elf";;
|
|||
|
diff --git a/bfd/cpu-nios2.c b/bfd/cpu-nios2.c
|
|||
|
new file mode 100644
|
|||
|
index 0000000..c8f39c9
|
|||
|
--- /dev/null
|
|||
|
+++ b/bfd/cpu-nios2.c
|
|||
|
@@ -0,0 +1,70 @@
|
|||
|
+/* bfd back-end for Altera Nios II support
|
|||
|
+
|
|||
|
+ Copyright (C) 2003
|
|||
|
+ by Nigel Gray (ngray@altera.com).
|
|||
|
+
|
|||
|
+This file is part of BFD, the Binary File Descriptor library.
|
|||
|
+
|
|||
|
+This program is free software; you can redistribute it and/or modify
|
|||
|
+it under the terms of 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.
|
|||
|
+
|
|||
|
+This program 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 a copy of the GNU General Public License
|
|||
|
+along with this program; if not, write to the Free Software
|
|||
|
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+#include "bfd.h"
|
|||
|
+#include "sysdep.h"
|
|||
|
+#include "libbfd.h"
|
|||
|
+
|
|||
|
+static const bfd_arch_info_type *nios2_compatible
|
|||
|
+ (const bfd_arch_info_type *, const bfd_arch_info_type *);
|
|||
|
+
|
|||
|
+/* The default routine tests bits_per_word, which is wrong on mips as
|
|||
|
+ mips word size doesn't correlate with reloc size. */
|
|||
|
+
|
|||
|
+static const bfd_arch_info_type *
|
|||
|
+nios2_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
|
|||
|
+{
|
|||
|
+ if (a->arch != b->arch)
|
|||
|
+ return NULL;
|
|||
|
+
|
|||
|
+ /* Machine compatibility is checked in
|
|||
|
+ _bfd_mips_elf_merge_private_bfd_data. */
|
|||
|
+
|
|||
|
+ return a;
|
|||
|
+}
|
|||
|
+
|
|||
|
+#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \
|
|||
|
+ { \
|
|||
|
+ BITS_WORD, /* bits in a word */ \
|
|||
|
+ BITS_ADDR, /* bits in an address */ \
|
|||
|
+ 8, /* 8 bits in a byte */ \
|
|||
|
+ bfd_arch_nios2, \
|
|||
|
+ NUMBER, \
|
|||
|
+ "nios2", \
|
|||
|
+ PRINT, \
|
|||
|
+ 3, \
|
|||
|
+ DEFAULT, \
|
|||
|
+ nios2_compatible, \
|
|||
|
+ bfd_default_scan, \
|
|||
|
+ NEXT, \
|
|||
|
+ }
|
|||
|
+
|
|||
|
+#define NN(index) (&arch_info_struct[(index) + 1])
|
|||
|
+
|
|||
|
+static const bfd_arch_info_type arch_info_struct[] =
|
|||
|
+{
|
|||
|
+ N (32, 32, bfd_mach_nios2, "nios2", FALSE, 0),
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* There is only one architecture - but we give the default a machine number of 0
|
|||
|
+ so the linker can distinguish it */
|
|||
|
+const bfd_arch_info_type bfd_nios2_arch =
|
|||
|
+N (32, 32, 0, "nios2", TRUE, &arch_info_struct[0]);
|
|||
|
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
|
|||
|
new file mode 100644
|
|||
|
index 0000000..f9ba1a0
|
|||
|
--- /dev/null
|
|||
|
+++ b/bfd/elf32-nios2.c
|
|||
|
@@ -0,0 +1,2193 @@
|
|||
|
+/* New Jersey-specific support for 32-bit ELF
|
|||
|
+
|
|||
|
+ Copyright (C) 2003
|
|||
|
+ by Nigel Gray (ngray@altera.com).
|
|||
|
+
|
|||
|
+
|
|||
|
+This file is part of BFD, the Binary File Descriptor library.
|
|||
|
+
|
|||
|
+This program is free software; you can redistribute it and/or modify
|
|||
|
+it under the terms of 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.
|
|||
|
+
|
|||
|
+This program 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 a copy of the GNU General Public License
|
|||
|
+along with this program; if not, write to the Free Software
|
|||
|
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+/* This file handles Altera New Jersey ELF targets */
|
|||
|
+
|
|||
|
+#include "bfd.h"
|
|||
|
+#include "sysdep.h"
|
|||
|
+#include "libbfd.h"
|
|||
|
+#include "bfdlink.h"
|
|||
|
+#include "genlink.h"
|
|||
|
+#include "elf-bfd.h"
|
|||
|
+#include "elf/nios2.h"
|
|||
|
+#include "opcode/nios2.h"
|
|||
|
+
|
|||
|
+/* use RELA relocations*/
|
|||
|
+#ifndef USE_RELA
|
|||
|
+#define USE_RELA
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+#ifdef USE_REL
|
|||
|
+#undef USE_REL
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+/* Function prototypes */
|
|||
|
+
|
|||
|
+static reloc_howto_type *nios2_elf32_bfd_reloc_type_lookup
|
|||
|
+ (bfd *, bfd_reloc_code_real_type);
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf32_relax_section
|
|||
|
+ (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf32_relax_delete_bytes
|
|||
|
+ (bfd *, asection *, bfd_vma, int);
|
|||
|
+
|
|||
|
+static reloc_howto_type *nios2_elf32_rtype_to_howto
|
|||
|
+ (unsigned int r_type, bfd_boolean rela_p);
|
|||
|
+
|
|||
|
+static void nios2_elf32_info_to_howto
|
|||
|
+ (bfd * abfd, arelent * cache_ptr, Elf_Internal_Rela * dst);
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf32_relocate_section
|
|||
|
+ (bfd * output_bfd, struct bfd_link_info * info, bfd * input_bfd,
|
|||
|
+ asection * input_section, bfd_byte * contents,
|
|||
|
+ Elf_Internal_Rela * relocs, Elf_Internal_Sym * local_syms,
|
|||
|
+ asection ** local_sections);
|
|||
|
+
|
|||
|
+static reloc_howto_type *lookup_howto (unsigned int rtype);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf_final_gp
|
|||
|
+ (bfd *, asymbol *, bfd_boolean, char **, bfd_vma *,
|
|||
|
+ struct bfd_link_info *);
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf_assign_gp
|
|||
|
+ (bfd *, bfd_vma *, struct bfd_link_info *);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_ignore_reloc
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_hi16_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_lo16_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_hiadj16_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_pcrel16_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_call26_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_gprel_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_ujmp_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_cjmp_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_callr_relocate
|
|||
|
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_hi16_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_lo16_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_hiadj16_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_pcrel16_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_call26_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_gprel_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_ujmp_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_cjmp_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type nios2_elf32_do_callr_relocate
|
|||
|
+ (bfd *, reloc_howto_type *, asection *,
|
|||
|
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma);
|
|||
|
+
|
|||
|
+
|
|||
|
+static void nios2_elf32_post_process_headers
|
|||
|
+ (bfd *, struct bfd_link_info *);
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf32_section_from_shdr
|
|||
|
+ (bfd *, Elf_Internal_Shdr *, const char *name, int shindex);
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf32_section_flags
|
|||
|
+ (flagword *, const Elf_Internal_Shdr *);
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf32_fake_sections
|
|||
|
+ (bfd *, Elf_Internal_Shdr *, asection *);
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_elf32_check_relocs
|
|||
|
+ (bfd *, struct bfd_link_info *, asection *,
|
|||
|
+ const Elf_Internal_Rela *);
|
|||
|
+
|
|||
|
+static asection *nios2_elf32_gc_mark_hook (asection * sec,
|
|||
|
+ struct bfd_link_info *
|
|||
|
+ info,
|
|||
|
+ Elf_Internal_Rela * rel,
|
|||
|
+ struct elf_link_hash_entry
|
|||
|
+ * h,
|
|||
|
+ Elf_Internal_Sym * sym);
|
|||
|
+
|
|||
|
+
|
|||
|
+/* target vector */
|
|||
|
+extern const bfd_target bfd_elf32_littlenios2_vec;
|
|||
|
+extern const bfd_target bfd_elf32_bignios2_vec;
|
|||
|
+
|
|||
|
+/* The relocation table used for SHT_REL sections. */
|
|||
|
+
|
|||
|
+static reloc_howto_type elf_nios2_howto_table_rel[] = {
|
|||
|
+ /* No relocation. */
|
|||
|
+ HOWTO (R_NIOS2_NONE, /* type */
|
|||
|
+ 0, /* rightshift */
|
|||
|
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
|
|||
|
+ 0, /* bitsize */
|
|||
|
+ FALSE, /* pc_relative */
|
|||
|
+ 0, /* bitpos */
|
|||
|
+ complain_overflow_dont, /* complain_on_overflow */
|
|||
|
+ bfd_elf_generic_reloc, /* special_function */
|
|||
|
+ "R_NIOS2_NONE", /* name */
|
|||
|
+ FALSE, /* partial_inplace */
|
|||
|
+ 0, /* src_mask */
|
|||
|
+ 0, /* dst_mask */
|
|||
|
+ FALSE), /* pcrel_offset */
|
|||
|
+
|
|||
|
+ /* 16-bit signed immediate relocation */
|
|||
|
+ HOWTO (R_NIOS2_S16, /* type */
|
|||
|
+ 0, /* rightshift */
|
|||
|
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
|
|||
|
+ 16, /* bitsize */
|
|||
|
+ FALSE, /* pc_relative */
|
|||
|
+ 6, /* bitpos */
|
|||
|
+ complain_overflow_signed, /* complain on overflow */
|
|||
|
+ bfd_elf_generic_reloc, /* special function */
|
|||
|
+ "R_NIOS2_S16", /* name */
|
|||
|
+ FALSE, /* partial_inplace */
|
|||
|
+ 0x003fffc0, /* src_mask */
|
|||
|
+ 0x003fffc0, /* dest_mask */
|
|||
|
+ FALSE), /* pcrel_offset */
|
|||
|
+
|
|||
|
+ /* 16-bit unsigned immediate relocation */
|
|||
|
+ HOWTO (R_NIOS2_U16, /* type */
|
|||
|
+ 0, /* rightshift */
|
|||
|
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
|
|||
|
+ 16, /* bitsize */
|
|||
|
+ FALSE, /* pc_relative */
|
|||
|
+ 6, /* bitpos */
|
|||
|
+ complain_overflow_unsigned, /* complain on overflow */
|
|||
|
+ bfd_elf_generic_reloc, /* special function */
|
|||
|
+ "R_NIOS2_U16", /* name */
|
|||
|
+ FALSE, /* partial_inplace */
|
|||
|
+ 0x003fffc0, /* src_mask */
|
|||
|
+ 0x003fffc0, /* dest_mask */
|
|||
|
+ FALSE), /* pcrel_offset */
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_PCREL16, /* type */
|
|||
|
+ 0, /* rightshift */
|
|||
|
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
|
|||
|
+ 16, /* bitsize */
|
|||
|
+ TRUE, /* pc_relative */
|
|||
|
+ 6, /* bitpos */
|
|||
|
+ complain_overflow_signed, /* complain on overflow */
|
|||
|
+ nios2_elf32_pcrel16_relocate, /* special function */
|
|||
|
+ "R_NIOS2_PCREL16", /* name */
|
|||
|
+ FALSE, /* partial_inplace */
|
|||
|
+ 0x003fffc0, /* src_mask */
|
|||
|
+ 0x003fffc0, /* dest_mask */
|
|||
|
+ TRUE), /* pcrel_offset */
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_CALL26, /* type */
|
|||
|
+ 2, /* rightshift */
|
|||
|
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
|
|||
|
+ 26, /* bitsize */
|
|||
|
+ FALSE, /* pc_relative */
|
|||
|
+ 6, /* bitpos */
|
|||
|
+ complain_overflow_dont, /* complain on overflow */
|
|||
|
+ nios2_elf32_call26_relocate, /* special function */
|
|||
|
+ "R_NIOS2_CALL26", /* name */
|
|||
|
+ FALSE, /* partial_inplace */
|
|||
|
+ 0xffffffc0, /* src_mask */
|
|||
|
+ 0xffffffc0, /* dst_mask */
|
|||
|
+ FALSE), /* pcrel_offset */
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_IMM5,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 5,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_bitfield,
|
|||
|
+ bfd_elf_generic_reloc,
|
|||
|
+ "R_NIOS2_IMM5",
|
|||
|
+ FALSE,
|
|||
|
+ 0x000007c0,
|
|||
|
+ 0x000007c0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_CACHE_OPX,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 5,
|
|||
|
+ FALSE,
|
|||
|
+ 22,
|
|||
|
+ complain_overflow_bitfield,
|
|||
|
+ bfd_elf_generic_reloc,
|
|||
|
+ "R_NIOS2_CACHE_OPX",
|
|||
|
+ FALSE,
|
|||
|
+ 0x07c00000,
|
|||
|
+ 0x07c00000,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_IMM6,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 6,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_bitfield,
|
|||
|
+ bfd_elf_generic_reloc,
|
|||
|
+ "R_NIOS2_IMM6",
|
|||
|
+ FALSE,
|
|||
|
+ 0x00000fc0,
|
|||
|
+ 0x00000fc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_IMM8,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 8,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_bitfield,
|
|||
|
+ bfd_elf_generic_reloc,
|
|||
|
+ "R_NIOS2_IMM8",
|
|||
|
+ FALSE,
|
|||
|
+ 0x00003fc0,
|
|||
|
+ 0x00003fc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_HI16,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_hi16_relocate,
|
|||
|
+ "R_NIOS2_HI16",
|
|||
|
+ FALSE,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_LO16,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_lo16_relocate,
|
|||
|
+ "R_NIOS2_LO16",
|
|||
|
+ FALSE,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_HIADJ16,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_hiadj16_relocate,
|
|||
|
+ "R_NIOS2_HIADJ16",
|
|||
|
+ FALSE,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_BFD_RELOC_32,
|
|||
|
+ 0,
|
|||
|
+ 2, /* long */
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ bfd_elf_generic_reloc,
|
|||
|
+ "R_NIOS2_BFD_RELOC32",
|
|||
|
+ FALSE,
|
|||
|
+ 0xffffffff,
|
|||
|
+ 0xffffffff,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_BFD_RELOC_16,
|
|||
|
+ 0,
|
|||
|
+ 1, /* short */
|
|||
|
+ 16,
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ complain_overflow_bitfield,
|
|||
|
+ bfd_elf_generic_reloc,
|
|||
|
+ "R_NIOS2_BFD_RELOC16",
|
|||
|
+ FALSE,
|
|||
|
+ 0x0000ffff,
|
|||
|
+ 0x0000ffff,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_BFD_RELOC_8,
|
|||
|
+ 0,
|
|||
|
+ 0, /* byte */
|
|||
|
+ 8,
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ complain_overflow_bitfield,
|
|||
|
+ bfd_elf_generic_reloc,
|
|||
|
+ "R_NIOS2_BFD_RELOC8",
|
|||
|
+ FALSE,
|
|||
|
+ 0x000000ff,
|
|||
|
+ 0x000000ff,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_GPREL,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_gprel_relocate,
|
|||
|
+ "R_NIOS2_GPREL",
|
|||
|
+ FALSE,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_GNU_VTINHERIT,
|
|||
|
+ 0,
|
|||
|
+ 2, /* short */
|
|||
|
+ 0,
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ NULL,
|
|||
|
+ "R_NIOS2_GNU_VTINHERIT",
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ 0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_GNU_VTENTRY,
|
|||
|
+ 0,
|
|||
|
+ 2, /* byte */
|
|||
|
+ 0,
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ _bfd_elf_rel_vtable_reloc_fn,
|
|||
|
+ "R_NIOS2_GNU_VTENTRY",
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ 0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_UJMP,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_ujmp_relocate,
|
|||
|
+ "R_NIOS2_UJMP",
|
|||
|
+ FALSE,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_CJMP,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_cjmp_relocate,
|
|||
|
+ "R_NIOS2_CJMP",
|
|||
|
+ FALSE,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_CALLR,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 32,
|
|||
|
+ FALSE,
|
|||
|
+ 6,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_callr_relocate,
|
|||
|
+ "R_NIOS2_CALLR",
|
|||
|
+ FALSE,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ 0x003fffc0,
|
|||
|
+ FALSE),
|
|||
|
+
|
|||
|
+ HOWTO (R_NIOS2_ALIGN,
|
|||
|
+ 0,
|
|||
|
+ 2,
|
|||
|
+ 0,
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ complain_overflow_dont,
|
|||
|
+ nios2_elf32_ignore_reloc,
|
|||
|
+ "R_NIOS2_ALIGN",
|
|||
|
+ FALSE,
|
|||
|
+ 0,
|
|||
|
+ 0,
|
|||
|
+ TRUE),
|
|||
|
+
|
|||
|
+/* add other relocations here */
|
|||
|
+};
|
|||
|
+
|
|||
|
+static unsigned char elf_code_to_howto_index[R_NIOS2_ILLEGAL + 1];
|
|||
|
+
|
|||
|
+static reloc_howto_type *
|
|||
|
+lookup_howto (unsigned int rtype)
|
|||
|
+{
|
|||
|
+ static int initialized = 0;
|
|||
|
+ int i;
|
|||
|
+ int howto_tbl_size = (int) (sizeof (elf_nios2_howto_table_rel)
|
|||
|
+ / sizeof (elf_nios2_howto_table_rel[0]));
|
|||
|
+
|
|||
|
+ if (!initialized)
|
|||
|
+ {
|
|||
|
+ initialized = 1;
|
|||
|
+ memset (elf_code_to_howto_index, 0xff,
|
|||
|
+ sizeof (elf_code_to_howto_index));
|
|||
|
+ for (i = 0; i < howto_tbl_size; i++)
|
|||
|
+ elf_code_to_howto_index[elf_nios2_howto_table_rel[i].type] = i;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ BFD_ASSERT (rtype <= R_NIOS2_ILLEGAL);
|
|||
|
+ i = elf_code_to_howto_index[rtype];
|
|||
|
+ if (i >= howto_tbl_size)
|
|||
|
+ return 0;
|
|||
|
+ return elf_nios2_howto_table_rel + i;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ map for converting BFD reloc types to New Jersey
|
|||
|
+ reloc types
|
|||
|
+ */
|
|||
|
+struct elf_reloc_map
|
|||
|
+{
|
|||
|
+ bfd_reloc_code_real_type bfd_val;
|
|||
|
+ enum elf_nios2_reloc_type elf_val;
|
|||
|
+};
|
|||
|
+
|
|||
|
+static const struct elf_reloc_map nios2_reloc_map[] = {
|
|||
|
+ {BFD_RELOC_NIOS2_S16, R_NIOS2_S16},
|
|||
|
+ {BFD_RELOC_NIOS2_U16, R_NIOS2_U16},
|
|||
|
+ {BFD_RELOC_16_PCREL, R_NIOS2_PCREL16},
|
|||
|
+ {BFD_RELOC_NIOS2_CALL26, R_NIOS2_CALL26},
|
|||
|
+ {BFD_RELOC_NIOS2_IMM5, R_NIOS2_IMM5},
|
|||
|
+ {BFD_RELOC_NIOS2_CACHE_OPX, R_NIOS2_CACHE_OPX},
|
|||
|
+ {BFD_RELOC_NIOS2_IMM6, R_NIOS2_IMM6},
|
|||
|
+ {BFD_RELOC_NIOS2_IMM8, R_NIOS2_IMM8},
|
|||
|
+ {BFD_RELOC_NIOS2_HI16, R_NIOS2_HI16},
|
|||
|
+ {BFD_RELOC_NIOS2_LO16, R_NIOS2_LO16},
|
|||
|
+ {BFD_RELOC_NIOS2_HIADJ16, R_NIOS2_HIADJ16},
|
|||
|
+ {BFD_RELOC_32, R_NIOS2_BFD_RELOC_32},
|
|||
|
+ {BFD_RELOC_16, R_NIOS2_BFD_RELOC_16},
|
|||
|
+ {BFD_RELOC_8, R_NIOS2_BFD_RELOC_8},
|
|||
|
+ {BFD_RELOC_NIOS2_GPREL, R_NIOS2_GPREL},
|
|||
|
+ {BFD_RELOC_VTABLE_INHERIT, R_NIOS2_GNU_VTINHERIT},
|
|||
|
+ {BFD_RELOC_VTABLE_ENTRY, R_NIOS2_GNU_VTENTRY},
|
|||
|
+ {BFD_RELOC_NIOS2_UJMP, R_NIOS2_UJMP},
|
|||
|
+ {BFD_RELOC_NIOS2_CJMP, R_NIOS2_CJMP},
|
|||
|
+ {BFD_RELOC_NIOS2_CALLR, R_NIOS2_CALLR},
|
|||
|
+ {BFD_RELOC_NIOS2_ALIGN, R_NIOS2_ALIGN},
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Given a BFD reloc type, return a howto structure. */
|
|||
|
+
|
|||
|
+static reloc_howto_type *
|
|||
|
+nios2_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
|
|||
|
+ bfd_reloc_code_real_type code)
|
|||
|
+{
|
|||
|
+ int i;
|
|||
|
+ for (i = 0;
|
|||
|
+ i < (int) (sizeof (nios2_reloc_map) / sizeof (struct elf_reloc_map));
|
|||
|
+ ++i)
|
|||
|
+ {
|
|||
|
+ if (nios2_reloc_map[i].bfd_val == code)
|
|||
|
+ return &elf_nios2_howto_table_rel[(int) nios2_reloc_map[i].elf_val];
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return NULL;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Helper function for nios2_elf32_info_to_howto */
|
|||
|
+
|
|||
|
+static reloc_howto_type *
|
|||
|
+nios2_elf32_rtype_to_howto (unsigned int r_type,
|
|||
|
+ bfd_boolean rela_p ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+ BFD_ASSERT (r_type < R_NIOS2_ILLEGAL);
|
|||
|
+ return &elf_nios2_howto_table_rel[r_type];
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Given a ELF32 relocation, fill in a arelent structure */
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_elf32_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * cache_ptr,
|
|||
|
+ Elf_Internal_Rela * dst)
|
|||
|
+{
|
|||
|
+ unsigned int r_type;
|
|||
|
+
|
|||
|
+ r_type = ELF32_R_TYPE (dst->r_info);
|
|||
|
+ cache_ptr->howto = nios2_elf32_rtype_to_howto (r_type, FALSE);
|
|||
|
+
|
|||
|
+ // FIXME - do we need to do anything else here???
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* The assembler has output long jmp/call sequences for all calls
|
|||
|
+ * and pc-relative branches that it cannot guarantee are within
|
|||
|
+ * range, so the linker must attempt to "relax" these sequences to
|
|||
|
+ * short branches and calls if it can. Since we only relax in one
|
|||
|
+ * direction - long to short - we don't need to see whether each
|
|||
|
+ * relaxation invalidates any others
|
|||
|
+ *
|
|||
|
+ *
|
|||
|
+ **/
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf32_relax_section (bfd * abfd,
|
|||
|
+ asection * sec,
|
|||
|
+ struct bfd_link_info *link_info, bfd_boolean * again)
|
|||
|
+{
|
|||
|
+ Elf_Internal_Shdr *symtab_hdr;
|
|||
|
+ Elf_Internal_Rela *internal_relocs;
|
|||
|
+ Elf_Internal_Rela *irel, *irelend;
|
|||
|
+ bfd_byte *contents = NULL;
|
|||
|
+ Elf_Internal_Sym *isymbuf = NULL;
|
|||
|
+
|
|||
|
+ /* Assume nothing changes. */
|
|||
|
+ *again = FALSE;
|
|||
|
+
|
|||
|
+ /* We don't have to do anything for a relocatable link, if
|
|||
|
+ this section does not have relocs, or if this is not a
|
|||
|
+ code section. */
|
|||
|
+ if (link_info->relocatable
|
|||
|
+ || (sec->flags & SEC_RELOC) == 0
|
|||
|
+ || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
|
|||
|
+ return TRUE;
|
|||
|
+
|
|||
|
+ /* If this is the first time we have been called for this section,
|
|||
|
+ initialize the cooked size. */
|
|||
|
+ if (sec->size == 0)
|
|||
|
+ sec->size = sec->rawsize;
|
|||
|
+
|
|||
|
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
|||
|
+
|
|||
|
+ /* Get a copy of the native relocations. */
|
|||
|
+ internal_relocs = (_bfd_elf_link_read_relocs
|
|||
|
+ (abfd, sec, (void *) NULL, (Elf_Internal_Rela *) NULL,
|
|||
|
+ link_info->keep_memory));
|
|||
|
+ if (internal_relocs == NULL)
|
|||
|
+ goto error_return;
|
|||
|
+
|
|||
|
+ /* Walk through them looking for relaxing opportunities. */
|
|||
|
+ irelend = internal_relocs + sec->reloc_count;
|
|||
|
+ for (irel = internal_relocs; irel < irelend; irel++)
|
|||
|
+ {
|
|||
|
+ bfd_vma symval;
|
|||
|
+
|
|||
|
+ /* If this isn't something that can be relaxed, then ignore
|
|||
|
+ this reloc. */
|
|||
|
+ if (ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_UJMP
|
|||
|
+ && ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_CJMP
|
|||
|
+ && ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_CALLR)
|
|||
|
+ {
|
|||
|
+ continue;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Get the section contents if we haven't done so already. */
|
|||
|
+ if (contents == NULL)
|
|||
|
+ {
|
|||
|
+ /* Get cached copy if it exists. */
|
|||
|
+ if (elf_section_data (sec)->this_hdr.contents != NULL)
|
|||
|
+ contents = elf_section_data (sec)->this_hdr.contents;
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ /* Go get them off disk. */
|
|||
|
+ contents = (bfd_byte *) bfd_malloc (sec->rawsize);
|
|||
|
+ if (contents == NULL)
|
|||
|
+ goto error_return;
|
|||
|
+
|
|||
|
+ if (!bfd_get_section_contents (abfd, sec, contents,
|
|||
|
+ (file_ptr) 0, sec->rawsize))
|
|||
|
+ goto error_return;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Read this BFD's local symbols if we haven't done so already. */
|
|||
|
+ if (isymbuf == NULL && symtab_hdr->sh_info != 0)
|
|||
|
+ {
|
|||
|
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
|
|||
|
+ if (isymbuf == NULL)
|
|||
|
+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
|
|||
|
+ symtab_hdr->sh_info, 0,
|
|||
|
+ NULL, NULL, NULL);
|
|||
|
+ if (isymbuf == NULL)
|
|||
|
+ goto error_return;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Get the value of the symbol referred to by the reloc. */
|
|||
|
+ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
|
|||
|
+ {
|
|||
|
+ /* A local symbol. */
|
|||
|
+ Elf_Internal_Sym *isym;
|
|||
|
+ asection *sym_sec;
|
|||
|
+
|
|||
|
+ isym = isymbuf + ELF32_R_SYM (irel->r_info);
|
|||
|
+ if (isym->st_shndx == SHN_UNDEF)
|
|||
|
+ sym_sec = bfd_und_section_ptr;
|
|||
|
+ else if (isym->st_shndx == SHN_ABS)
|
|||
|
+ sym_sec = bfd_abs_section_ptr;
|
|||
|
+ else if (isym->st_shndx == SHN_COMMON)
|
|||
|
+ sym_sec = bfd_com_section_ptr;
|
|||
|
+ else
|
|||
|
+ sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
|
|||
|
+ symval = (isym->st_value
|
|||
|
+ + sym_sec->output_section->vma + sym_sec->output_offset);
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ unsigned long indx;
|
|||
|
+ struct elf_link_hash_entry *h;
|
|||
|
+
|
|||
|
+ /* An external symbol. */
|
|||
|
+ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
|
|||
|
+ h = elf_sym_hashes (abfd)[indx];
|
|||
|
+ BFD_ASSERT (h != NULL);
|
|||
|
+ if (h->root.type != bfd_link_hash_defined
|
|||
|
+ && h->root.type != bfd_link_hash_defweak)
|
|||
|
+ {
|
|||
|
+ /* This appears to be a reference to an undefined
|
|||
|
+ symbol. Just ignore it--it will be caught by the
|
|||
|
+ regular reloc processing. */
|
|||
|
+ continue;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ symval = (h->root.u.def.value
|
|||
|
+ + h->root.u.def.section->output_section->vma
|
|||
|
+ + h->root.u.def.section->output_offset);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* For simplicity of coding, we are going to modify the section
|
|||
|
+ contents, the section relocs, and the BFD symbol table. We
|
|||
|
+ must tell the rest of the code not to free up this
|
|||
|
+ information. It would be possible to instead create a table
|
|||
|
+ of changes which have to be made, as is done in coff-mips.c;
|
|||
|
+ that would be more work, but would require less memory when
|
|||
|
+ the linker is run. */
|
|||
|
+
|
|||
|
+ /* try to turn :
|
|||
|
+ * movhi at, %hi(symbol)
|
|||
|
+ * movui at, %lo(symbol)
|
|||
|
+ * callr at
|
|||
|
+ * into:
|
|||
|
+ * call symbol
|
|||
|
+ */
|
|||
|
+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_CALLR)
|
|||
|
+ {
|
|||
|
+ bfd_vma targ_addr = symval + irel->r_addend;
|
|||
|
+ bfd_vma curr_addr = (sec->output_section->vma + sec->output_offset);
|
|||
|
+ bfd_vma targ_page, curr_page;
|
|||
|
+ targ_page = targ_addr & 0xf0000000;
|
|||
|
+ curr_page = curr_addr & 0xf0000000;
|
|||
|
+
|
|||
|
+ if (targ_page == curr_page)
|
|||
|
+ {
|
|||
|
+ /* change the opcode to a call */
|
|||
|
+ bfd_put_32 (abfd, OP_MATCH_CALL, contents + irel->r_offset);
|
|||
|
+ /* Note that we've changed the relocs, section contents, etc. */
|
|||
|
+ elf_section_data (sec)->relocs = internal_relocs;
|
|||
|
+ elf_section_data (sec)->this_hdr.contents = contents;
|
|||
|
+ symtab_hdr->contents = (unsigned char *) isymbuf;
|
|||
|
+
|
|||
|
+ /* Fix the relocation's type. */
|
|||
|
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
|||
|
+ R_NIOS2_CALL26);
|
|||
|
+
|
|||
|
+ /* delete the next two instructions */
|
|||
|
+ if (!nios2_elf32_relax_delete_bytes (abfd, sec,
|
|||
|
+ irel->r_offset + 4, 8))
|
|||
|
+ goto error_return;
|
|||
|
+
|
|||
|
+ /* NG FIXME - I'm putting this in for now, but I don't think we need it */
|
|||
|
+ *again = TRUE;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* try to turn :
|
|||
|
+ * movhi at, %hi(symbol)
|
|||
|
+ * movui at, %lo(symbol)
|
|||
|
+ * jmp at
|
|||
|
+ * into:
|
|||
|
+ * br symbol
|
|||
|
+ */
|
|||
|
+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_UJMP)
|
|||
|
+ {
|
|||
|
+ bfd_vma pcrel_offset;
|
|||
|
+ Elf_Internal_Rela *irelalign = NULL;
|
|||
|
+ Elf_Internal_Rela *irela = elf_section_data (sec)->relocs;
|
|||
|
+ Elf_Internal_Rela *irelend = irel + sec->reloc_count;
|
|||
|
+
|
|||
|
+ for (; irela < irelend; irela++)
|
|||
|
+ {
|
|||
|
+ if (ELF32_R_TYPE (irela->r_info) == (int) R_NIOS2_ALIGN
|
|||
|
+ && irela->r_offset > irel->r_offset + 4
|
|||
|
+ && 8 < (1 << irela->r_addend))
|
|||
|
+ {
|
|||
|
+ irelalign = irela;
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* calculate the pcrelative offset from current location */
|
|||
|
+ pcrel_offset = symval;
|
|||
|
+ pcrel_offset -= (sec->output_section->vma + sec->output_offset);
|
|||
|
+ pcrel_offset += irel->r_addend;
|
|||
|
+
|
|||
|
+ /* we need to compute the pcrel_offset from the next instruction */
|
|||
|
+ pcrel_offset -= (irel->r_offset + 4);
|
|||
|
+
|
|||
|
+ /* does this value fit in 16 bits */
|
|||
|
+ if ((irelalign == NULL && (long) pcrel_offset <= 0x8004
|
|||
|
+ && (long) pcrel_offset >= -0x8000) || (irelalign != NULL
|
|||
|
+ && (long) pcrel_offset
|
|||
|
+ <= 0x7ffc
|
|||
|
+ && (long) pcrel_offset
|
|||
|
+ >= -0x8000))
|
|||
|
+ {
|
|||
|
+ /* change the opcode to an unconditional branch */
|
|||
|
+ bfd_put_32 (abfd, OP_MATCH_BR, contents + irel->r_offset);
|
|||
|
+ /* Note that we've changed the relocs, section contents, etc. */
|
|||
|
+ elf_section_data (sec)->relocs = internal_relocs;
|
|||
|
+ elf_section_data (sec)->this_hdr.contents = contents;
|
|||
|
+ symtab_hdr->contents = (unsigned char *) isymbuf;
|
|||
|
+
|
|||
|
+ /* Fix the relocation's type. */
|
|||
|
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
|||
|
+ R_NIOS2_PCREL16);
|
|||
|
+
|
|||
|
+ /* delete the next two instructions */
|
|||
|
+ if (!nios2_elf32_relax_delete_bytes (abfd, sec,
|
|||
|
+ irel->r_offset + 4, 8))
|
|||
|
+ goto error_return;
|
|||
|
+
|
|||
|
+ /* NG FIXME - I'm putting this in for now, but I don't think we need it */
|
|||
|
+ *again = TRUE;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* try to turn :
|
|||
|
+ * b{cond} a, b skip
|
|||
|
+ * movhi at, %hi(symbol)
|
|||
|
+ * movui at, %lo(symbol)
|
|||
|
+ * jmp at
|
|||
|
+ * skip:
|
|||
|
+ * ...
|
|||
|
+ * into:
|
|||
|
+ * br{opp_cond} a, b, symbol
|
|||
|
+ */
|
|||
|
+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_CJMP)
|
|||
|
+ {
|
|||
|
+ bfd_vma pcrel_offset;
|
|||
|
+ Elf_Internal_Rela *irelalign = NULL;
|
|||
|
+ Elf_Internal_Rela *irela = elf_section_data (sec)->relocs;
|
|||
|
+ Elf_Internal_Rela *irelend = irel + sec->reloc_count;
|
|||
|
+
|
|||
|
+ for (; irela < irelend; irela++)
|
|||
|
+ {
|
|||
|
+ if (ELF32_R_TYPE (irela->r_info) == (int) R_NIOS2_ALIGN
|
|||
|
+ && irela->r_offset > irel->r_offset + 4
|
|||
|
+ && 8 < (1 << irela->r_addend))
|
|||
|
+ {
|
|||
|
+ irelalign = irela;
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* calculate the pcrelative offset from current location */
|
|||
|
+ pcrel_offset = symval;
|
|||
|
+ pcrel_offset -= (sec->output_section->vma + sec->output_offset);
|
|||
|
+ pcrel_offset += irel->r_addend;
|
|||
|
+
|
|||
|
+ /* we need to compute the pcrel_offset from this instruction
|
|||
|
+ * ie the movhi */
|
|||
|
+ pcrel_offset -= (irel->r_offset);
|
|||
|
+
|
|||
|
+ /* does this value fit in 16 bits */
|
|||
|
+ if ((irelalign == NULL && (long) pcrel_offset <= 0x8008
|
|||
|
+ && (long) pcrel_offset >= -0x8000) || (irelalign != NULL
|
|||
|
+ && (long) pcrel_offset
|
|||
|
+ <= 0x7ffc
|
|||
|
+ && (long) pcrel_offset
|
|||
|
+ >= -0x8000))
|
|||
|
+ {
|
|||
|
+ unsigned long opcode, op_a, op_b;
|
|||
|
+ /* get the conditional branch opcode */
|
|||
|
+ opcode = bfd_get_32 (abfd, contents + irel->r_offset - 4);
|
|||
|
+ /* reverse the condition */
|
|||
|
+ switch (opcode & OP_MASK_OP)
|
|||
|
+ {
|
|||
|
+ case OP_MATCH_BEQ:
|
|||
|
+ opcode = (opcode & ~OP_MASK_OP) | OP_MATCH_BNE;
|
|||
|
+ break;
|
|||
|
+ case OP_MATCH_BNE:
|
|||
|
+ opcode = (opcode & ~OP_MASK_OP) | OP_MATCH_BEQ;
|
|||
|
+ break;
|
|||
|
+ case OP_MATCH_BGE:
|
|||
|
+ case OP_MATCH_BGEU:
|
|||
|
+ case OP_MATCH_BLT:
|
|||
|
+ case OP_MATCH_BLTU:
|
|||
|
+ /* swap the operands */
|
|||
|
+ op_a = (opcode & OP_MASK_RRT) << 5;
|
|||
|
+ op_b = (opcode & OP_MASK_RRS) >> 5;
|
|||
|
+ opcode =
|
|||
|
+ (opcode & ~(OP_MASK_RRS | OP_MASK_RRT)) | op_a | op_b;
|
|||
|
+ break;
|
|||
|
+ default:
|
|||
|
+ fprintf (stderr,
|
|||
|
+ "relaxation error - expecting conditional branch, aborting\n");
|
|||
|
+ abort ();
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* we must set the branch target to zero so that the skip over the jmp doesn't get
|
|||
|
+ * added to the jmp */
|
|||
|
+ opcode = opcode & (~OP_MASK_IMM16);
|
|||
|
+
|
|||
|
+ /* change the opcode to the reversed conditional branch */
|
|||
|
+ bfd_put_32 (abfd, opcode, contents + irel->r_offset - 4);
|
|||
|
+ /* Note that we've changed the relocs, section contents, etc. */
|
|||
|
+ elf_section_data (sec)->relocs = internal_relocs;
|
|||
|
+ elf_section_data (sec)->this_hdr.contents = contents;
|
|||
|
+ symtab_hdr->contents = (unsigned char *) isymbuf;
|
|||
|
+
|
|||
|
+ /* Fix the relocation's type. */
|
|||
|
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
|||
|
+ R_NIOS2_PCREL16);
|
|||
|
+
|
|||
|
+ /* this relocation's offset has also been reduced by 4 bytes */
|
|||
|
+ irel->r_offset -= 4;
|
|||
|
+
|
|||
|
+ /* delete the next three instructions */
|
|||
|
+ if (!nios2_elf32_relax_delete_bytes (abfd, sec,
|
|||
|
+ irel->r_offset + 4, 12))
|
|||
|
+ goto error_return;
|
|||
|
+
|
|||
|
+ /* NG FIXME - I'm putting this in for now, but I don't think we need it */
|
|||
|
+ *again = TRUE;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* otherwise, leave alone */
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
|
|||
|
+ {
|
|||
|
+ if (!link_info->keep_memory)
|
|||
|
+ free (isymbuf);
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ /* Cache the symbols for elf_link_input_bfd. */
|
|||
|
+ symtab_hdr->contents = (unsigned char *) isymbuf;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (contents != NULL
|
|||
|
+ && elf_section_data (sec)->this_hdr.contents != contents)
|
|||
|
+ {
|
|||
|
+ if (!link_info->keep_memory)
|
|||
|
+ free (contents);
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ /* Cache the section contents for elf_link_input_bfd. */
|
|||
|
+ elf_section_data (sec)->this_hdr.contents = contents;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (internal_relocs != NULL
|
|||
|
+ && elf_section_data (sec)->relocs != internal_relocs)
|
|||
|
+ free (internal_relocs);
|
|||
|
+
|
|||
|
+
|
|||
|
+ return TRUE;
|
|||
|
+
|
|||
|
+error_return:
|
|||
|
+ if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
|
|||
|
+ free (isymbuf);
|
|||
|
+ if (contents != NULL
|
|||
|
+ && elf_section_data (sec)->this_hdr.contents != contents)
|
|||
|
+ free (contents);
|
|||
|
+ if (internal_relocs != NULL
|
|||
|
+ && elf_section_data (sec)->relocs != internal_relocs)
|
|||
|
+ free (internal_relocs);
|
|||
|
+
|
|||
|
+ return FALSE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Delete some bytes from a section while relaxing.
|
|||
|
+ * Copied from mn10200 port */
|
|||
|
+
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf32_relax_delete_bytes (bfd * abfd,
|
|||
|
+ asection * sec, bfd_vma addr, int count)
|
|||
|
+{
|
|||
|
+ Elf_Internal_Shdr *symtab_hdr;
|
|||
|
+ unsigned int sec_shndx;
|
|||
|
+ bfd_byte *contents;
|
|||
|
+ Elf_Internal_Rela *irel, *irelend;
|
|||
|
+ Elf_Internal_Rela *irelalign;
|
|||
|
+ bfd_vma toaddr;
|
|||
|
+ Elf_Internal_Sym *isym;
|
|||
|
+ Elf_Internal_Sym *isymend;
|
|||
|
+ struct elf_link_hash_entry **sym_hashes;
|
|||
|
+ struct elf_link_hash_entry **end_hashes;
|
|||
|
+ unsigned int symcount;
|
|||
|
+ asection *asec;
|
|||
|
+
|
|||
|
+ sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
|
|||
|
+
|
|||
|
+ contents = elf_section_data (sec)->this_hdr.contents;
|
|||
|
+
|
|||
|
+ /* The deletion must stop at the next ALIGN reloc for an aligment
|
|||
|
+ power larger than the number of bytes we are deleting. */
|
|||
|
+
|
|||
|
+ irelalign = NULL;
|
|||
|
+ /* +1 because we need to readjust symbols at end of section */
|
|||
|
+ toaddr = sec->size + 1;
|
|||
|
+
|
|||
|
+ irel = elf_section_data (sec)->relocs;
|
|||
|
+ irelend = irel + sec->reloc_count;
|
|||
|
+
|
|||
|
+ for (; irel < irelend; irel++)
|
|||
|
+ {
|
|||
|
+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_ALIGN
|
|||
|
+ && irel->r_offset > addr && count < (1 << irel->r_addend))
|
|||
|
+ {
|
|||
|
+ irelalign = irel;
|
|||
|
+ /* +1 because we need to readjust symbols at end of section */
|
|||
|
+ toaddr = irel->r_offset + 1;
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+
|
|||
|
+ /* Actually delete the bytes. */
|
|||
|
+ memmove (contents + addr, contents + addr + count,
|
|||
|
+ (size_t) ((toaddr - 1) - addr - count));
|
|||
|
+
|
|||
|
+ if (irelalign == NULL)
|
|||
|
+ sec->size -= count;
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ int i;
|
|||
|
+
|
|||
|
+#define NOP_OPCODE (0x0001883a)
|
|||
|
+
|
|||
|
+ BFD_ASSERT ((count & 3) == 0);
|
|||
|
+ for (i = 0; i < count; i += 4)
|
|||
|
+ bfd_put_32 (abfd, (bfd_vma) NOP_OPCODE,
|
|||
|
+ contents + (toaddr - 1) - count + i);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* get the symbol table */
|
|||
|
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
|||
|
+ isym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
|||
|
+
|
|||
|
+ /* Adjust all the reloc offsets in this section. */
|
|||
|
+ for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
|
|||
|
+ {
|
|||
|
+ /* Get the new reloc address. */
|
|||
|
+ if ((irel->r_offset > addr && irel->r_offset < toaddr))
|
|||
|
+ irel->r_offset -= count;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Adjust relocations against targets in this section whose positions
|
|||
|
+ * have moved as a result of the relaxation */
|
|||
|
+
|
|||
|
+ for (asec = abfd->sections; asec; asec = asec->next)
|
|||
|
+ {
|
|||
|
+ irelend = elf_section_data (asec)->relocs + asec->reloc_count;
|
|||
|
+ for (irel = elf_section_data (asec)->relocs; irel < irelend; irel++)
|
|||
|
+ {
|
|||
|
+ Elf_Internal_Sym *sym;
|
|||
|
+ /* if the symbol which this reloc is against doesn't change
|
|||
|
+ * we need to change the reloc addend */
|
|||
|
+
|
|||
|
+ sym = isym + ELF32_R_SYM (irel->r_info);
|
|||
|
+ if (sym->st_shndx == sec_shndx
|
|||
|
+ && !(sym->st_value > addr && sym->st_value < toaddr)
|
|||
|
+ && sym->st_value + irel->r_addend > addr
|
|||
|
+ && sym->st_value + irel->r_addend < toaddr)
|
|||
|
+ {
|
|||
|
+ irel->r_addend -= count;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Adjust the local symbols defined in this section. */
|
|||
|
+ for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
|
|||
|
+ {
|
|||
|
+ if (isym->st_shndx == sec_shndx
|
|||
|
+ && isym->st_value > addr && isym->st_value < toaddr)
|
|||
|
+ isym->st_value -= count;
|
|||
|
+
|
|||
|
+
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Now adjust the global symbols defined in this section. */
|
|||
|
+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
|
|||
|
+ - symtab_hdr->sh_info);
|
|||
|
+ sym_hashes = elf_sym_hashes (abfd);
|
|||
|
+ end_hashes = sym_hashes + symcount;
|
|||
|
+ for (; sym_hashes < end_hashes; sym_hashes++)
|
|||
|
+ {
|
|||
|
+ struct elf_link_hash_entry *sym_hash = *sym_hashes;
|
|||
|
+ if ((sym_hash->root.type == bfd_link_hash_defined
|
|||
|
+ || sym_hash->root.type == bfd_link_hash_defweak)
|
|||
|
+ && sym_hash->root.u.def.section == sec
|
|||
|
+ && sym_hash->root.u.def.value > addr
|
|||
|
+ && sym_hash->root.u.def.value < toaddr)
|
|||
|
+ {
|
|||
|
+ sym_hash->root.u.def.value -= count;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return TRUE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+struct bfd_link_info *nios2_link_info = NULL;
|
|||
|
+
|
|||
|
+/*
|
|||
|
+void
|
|||
|
+_bfd_set_link_info (info)
|
|||
|
+ struct bfd_link_info *info;
|
|||
|
+{
|
|||
|
+ nios2_link_info = info;
|
|||
|
+}
|
|||
|
+*/
|
|||
|
+
|
|||
|
+bfd_boolean linker_force_make_executable = FALSE;
|
|||
|
+
|
|||
|
+/*
|
|||
|
+void
|
|||
|
+_bfd_set_force_make_executable (force)
|
|||
|
+ bfd_boolean force;
|
|||
|
+{
|
|||
|
+ linker_force_make_executable = force;
|
|||
|
+}
|
|||
|
+*/
|
|||
|
+
|
|||
|
+/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a
|
|||
|
+ dangerous relocation. */
|
|||
|
+
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp, struct bfd_link_info *info)
|
|||
|
+{
|
|||
|
+
|
|||
|
+ bfd_boolean gp_found;
|
|||
|
+ struct bfd_hash_entry *h;
|
|||
|
+ struct bfd_link_hash_entry *lh;
|
|||
|
+
|
|||
|
+ /* If we've already figured out what GP will be, just return it. */
|
|||
|
+ *pgp = _bfd_get_gp_value (output_bfd);
|
|||
|
+ if (*pgp)
|
|||
|
+ return TRUE;
|
|||
|
+
|
|||
|
+ h = bfd_hash_lookup (&info->hash->table, "_gp", FALSE, FALSE);
|
|||
|
+ lh = (struct bfd_link_hash_entry *) h;
|
|||
|
+lookup:
|
|||
|
+ if (lh)
|
|||
|
+ {
|
|||
|
+ switch (lh->type)
|
|||
|
+ {
|
|||
|
+ case bfd_link_hash_undefined:
|
|||
|
+ case bfd_link_hash_undefweak:
|
|||
|
+ case bfd_link_hash_common:
|
|||
|
+ gp_found = FALSE;
|
|||
|
+ break;
|
|||
|
+ case bfd_link_hash_defined:
|
|||
|
+ case bfd_link_hash_defweak:
|
|||
|
+ gp_found = TRUE;
|
|||
|
+ *pgp = lh->u.def.value;
|
|||
|
+ break;
|
|||
|
+ case bfd_link_hash_indirect:
|
|||
|
+ case bfd_link_hash_warning:
|
|||
|
+ lh = lh->u.i.link;
|
|||
|
+ /* @@FIXME ignoring warning for now */
|
|||
|
+ goto lookup;
|
|||
|
+ case bfd_link_hash_new:
|
|||
|
+ default:
|
|||
|
+ abort ();
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ gp_found = FALSE;
|
|||
|
+
|
|||
|
+ if (!gp_found)
|
|||
|
+ {
|
|||
|
+ /* Only get the error once. */
|
|||
|
+ *pgp = 4;
|
|||
|
+ _bfd_set_gp_value (output_bfd, *pgp);
|
|||
|
+ return FALSE;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ _bfd_set_gp_value (output_bfd, *pgp);
|
|||
|
+
|
|||
|
+ return TRUE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* We have to figure out the gp value, so that we can adjust the
|
|||
|
+ symbol value correctly. We look up the symbol _gp in the output
|
|||
|
+ BFD. If we can't find it, we're stuck. We cache it in the ELF
|
|||
|
+ target data. We don't need to adjust the symbol value for an
|
|||
|
+ external symbol if we are producing relocatable output. */
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable,
|
|||
|
+ char **error_message, bfd_vma *pgp, struct bfd_link_info *info)
|
|||
|
+{
|
|||
|
+ if (bfd_is_und_section (symbol->section) && !relocatable)
|
|||
|
+ {
|
|||
|
+ *pgp = 0;
|
|||
|
+ return bfd_reloc_undefined;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ *pgp = _bfd_get_gp_value (output_bfd);
|
|||
|
+ if (*pgp == 0 && (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0))
|
|||
|
+ {
|
|||
|
+ /* if this is called without link_info, then
|
|||
|
+ we cannot be doing a final link */
|
|||
|
+ if (info == NULL)
|
|||
|
+ relocatable = TRUE;
|
|||
|
+
|
|||
|
+ if (relocatable)
|
|||
|
+ {
|
|||
|
+ /* Make up a value. */
|
|||
|
+ *pgp = symbol->section->output_section->vma + 0x4000;
|
|||
|
+ _bfd_set_gp_value (output_bfd, *pgp);
|
|||
|
+ }
|
|||
|
+ else if (!nios2_elf_assign_gp (output_bfd, pgp, info))
|
|||
|
+ {
|
|||
|
+ *error_message =
|
|||
|
+ (char *)
|
|||
|
+ _("global pointer relative relocation when _gp not defined");
|
|||
|
+ return bfd_reloc_dangerous;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Relocations that require special handling */
|
|||
|
+
|
|||
|
+/* This is for relocations used only when relaxing to ensure
|
|||
|
+ * changes in size of section don't screw up .align */
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
|
|||
|
+ asymbol *symbol ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED,
|
|||
|
+ asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_hi16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data,
|
|||
|
+ asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+ /* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_hi16_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ + symbol->section->output_section->vma
|
|||
|
+ + symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_lo16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+/* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_lo16_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ + symbol->section->output_section->vma
|
|||
|
+ + symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_hiadj16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd,
|
|||
|
+ char **error_message ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+/* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_hiadj16_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ +
|
|||
|
+ symbol->section->output_section->
|
|||
|
+ vma +
|
|||
|
+ symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_pcrel16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd,
|
|||
|
+ char **error_message ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+/* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_pcrel16_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ +
|
|||
|
+ symbol->section->output_section->
|
|||
|
+ vma +
|
|||
|
+ symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_call26_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+/* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_call26_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ +
|
|||
|
+ symbol->section->output_section->
|
|||
|
+ vma +
|
|||
|
+ symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_gprel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd, char **msg)
|
|||
|
+{
|
|||
|
+ bfd_vma relocation;
|
|||
|
+ bfd_vma gp;
|
|||
|
+ bfd_reloc_status_type r;
|
|||
|
+
|
|||
|
+
|
|||
|
+/* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ relocation = symbol->value
|
|||
|
+ + symbol->section->output_section->vma + symbol->section->output_offset;
|
|||
|
+
|
|||
|
+ if ((r =
|
|||
|
+ nios2_elf_final_gp (abfd, symbol, FALSE, msg, &gp,
|
|||
|
+ nios2_link_info)) == bfd_reloc_ok)
|
|||
|
+ {
|
|||
|
+ relocation = relocation + reloc_entry->addend - gp;
|
|||
|
+ reloc_entry->addend = 0;
|
|||
|
+ if ((signed) relocation < -32768 || (signed) relocation > 32767)
|
|||
|
+ {
|
|||
|
+ *msg = _("global pointer relative address out of range");
|
|||
|
+ r = bfd_reloc_outofrange;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ r = nios2_elf32_do_gprel_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ relocation, reloc_entry->addend);
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return r;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_ujmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd, char **msg ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+ /* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_ujmp_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ + symbol->section->output_section->vma
|
|||
|
+ + symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_cjmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd, char **msg ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+ /* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_cjmp_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ + symbol->section->output_section->vma
|
|||
|
+ + symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_callr_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
|
+ void *data, asection *input_section, bfd *output_bfd, char **msg ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+ /* This part is from bfd_elf_generic_reloc. */
|
|||
|
+ if (output_bfd != (bfd *) NULL
|
|||
|
+ && (symbol->flags & BSF_SECTION_SYM) == 0
|
|||
|
+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
|
|||
|
+ {
|
|||
|
+ reloc_entry->address += input_section->output_offset;
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (output_bfd != NULL)
|
|||
|
+ /* FIXME: See bfd_perform_relocation. Is this right? */
|
|||
|
+ return bfd_reloc_ok;
|
|||
|
+
|
|||
|
+
|
|||
|
+ return nios2_elf32_do_callr_relocate (abfd, reloc_entry->howto,
|
|||
|
+ input_section,
|
|||
|
+ data, reloc_entry->address,
|
|||
|
+ (symbol->value
|
|||
|
+ +
|
|||
|
+ symbol->section->output_section->
|
|||
|
+ vma +
|
|||
|
+ symbol->section->output_offset),
|
|||
|
+ reloc_entry->addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Do the relocations which require special handling */
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_hi16_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ symbol_value = symbol_value + addend;
|
|||
|
+ addend = 0;
|
|||
|
+ symbol_value = (symbol_value >> 16) & 0xffff;
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_value, addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_lo16_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ symbol_value = symbol_value + addend;
|
|||
|
+ addend = 0;
|
|||
|
+ symbol_value = symbol_value & 0xffff;
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_value, addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_hiadj16_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data, bfd_vma offset,
|
|||
|
+ bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ symbol_value = symbol_value + addend;
|
|||
|
+ addend = 0;
|
|||
|
+ symbol_value =
|
|||
|
+ ((symbol_value >> 16) & 0xffff) + ((symbol_value >> 15) & 0x01);
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section, data, offset,
|
|||
|
+ symbol_value, addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_pcrel16_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ // NIOS2 pc relative relocations are relative to the next 32-bit instruction so we need
|
|||
|
+ // to subtract 4 before doing a final_link_relocate
|
|||
|
+ symbol_value = symbol_value + addend - 4;
|
|||
|
+ addend = 0;
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_value, addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_call26_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ /* check that the relocation is in the same page as the current address */
|
|||
|
+ if (((symbol_value + addend) & 0xf0000000)
|
|||
|
+ != ((input_section->output_section->vma + offset) & 0xf0000000))
|
|||
|
+ return bfd_reloc_overflow;
|
|||
|
+
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_value, addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_gprel_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ // because we need the output_bfd, the special handling is done
|
|||
|
+ // in nios2_elf32_relocate_section or in nios2_elf32_gprel_relocate
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_value, addend);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_ujmp_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ bfd_vma symbol_lo16, symbol_hi16;
|
|||
|
+ bfd_reloc_status_type r;
|
|||
|
+ symbol_value = symbol_value + addend;
|
|||
|
+ addend = 0;
|
|||
|
+ symbol_hi16 = (symbol_value >> 16) & 0xffff;
|
|||
|
+ symbol_lo16 = symbol_value & 0xffff;
|
|||
|
+
|
|||
|
+ r = _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_hi16, addend);
|
|||
|
+
|
|||
|
+ if (r == bfd_reloc_ok)
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset + 4, symbol_lo16, addend);
|
|||
|
+
|
|||
|
+ return r;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_cjmp_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ bfd_vma symbol_lo16, symbol_hi16;
|
|||
|
+ bfd_reloc_status_type r;
|
|||
|
+ symbol_value = symbol_value + addend;
|
|||
|
+ addend = 0;
|
|||
|
+ symbol_hi16 = (symbol_value >> 16) & 0xffff;
|
|||
|
+ symbol_lo16 = symbol_value & 0xffff;
|
|||
|
+
|
|||
|
+ r = _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_hi16, addend);
|
|||
|
+
|
|||
|
+ if (r == bfd_reloc_ok)
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset + 4, symbol_lo16, addend);
|
|||
|
+
|
|||
|
+ return r;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bfd_reloc_status_type
|
|||
|
+nios2_elf32_do_callr_relocate (bfd *abfd, reloc_howto_type *howto,
|
|||
|
+ asection *input_section ATTRIBUTE_UNUSED, bfd_byte *data,
|
|||
|
+ bfd_vma offset, bfd_vma symbol_value, bfd_vma addend)
|
|||
|
+{
|
|||
|
+ bfd_vma symbol_lo16, symbol_hi16;
|
|||
|
+ bfd_reloc_status_type r;
|
|||
|
+ symbol_value = symbol_value + addend;
|
|||
|
+ addend = 0;
|
|||
|
+ symbol_hi16 = (symbol_value >> 16) & 0xffff;
|
|||
|
+ symbol_lo16 = symbol_value & 0xffff;
|
|||
|
+
|
|||
|
+ r = _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset, symbol_hi16, addend);
|
|||
|
+
|
|||
|
+ if (r == bfd_reloc_ok)
|
|||
|
+ return _bfd_final_link_relocate (howto, abfd, input_section,
|
|||
|
+ data, offset + 4, symbol_lo16, addend);
|
|||
|
+
|
|||
|
+ return r;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ The function nios2_elf32_relocate_section is used by the linker
|
|||
|
+ to perform relocations
|
|||
|
+*/
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf32_relocate_section (bfd * output_bfd,
|
|||
|
+ struct bfd_link_info *info,
|
|||
|
+ bfd * input_bfd,
|
|||
|
+ asection * input_section,
|
|||
|
+ bfd_byte * contents,
|
|||
|
+ Elf_Internal_Rela * relocs,
|
|||
|
+ Elf_Internal_Sym * local_syms,
|
|||
|
+ asection ** local_sections)
|
|||
|
+{
|
|||
|
+ Elf_Internal_Shdr *symtab_hdr;
|
|||
|
+ struct elf_link_hash_entry **sym_hashes;
|
|||
|
+ Elf_Internal_Rela *rel;
|
|||
|
+ Elf_Internal_Rela *relend;
|
|||
|
+
|
|||
|
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
|||
|
+ sym_hashes = elf_sym_hashes (input_bfd);
|
|||
|
+ relend = relocs + input_section->reloc_count;
|
|||
|
+
|
|||
|
+// size_t psymalloc = 0;
|
|||
|
+// _bfd_generic_link_output_symbols(output_bfd, input_bfd, info, &psymalloc);
|
|||
|
+ for (rel = relocs; rel < relend; rel++)
|
|||
|
+ {
|
|||
|
+ reloc_howto_type *howto;
|
|||
|
+ unsigned long r_symndx;
|
|||
|
+ Elf_Internal_Sym *sym;
|
|||
|
+ asection *sec;
|
|||
|
+ struct elf_link_hash_entry *h;
|
|||
|
+ bfd_vma relocation;
|
|||
|
+ bfd_vma gp;
|
|||
|
+ bfd_reloc_status_type r = bfd_reloc_ok;
|
|||
|
+ const char *name = NULL;
|
|||
|
+ int r_type;
|
|||
|
+ const char *msg;
|
|||
|
+
|
|||
|
+ msg = (const char *) NULL;
|
|||
|
+
|
|||
|
+ r_type = ELF32_R_TYPE (rel->r_info);
|
|||
|
+
|
|||
|
+ r_symndx = ELF32_R_SYM (rel->r_info);
|
|||
|
+
|
|||
|
+ if (info->relocatable)
|
|||
|
+ {
|
|||
|
+ /* This is a relocatable link. We don't have to change
|
|||
|
+ anything, unless the reloc is against a section symbol,
|
|||
|
+ in which case we have to adjust according to where the
|
|||
|
+ section symbol winds up in the output section. */
|
|||
|
+ if (r_symndx < symtab_hdr->sh_info)
|
|||
|
+ {
|
|||
|
+ sym = local_syms + r_symndx;
|
|||
|
+
|
|||
|
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
|
|||
|
+ {
|
|||
|
+ sec = local_sections[r_symndx];
|
|||
|
+ rel->r_addend += sec->output_offset + sym->st_value;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ continue;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* This is a final link. */
|
|||
|
+ howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
|
|||
|
+ h = NULL;
|
|||
|
+ sym = NULL;
|
|||
|
+ sec = NULL;
|
|||
|
+
|
|||
|
+ if (r_symndx < symtab_hdr->sh_info)
|
|||
|
+ {
|
|||
|
+ sym = local_syms + r_symndx;
|
|||
|
+ sec = local_sections[r_symndx];
|
|||
|
+
|
|||
|
+ relocation = (sec->output_section->vma
|
|||
|
+ + sec->output_offset + sym->st_value);
|
|||
|
+
|
|||
|
+ // this ensures that relocations against duplicated symbols
|
|||
|
+ // in merged sections that have been removed are fixed up against
|
|||
|
+ // the remaining symbol and not the one that has been removed
|
|||
|
+ if ((sec->flags & SEC_MERGE)
|
|||
|
+ && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
|
|||
|
+ {
|
|||
|
+ rel->r_addend =
|
|||
|
+ _bfd_elf_rel_local_sym (output_bfd, sym, &sec, rel->r_addend);
|
|||
|
+ rel->r_addend -= relocation;
|
|||
|
+ rel->r_addend += sec->output_section->vma + sec->output_offset;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ name = bfd_elf_string_from_elf_section
|
|||
|
+ (input_bfd, symtab_hdr->sh_link, sym->st_name);
|
|||
|
+
|
|||
|
+ name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
|||
|
+
|
|||
|
+ while (h->root.type == bfd_link_hash_indirect
|
|||
|
+ || h->root.type == bfd_link_hash_warning)
|
|||
|
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|||
|
+
|
|||
|
+ name = h->root.root.string;
|
|||
|
+
|
|||
|
+ if (h->root.type == bfd_link_hash_defined
|
|||
|
+ || h->root.type == bfd_link_hash_defweak)
|
|||
|
+ {
|
|||
|
+ sec = h->root.u.def.section;
|
|||
|
+
|
|||
|
+ relocation = (h->root.u.def.value
|
|||
|
+ + sec->output_section->vma + sec->output_offset);
|
|||
|
+ }
|
|||
|
+ else if (h->root.type == bfd_link_hash_undefweak)
|
|||
|
+ {
|
|||
|
+ relocation = 0;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ if (!((*info->callbacks->undefined_symbol)
|
|||
|
+ (info, h->root.root.string, input_bfd,
|
|||
|
+ input_section, rel->r_offset, TRUE)))
|
|||
|
+ return FALSE;
|
|||
|
+ relocation = 0;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (howto != NULL)
|
|||
|
+ {
|
|||
|
+ switch (howto->type)
|
|||
|
+ {
|
|||
|
+ case R_NIOS2_HI16:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_hi16_relocate (input_bfd, howto, input_section,
|
|||
|
+ contents, rel->r_offset,
|
|||
|
+ relocation, rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_LO16:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_lo16_relocate (input_bfd, howto, input_section,
|
|||
|
+ contents, rel->r_offset,
|
|||
|
+ relocation, rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_HIADJ16:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_hiadj16_relocate (input_bfd, howto,
|
|||
|
+ input_section, contents,
|
|||
|
+ rel->r_offset, relocation,
|
|||
|
+ rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_PCREL16:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_pcrel16_relocate (input_bfd, howto,
|
|||
|
+ input_section, contents,
|
|||
|
+ rel->r_offset, relocation,
|
|||
|
+ rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_GPREL:
|
|||
|
+ // turns an absolute address into a gp-relative address
|
|||
|
+ if (!nios2_elf_assign_gp (output_bfd, &gp, info))
|
|||
|
+ {
|
|||
|
+ msg =
|
|||
|
+ _
|
|||
|
+ ("global pointer relative relocation when _gp not defined");
|
|||
|
+ r = bfd_reloc_dangerous;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ relocation = relocation + rel->r_addend - gp;
|
|||
|
+ rel->r_addend = 0;
|
|||
|
+ if ((signed) relocation < -32768
|
|||
|
+ || (signed) relocation > 32767)
|
|||
|
+ {
|
|||
|
+ msg = _("global pointer relative address out of range");
|
|||
|
+ r = bfd_reloc_outofrange;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ r =
|
|||
|
+ _bfd_final_link_relocate (howto, input_bfd,
|
|||
|
+ input_section, contents,
|
|||
|
+ rel->r_offset, relocation,
|
|||
|
+ rel->r_addend);
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_UJMP:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_ujmp_relocate (input_bfd, howto, input_section,
|
|||
|
+ contents, rel->r_offset,
|
|||
|
+ relocation, rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_CJMP:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_cjmp_relocate (input_bfd, howto, input_section,
|
|||
|
+ contents, rel->r_offset,
|
|||
|
+ relocation, rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_CALLR:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_callr_relocate (input_bfd, howto,
|
|||
|
+ input_section, contents,
|
|||
|
+ rel->r_offset, relocation,
|
|||
|
+ rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_CALL26:
|
|||
|
+ r =
|
|||
|
+ nios2_elf32_do_call26_relocate (input_bfd, howto,
|
|||
|
+ input_section, contents,
|
|||
|
+ rel->r_offset, relocation,
|
|||
|
+ rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ case R_NIOS2_ALIGN:
|
|||
|
+ r = bfd_reloc_ok;
|
|||
|
+ /* comment - for symmetry this would be
|
|||
|
+ r = nios2_elf32_do_ignore_reloc (input_bfd, howto, input_section,
|
|||
|
+ contents, rel->r_offset,
|
|||
|
+ relocation, rel->r_addend);
|
|||
|
+ but do_ignore_reloc would do no more than return bfd_reloc_ok */
|
|||
|
+ break;
|
|||
|
+ default:
|
|||
|
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
|
|||
|
+ contents, rel->r_offset,
|
|||
|
+ relocation, rel->r_addend);
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ r = bfd_reloc_notsupported;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (r != bfd_reloc_ok)
|
|||
|
+ {
|
|||
|
+ if (h != NULL)
|
|||
|
+ name = h->root.root.string;
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ name = (bfd_elf_string_from_elf_section
|
|||
|
+ (input_bfd, symtab_hdr->sh_link, sym->st_name));
|
|||
|
+ if (name == NULL || *name == '\0')
|
|||
|
+ name = bfd_section_name (input_bfd, sec);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ switch (r)
|
|||
|
+ {
|
|||
|
+ case bfd_reloc_overflow:
|
|||
|
+ r = info->callbacks->reloc_overflow
|
|||
|
+ (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
|
|||
|
+ input_bfd, input_section, rel->r_offset);
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ case bfd_reloc_undefined:
|
|||
|
+ r = info->callbacks->undefined_symbol
|
|||
|
+ (info, name, input_bfd, input_section, rel->r_offset, TRUE);
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ case bfd_reloc_outofrange:
|
|||
|
+ if (msg == NULL)
|
|||
|
+ msg = _("relocation out of range");
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ case bfd_reloc_notsupported:
|
|||
|
+ if (msg == NULL)
|
|||
|
+ msg = _("unsupported relocation");
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ case bfd_reloc_dangerous:
|
|||
|
+ if (msg == NULL)
|
|||
|
+ msg = _("dangerous relocation");
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ default:
|
|||
|
+ if (msg == NULL)
|
|||
|
+ msg = _("unknown error");
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (msg)
|
|||
|
+ {
|
|||
|
+ r = info->callbacks->warning
|
|||
|
+ (info, msg, name, input_bfd, input_section, rel->r_offset);
|
|||
|
+ return linker_force_make_executable;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ return TRUE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Handle an NIOS2 specific section when reading an object file. This
|
|||
|
+ is called when elfcode.h finds a section with an unknown type.
|
|||
|
+ FIXME: We need to handle the SHF_NIOS2_GPREL flag */
|
|||
|
+
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf32_section_from_shdr (bfd *abfd,
|
|||
|
+ Elf_Internal_Shdr *hdr, const char *name, int shindex)
|
|||
|
+{
|
|||
|
+ asection *newsect;
|
|||
|
+
|
|||
|
+ /* NG - I'm keeping this code commented out at the moment
|
|||
|
+ in case we add a .mdebug section */
|
|||
|
+
|
|||
|
+ /*
|
|||
|
+ switch (hdr->sh_type)
|
|||
|
+ {
|
|||
|
+ case SHT_NIOS2_DEBUG:
|
|||
|
+ if (strcmp (name, ".mdebug") != 0)
|
|||
|
+ return FALSE;
|
|||
|
+ break;
|
|||
|
+ default:
|
|||
|
+ return FALSE;
|
|||
|
+ }
|
|||
|
+ */
|
|||
|
+
|
|||
|
+ if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
|
|||
|
+ return FALSE;
|
|||
|
+
|
|||
|
+ newsect = hdr->bfd_section;
|
|||
|
+
|
|||
|
+ /* ditto */
|
|||
|
+ /*
|
|||
|
+ if (hdr->sh_type == SHT_NIOS2_DEBUG)
|
|||
|
+ {
|
|||
|
+ if (! bfd_set_section_flags (abfd, newsect,
|
|||
|
+ (bfd_get_section_flags (abfd, newsect)
|
|||
|
+ | SEC_DEBUGGING)))
|
|||
|
+ return FALSE;
|
|||
|
+ }
|
|||
|
+ */
|
|||
|
+ return TRUE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Convert NIOS2 specific section flags to bfd internal section flags. */
|
|||
|
+
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf32_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr)
|
|||
|
+{
|
|||
|
+ if (hdr->sh_flags & SHF_NIOS2_GPREL)
|
|||
|
+ *flags |= SEC_SMALL_DATA;
|
|||
|
+
|
|||
|
+ return TRUE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Set the correct type for an NIOS2 ELF section. We do this by the
|
|||
|
+ section name, which is a hack, but ought to work. */
|
|||
|
+
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf32_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
|
|||
|
+ Elf_Internal_Shdr *hdr, asection *sec)
|
|||
|
+{
|
|||
|
+ register const char *name;
|
|||
|
+
|
|||
|
+ name = bfd_get_section_name (abfd, sec);
|
|||
|
+
|
|||
|
+ if (strcmp (name, ".mdebug") == 0)
|
|||
|
+ {
|
|||
|
+ /* we don't yet have an .mdebug section, but I'm leaving this here
|
|||
|
+ in case we ever do
|
|||
|
+ hdr->sh_type = SHT_NIOS2_DEBUG;
|
|||
|
+
|
|||
|
+ if ((abfd->flags & DYNAMIC) != 0 )
|
|||
|
+ hdr->sh_entsize = 0;
|
|||
|
+ else
|
|||
|
+ hdr->sh_entsize = 1;
|
|||
|
+ */
|
|||
|
+ }
|
|||
|
+ else if ((sec->flags & SEC_SMALL_DATA)
|
|||
|
+ || strcmp (name, ".sdata") == 0
|
|||
|
+ || strcmp (name, ".sbss") == 0
|
|||
|
+ || strcmp (name, ".lit4") == 0 || strcmp (name, ".lit8") == 0)
|
|||
|
+ hdr->sh_flags |= SHF_NIOS2_GPREL;
|
|||
|
+
|
|||
|
+ return TRUE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Look through the relocs for a section during the first phase.
|
|||
|
+ Since we don't do .gots or .plts, we just need to consider the
|
|||
|
+ virtual table relocs for gc. */
|
|||
|
+
|
|||
|
+static bfd_boolean
|
|||
|
+nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
|
+ asection *sec, const Elf_Internal_Rela *relocs)
|
|||
|
+{
|
|||
|
+ Elf_Internal_Shdr *symtab_hdr;
|
|||
|
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
|
|||
|
+ const Elf_Internal_Rela *rel;
|
|||
|
+ const Elf_Internal_Rela *rel_end;
|
|||
|
+
|
|||
|
+ if (info->relocatable)
|
|||
|
+ return TRUE;
|
|||
|
+
|
|||
|
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
|||
|
+ sym_hashes = elf_sym_hashes (abfd);
|
|||
|
+ sym_hashes_end =
|
|||
|
+ sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
|
|||
|
+ if (!elf_bad_symtab (abfd))
|
|||
|
+ sym_hashes_end -= symtab_hdr->sh_info;
|
|||
|
+
|
|||
|
+ rel_end = relocs + sec->reloc_count;
|
|||
|
+ for (rel = relocs; rel < rel_end; rel++)
|
|||
|
+ {
|
|||
|
+ struct elf_link_hash_entry *h;
|
|||
|
+ unsigned long r_symndx;
|
|||
|
+
|
|||
|
+ r_symndx = ELF32_R_SYM (rel->r_info);
|
|||
|
+ if (r_symndx < symtab_hdr->sh_info)
|
|||
|
+ h = NULL;
|
|||
|
+ else
|
|||
|
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
|||
|
+
|
|||
|
+ switch (ELF32_R_TYPE (rel->r_info))
|
|||
|
+ {
|
|||
|
+ /* This relocation describes the C++ object vtable hierarchy.
|
|||
|
+ Reconstruct it for later use during GC. */
|
|||
|
+ case R_NIOS2_GNU_VTINHERIT:
|
|||
|
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
|
|||
|
+ return FALSE;
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ /* This relocation describes which C++ vtable entries are actually
|
|||
|
+ used. Record for later use during GC. */
|
|||
|
+ case R_NIOS2_GNU_VTENTRY:
|
|||
|
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
|
|||
|
+ return FALSE;
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return TRUE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Return the section that should be marked against GC for a given
|
|||
|
+ relocation. */
|
|||
|
+
|
|||
|
+asection *
|
|||
|
+nios2_elf32_gc_mark_hook (asection *sec,
|
|||
|
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
|||
|
+ Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
|
|||
|
+ Elf_Internal_Sym *sym)
|
|||
|
+{
|
|||
|
+ if (h != NULL)
|
|||
|
+ {
|
|||
|
+ switch (ELF32_R_TYPE (rel->r_info))
|
|||
|
+ {
|
|||
|
+ case R_NIOS2_GNU_VTINHERIT:
|
|||
|
+ case R_NIOS2_GNU_VTENTRY:
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ default:
|
|||
|
+ switch (h->root.type)
|
|||
|
+ {
|
|||
|
+ case bfd_link_hash_defined:
|
|||
|
+ case bfd_link_hash_defweak:
|
|||
|
+ return h->root.u.def.section;
|
|||
|
+
|
|||
|
+ case bfd_link_hash_common:
|
|||
|
+ return h->root.u.c.p->section;
|
|||
|
+
|
|||
|
+ default:
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
|
|||
|
+
|
|||
|
+ return NULL;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ NG ??? I'm marking the sections as standalone ie. I'm linking for
|
|||
|
+ standalone embedded applications, not for UNIX System V or any other
|
|||
|
+ OS/ABI - this may need to change when we deal with embedded PIC or
|
|||
|
+ dynamic linking
|
|||
|
+*/
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_elf32_post_process_headers (bfd *abfd,
|
|||
|
+ struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
|
|||
|
+{
|
|||
|
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
|
|||
|
+
|
|||
|
+ i_ehdrp = elf_elfheader (abfd);
|
|||
|
+ i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+#define ELF_ARCH bfd_arch_nios2
|
|||
|
+#define ELF_MACHINE_CODE EM_ALTERA_NIOS2
|
|||
|
+
|
|||
|
+/* for now we just make this 1, as we have no MMU in New Jersey */
|
|||
|
+
|
|||
|
+#define ELF_MAXPAGESIZE 1
|
|||
|
+
|
|||
|
+/* relocation table lookup macros */
|
|||
|
+
|
|||
|
+#define bfd_elf32_bfd_reloc_type_lookup nios2_elf32_bfd_reloc_type_lookup
|
|||
|
+
|
|||
|
+/* JUMP_TABLE_LINK macros */
|
|||
|
+
|
|||
|
+#define bfd_elf32_bfd_relax_section nios2_elf32_relax_section
|
|||
|
+
|
|||
|
+/* elf_info_to_howto (using RELA relocations) */
|
|||
|
+
|
|||
|
+#define elf_info_to_howto nios2_elf32_info_to_howto
|
|||
|
+
|
|||
|
+/* elf backend functions */
|
|||
|
+
|
|||
|
+#define elf_backend_can_gc_sections 1
|
|||
|
+
|
|||
|
+#define elf_backend_relocate_section nios2_elf32_relocate_section
|
|||
|
+#define elf_backend_section_from_shdr nios2_elf32_section_from_shdr
|
|||
|
+#define elf_backend_section_flags nios2_elf32_section_flags
|
|||
|
+#define elf_backend_fake_sections nios2_elf32_fake_sections
|
|||
|
+#define elf_backend_post_process_headers nios2_elf32_post_process_headers
|
|||
|
+#define elf_backend_check_relocs nios2_elf32_check_relocs
|
|||
|
+
|
|||
|
+#define elf_backend_gc_mark_hook nios2_elf32_gc_mark_hook
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Support for SGI-ish mips targets. */
|
|||
|
+#define TARGET_LITTLE_SYM bfd_elf32_littlenios2_vec
|
|||
|
+#define TARGET_LITTLE_NAME "elf32-littlenios2"
|
|||
|
+#define TARGET_BIG_SYM bfd_elf32_bignios2_vec
|
|||
|
+#define TARGET_BIG_NAME "elf32-bignios2"
|
|||
|
+
|
|||
|
+#include "elf32-target.h"
|
|||
|
diff --git a/bfd/reloc.c b/bfd/reloc.c
|
|||
|
index 1b8c8d7..c66a23d 100644
|
|||
|
--- a/bfd/reloc.c
|
|||
|
+++ b/bfd/reloc.c
|
|||
|
@@ -4733,6 +4733,39 @@ ENUMDOC
|
|||
|
msp430 specific relocation codes
|
|||
|
|
|||
|
ENUM
|
|||
|
+ BFD_RELOC_NIOS2_S16
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_U16
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_CALL26
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_IMM5
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_CACHE_OPX
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_IMM6
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_IMM8
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_HI16
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_LO16
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_HIADJ16
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_GPREL
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_UJMP
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_CJMP
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_CALLR
|
|||
|
+ENUMX
|
|||
|
+ BFD_RELOC_NIOS2_ALIGN
|
|||
|
+ENUMDOC
|
|||
|
+ Relocations used by the Altera Nios II core
|
|||
|
+
|
|||
|
+ENUM
|
|||
|
BFD_RELOC_IQ2000_OFFSET_16
|
|||
|
ENUMX
|
|||
|
BFD_RELOC_IQ2000_OFFSET_21
|
|||
|
diff --git a/bfd/targets.c b/bfd/targets.c
|
|||
|
index 71e3337..d5f6d60 100644
|
|||
|
--- a/bfd/targets.c
|
|||
|
+++ b/bfd/targets.c
|
|||
|
@@ -619,6 +619,8 @@ extern const bfd_target bfd_elf32_ntradbigmips_vec;
|
|||
|
extern const bfd_target bfd_elf32_ntradlittlemips_vec;
|
|||
|
extern const bfd_target bfd_elf32_openrisc_vec;
|
|||
|
extern const bfd_target bfd_elf32_or32_big_vec;
|
|||
|
+extern const bfd_target bfd_elf32_littlenios2_vec;
|
|||
|
+extern const bfd_target bfd_elf32_bignios2_vec;
|
|||
|
extern const bfd_target bfd_elf32_pj_vec;
|
|||
|
extern const bfd_target bfd_elf32_pjl_vec;
|
|||
|
extern const bfd_target bfd_elf32_powerpc_vec;
|
|||
|
@@ -819,6 +821,8 @@ extern const bfd_target sco5_core_vec;
|
|||
|
extern const bfd_target trad_core_vec;
|
|||
|
|
|||
|
extern const bfd_target bfd_elf32_am33lin_vec;
|
|||
|
+extern const bfd_target bfd_elf32_littlenios2_vec;
|
|||
|
+extern const bfd_target bfd_elf32_bignios2_vec;
|
|||
|
static const bfd_target * const _bfd_target_vector[] =
|
|||
|
{
|
|||
|
#ifdef SELECT_VECS
|
|||
|
@@ -923,6 +927,8 @@ static const bfd_target * const _bfd_target_vector[] =
|
|||
|
&bfd_elf32_littlearm_vxworks_vec,
|
|||
|
&bfd_elf32_littlemips_vec,
|
|||
|
&bfd_elf32_littlemips_vxworks_vec,
|
|||
|
+ &bfd_elf32_littlenios2_vec,
|
|||
|
+ &bfd_elf32_bignios2_vec,
|
|||
|
&bfd_elf32_m32c_vec,
|
|||
|
&bfd_elf32_m32r_vec,
|
|||
|
&bfd_elf32_m32rle_vec,
|
|||
|
diff --git a/config.sub b/config.sub
|
|||
|
index fab0aa3..462e7c6 100755
|
|||
|
--- a/config.sub
|
|||
|
+++ b/config.sub
|
|||
|
@@ -270,7 +270,7 @@ case $basic_machine in
|
|||
|
| mn10200 | mn10300 \
|
|||
|
| mt \
|
|||
|
| msp430 \
|
|||
|
- | nios | nios2 \
|
|||
|
+ | nios2 | nios2eb | nios2el \
|
|||
|
| ns16k | ns32k \
|
|||
|
| or32 \
|
|||
|
| pdp10 | pdp11 | pj | pjl \
|
|||
|
diff --git a/configure.in b/configure.in
|
|||
|
index a4befda..f2e34c7 100644
|
|||
|
--- a/configure.in
|
|||
|
+++ b/configure.in
|
|||
|
@@ -740,6 +740,9 @@ case "${target}" in
|
|||
|
mips*-*-*)
|
|||
|
noconfigdirs="$noconfigdirs gprof ${libgcj}"
|
|||
|
;;
|
|||
|
+ nios2*-*-*)
|
|||
|
+ noconfigdirs="$noconfigdirs ld"
|
|||
|
+ ;;
|
|||
|
romp-*-*)
|
|||
|
noconfigdirs="$noconfigdirs bfd binutils ld gas opcodes target-libgloss ${libgcj}"
|
|||
|
;;
|
|||
|
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
|||
|
index 14fd58b..eac9489 100644
|
|||
|
--- a/gdb/Makefile.in
|
|||
|
+++ b/gdb/Makefile.in
|
|||
|
@@ -593,6 +593,7 @@ libiberty_h = $(INCLUDE_DIR)/libiberty.h
|
|||
|
libbfd_h = $(BFD_SRC)/libbfd.h
|
|||
|
remote_sim_h = $(INCLUDE_DIR)/gdb/remote-sim.h
|
|||
|
demangle_h = $(INCLUDE_DIR)/demangle.h
|
|||
|
+nios2_h = $(INCLUDE_DIR)/opcode/nios2.h
|
|||
|
obstack_h = $(INCLUDE_DIR)/obstack.h
|
|||
|
opcode_m68hc11_h = $(INCLUDE_DIR)/opcode/m68hc11.h
|
|||
|
readline_h = $(READLINE_SRC)/readline.h
|
|||
|
@@ -2399,6 +2400,7 @@ ms1-tdep.o: ms1-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) $(frame_base_h) \
|
|||
|
$(trad_frame_h) $(inferior_h) $(dwarf2_frame_h) $(infcall_h) \
|
|||
|
$(gdb_assert_h)
|
|||
|
nbsd-tdep.o: nbsd-tdep.c $(defs_h) $(gdb_string_h) $(solib_svr4_h)
|
|||
|
+nios2-tdep.o: nios2-tdep.c $(defs_h) $(symtab_h) $(frame_h) $(nios2_h)
|
|||
|
nlmread.o: nlmread.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) \
|
|||
|
$(objfiles_h) $(buildsym_h) $(stabsread_h) $(block_h)
|
|||
|
nto-procfs.o: nto-procfs.c $(defs_h) $(gdb_dirent_h) $(exceptions_h) \
|
|||
|
diff --git a/gdb/config/nios2/nios2.mt b/gdb/config/nios2/nios2.mt
|
|||
|
new file mode 100644
|
|||
|
index 0000000..63413b4
|
|||
|
--- /dev/null
|
|||
|
+++ b/gdb/config/nios2/nios2.mt
|
|||
|
@@ -0,0 +1,4 @@
|
|||
|
+# Target: Altera New Jersey Processor machine (NIOS2)
|
|||
|
+TDEPFILES= nios2-tdep.o
|
|||
|
+
|
|||
|
+
|
|||
|
diff --git a/gdb/config/nios2/tm-nios2.h b/gdb/config/nios2/tm-nios2.h
|
|||
|
new file mode 100644
|
|||
|
index 0000000..2962b6b
|
|||
|
--- /dev/null
|
|||
|
+++ b/gdb/config/nios2/tm-nios2.h
|
|||
|
@@ -0,0 +1,28 @@
|
|||
|
+/* Definitions to target GDB to New Jersey targets.
|
|||
|
+ Copyright 1986, 1987, 1988, 1989, 1991, 1993, 1994,
|
|||
|
+ 1995, 1996, 1997, 1998, 1999, 2000, 2003
|
|||
|
+ by Peter Brookes (pbrookes@altera.com)
|
|||
|
+
|
|||
|
+ This file is part of GDB.
|
|||
|
+
|
|||
|
+ This program is free software; you can redistribute it and/or modify
|
|||
|
+ it under the terms of 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.
|
|||
|
+
|
|||
|
+ This program 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 a copy of the GNU General Public License
|
|||
|
+ along with this program; if not, write to the Free Software
|
|||
|
+ Foundation, Inc., 59 Temple Place - Suite 330,
|
|||
|
+ Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+#ifndef TM_NIOS2_H
|
|||
|
+#define TM_NIOS2_H
|
|||
|
+
|
|||
|
+#define GDB_MULTI_ARCH 1
|
|||
|
+
|
|||
|
+#endif /* TM_NIOS2_H */
|
|||
|
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
|
|||
|
index dd2e719..7222f59 100644
|
|||
|
--- a/gdb/configure.tgt
|
|||
|
+++ b/gdb/configure.tgt
|
|||
|
@@ -20,6 +20,7 @@ m68hc11*|m6811*) gdb_target_cpu=m68hc11 ;;
|
|||
|
m68*) gdb_target_cpu=m68k ;;
|
|||
|
m88*) gdb_target_cpu=m88k ;;
|
|||
|
mips*) gdb_target_cpu=mips ;;
|
|||
|
+nios2*) gdb_target_cpu=nios2 ;;
|
|||
|
powerpc*) gdb_target_cpu=powerpc ;;
|
|||
|
sparc*) gdb_target_cpu=sparc ;;
|
|||
|
thumb*) gdb_target_cpu=arm ;;
|
|||
|
@@ -155,6 +156,8 @@ mn10300-*-*) gdb_target=mn10300 ;;
|
|||
|
|
|||
|
mt-*-*) gdb_target=mt ;;
|
|||
|
|
|||
|
+nios2*-*-*) gdb_target=nios2 ;;
|
|||
|
+
|
|||
|
powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu)
|
|||
|
gdb_target=nbsd ;;
|
|||
|
powerpc-*-openbsd*) gdb_target=obsd ;;
|
|||
|
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
|
|||
|
index 9748c95..b3fb5f8 100644
|
|||
|
--- a/gdb/gdbserver/Makefile.in
|
|||
|
+++ b/gdb/gdbserver/Makefile.in
|
|||
|
@@ -280,6 +280,7 @@ linux-ia64-low.o: linux-ia64-low.c $(linux_low_h) $(server_h)
|
|||
|
linux-m32r-low.o: linux-m32r-low.c $(linux_low_h) $(server_h)
|
|||
|
linux-mips-low.o: linux-mips-low.c $(linux_low_h) $(server_h) \
|
|||
|
$(gdb_proc_service_h)
|
|||
|
+linux-nios2-low.o: linux-nios2-low.c $(linux_low_h) $(server_h)
|
|||
|
linux-ppc-low.o: linux-ppc-low.c $(linux_low_h) $(server_h)
|
|||
|
linux-ppc64-low.o: linux-ppc64-low.c $(linux_low_h) $(server_h)
|
|||
|
linux-s390-low.o: linux-s390-low.c $(linux_low_h) $(server_h)
|
|||
|
@@ -318,6 +319,9 @@ reg-m68k.c : $(srcdir)/../regformats/reg-m68k.dat $(regdat_sh)
|
|||
|
reg-mips.o : reg-mips.c $(regdef_h)
|
|||
|
reg-mips.c : $(srcdir)/../regformats/reg-mips.dat $(regdat_sh)
|
|||
|
sh $(regdat_sh) $(srcdir)/../regformats/reg-mips.dat reg-mips.c
|
|||
|
+reg-nios2.o : reg-nios2.c $(regdef_h)
|
|||
|
+reg-nios2.c : $(srcdir)/../regformats/reg-nios2.dat $(regdat_sh)
|
|||
|
+ sh $(regdat_sh) $(srcdir)/../regformats/reg-nios2.dat reg-nios2.c
|
|||
|
reg-ppc.o : reg-ppc.c $(regdef_h)
|
|||
|
reg-ppc.c : $(srcdir)/../regformats/reg-ppc.dat $(regdat_sh)
|
|||
|
sh $(regdat_sh) $(srcdir)/../regformats/reg-ppc.dat reg-ppc.c
|
|||
|
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
|
|||
|
index 5a4792c..fdc847c 100644
|
|||
|
--- a/gdb/gdbserver/configure.srv
|
|||
|
+++ b/gdb/gdbserver/configure.srv
|
|||
|
@@ -72,6 +72,10 @@ case "${target}" in
|
|||
|
srv_linux_usrregs=yes
|
|||
|
srv_linux_thread_db=yes
|
|||
|
;;
|
|||
|
+ nios2-*-linux*) srv_regobj=reg-nios2.o
|
|||
|
+ srv_tgtobj="linux-low.o linux-nios2-low.o"
|
|||
|
+ srv_linux_usrregs=yes
|
|||
|
+ ;;
|
|||
|
powerpc64-*-linux*) srv_regobj=reg-ppc64.o
|
|||
|
srv_tgtobj="linux-low.o linux-ppc64-low.o"
|
|||
|
srv_linux_usrregs=yes
|
|||
|
diff --git a/gdb/gdbserver/linux-nios2-low.c b/gdb/gdbserver/linux-nios2-low.c
|
|||
|
new file mode 100644
|
|||
|
index 0000000..1fab749
|
|||
|
--- /dev/null
|
|||
|
+++ b/gdb/gdbserver/linux-nios2-low.c
|
|||
|
@@ -0,0 +1,89 @@
|
|||
|
+/* GNU/Linux/Nios2 specific low level interface for the remote server for GDB */
|
|||
|
+
|
|||
|
+#include "server.h"
|
|||
|
+#include "linux-low.h"
|
|||
|
+
|
|||
|
+#ifdef HAVE_SYS_REG_H
|
|||
|
+#include <sys/reg.h>
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+#include <asm/ptrace.h>
|
|||
|
+
|
|||
|
+static int nios2_regmap[] =
|
|||
|
+{
|
|||
|
+ -1, PTR_R1 * 4, PTR_R2 * 4, PTR_R3 * 4,
|
|||
|
+ PTR_R4 * 4, PTR_R5 * 4, PTR_R6 * 4, PTR_R7 * 4,
|
|||
|
+ PTR_R8 * 4, PTR_R9 * 4, PTR_R10 * 4, PTR_R11 * 4,
|
|||
|
+ PTR_R12 * 4, PTR_R13 * 4, PTR_R14 * 4, PTR_R15 * 4, /* reg 15 */
|
|||
|
+ PTR_R16 * 4, PTR_R17 * 4, PTR_R18 * 4, PTR_R19 * 4,
|
|||
|
+ PTR_R20 * 4, PTR_R21 * 4, PTR_R22 * 4, PTR_R23 * 4,
|
|||
|
+ -1, -1, PTR_GP * 4, PTR_SP * 4,
|
|||
|
+ PTR_FP * 4, -1, -1, PTR_RA * 4, /* reg 31 */
|
|||
|
+ PTR_PC * 4, -1, -1, -1,
|
|||
|
+ -1, -1, -1, -1,
|
|||
|
+ -1, -1, -1, -1
|
|||
|
+};
|
|||
|
+
|
|||
|
+#define nios2_num_regs (sizeof(nios2_regmap) / sizeof(nios2_regmap[0]))
|
|||
|
+
|
|||
|
+static int
|
|||
|
+nios2_cannot_store_register (int regno)
|
|||
|
+{
|
|||
|
+ return (regno >= 33);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static int
|
|||
|
+nios2_cannot_fetch_register (int regno)
|
|||
|
+{
|
|||
|
+ return (regno >= 33);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static CORE_ADDR
|
|||
|
+nios2_get_pc ()
|
|||
|
+{
|
|||
|
+ unsigned long pc;
|
|||
|
+ collect_register_by_name ("pc", &pc);
|
|||
|
+ return pc;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_set_pc (CORE_ADDR pc)
|
|||
|
+{
|
|||
|
+ unsigned long newpc = pc;
|
|||
|
+ supply_register_by_name ("pc", &newpc);
|
|||
|
+}
|
|||
|
+
|
|||
|
+#if 0
|
|||
|
+static const unsigned long nios2_breakpoint = 0x003da03a;
|
|||
|
+#else
|
|||
|
+static const unsigned long nios2_breakpoint = 0x003b687a; /* Trap instr. w/imm=0x01 */
|
|||
|
+#endif
|
|||
|
+#define nios2_breakpoint_len 4
|
|||
|
+
|
|||
|
+static int
|
|||
|
+nios2_breakpoint_at (CORE_ADDR where)
|
|||
|
+{
|
|||
|
+ unsigned long insn;
|
|||
|
+
|
|||
|
+ (*the_target->read_memory) (where, (char *) &insn, nios2_breakpoint_len);
|
|||
|
+ if (insn == nios2_breakpoint)
|
|||
|
+ return 1;
|
|||
|
+
|
|||
|
+ /* If necessary, recognize more trap instructions here. GDB only uses the
|
|||
|
+ one. */
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+struct linux_target_ops the_low_target = {
|
|||
|
+ nios2_num_regs,
|
|||
|
+ nios2_regmap,
|
|||
|
+ nios2_cannot_fetch_register,
|
|||
|
+ nios2_cannot_store_register,
|
|||
|
+ nios2_get_pc,
|
|||
|
+ nios2_set_pc,
|
|||
|
+ (const char *) &nios2_breakpoint,
|
|||
|
+ nios2_breakpoint_len,
|
|||
|
+ NULL,
|
|||
|
+ 0,
|
|||
|
+ nios2_breakpoint_at,
|
|||
|
+};
|
|||
|
diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c
|
|||
|
new file mode 100644
|
|||
|
index 0000000..e0712dd
|
|||
|
--- /dev/null
|
|||
|
+++ b/gdb/nios2-tdep.c
|
|||
|
@@ -0,0 +1,1610 @@
|
|||
|
+/* Target-machine dependent code for Nios2, for GDB.
|
|||
|
+ Copyright (C) 2003-2005
|
|||
|
+ by Peter Brookes (pbrookes@altera.com)
|
|||
|
+ and Andrew Draper (adraper@altera.com)
|
|||
|
+
|
|||
|
+ This file is part of GDB.
|
|||
|
+
|
|||
|
+ This program is free software; you can redistribute it and/or modify
|
|||
|
+ it under the terms of 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.
|
|||
|
+
|
|||
|
+ This program 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 a copy of the GNU General Public License
|
|||
|
+ along with this program; if not, write to the Free Software
|
|||
|
+ Foundation, Inc., 59 Temple Place - Suite 330,
|
|||
|
+ Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+#include "defs.h"
|
|||
|
+#include "frame.h"
|
|||
|
+#include "frame-unwind.h"
|
|||
|
+#include "frame-base.h"
|
|||
|
+#include "trad-frame.h"
|
|||
|
+#include "dwarf2-frame.h"
|
|||
|
+#include "symtab.h"
|
|||
|
+#include "inferior.h"
|
|||
|
+#include "gdbtypes.h"
|
|||
|
+#include "gdbcore.h"
|
|||
|
+#include "gdbcmd.h"
|
|||
|
+#include "target.h"
|
|||
|
+#include "dis-asm.h"
|
|||
|
+#include "regcache.h"
|
|||
|
+#include "value.h"
|
|||
|
+#include "symfile.h"
|
|||
|
+#include "arch-utils.h"
|
|||
|
+#include "floatformat.h"
|
|||
|
+#include "gdb_assert.h"
|
|||
|
+
|
|||
|
+/* To get entry_point_address. */
|
|||
|
+#include "objfiles.h"
|
|||
|
+
|
|||
|
+/* Nios II ISA specific encodings and macros */
|
|||
|
+#include "opcode/nios2.h"
|
|||
|
+
|
|||
|
+/* Macros */
|
|||
|
+
|
|||
|
+#define Z_REGNUM 0 /* Zero */
|
|||
|
+#define R2_REGNUM 2 /* used for return value */
|
|||
|
+#define R3_REGNUM 3 /* used for return value */
|
|||
|
+/* used for hidden zero argument to store ptr to struct return value */
|
|||
|
+#define R4_REGNUM 4
|
|||
|
+#define R7_REGNUM 7
|
|||
|
+#define GP_REGNUM 26 /* Global Pointer */
|
|||
|
+#undef SP_REGNUM
|
|||
|
+#define SP_REGNUM 27 /* Stack Pointer */
|
|||
|
+#undef FP_REGNUM
|
|||
|
+#define FP_REGNUM 28 /* Frame Pointer */
|
|||
|
+#define EA_REGNUM 29 /* Exception address */
|
|||
|
+#define BA_REGNUM 30 /* Breakpoint return address */
|
|||
|
+#define RA_REGNUM 31 /* Return address */
|
|||
|
+#undef PC_REGNUM
|
|||
|
+#define PC_REGNUM 32
|
|||
|
+#define STATUS_REGNUM 33 /* Ctrl registers */
|
|||
|
+#define ESTATUS_REGNUM 34
|
|||
|
+#define BSTATUS_REGNUM 35
|
|||
|
+#define IENABLE_REGNUM 36
|
|||
|
+#define IPENDING_REGNUM 37
|
|||
|
+#define CPUID_REGNUM 38
|
|||
|
+#define PTEADDR_REGNUM 41
|
|||
|
+#define TLBACC_REGNUM 42
|
|||
|
+#define TLBMISC_REGNUM 43
|
|||
|
+#define FIRST_ARGREG R4_REGNUM
|
|||
|
+#define LAST_ARGREG R7_REGNUM
|
|||
|
+/* Number of all registers */
|
|||
|
+#define NIOS2_NUM_REGS (44)
|
|||
|
+/* The maximum register number displayed to the user, */
|
|||
|
+/* as a result of typing "info reg" at the gdb prompt */
|
|||
|
+#define NIOS2_MAX_REG_DISPLAYED_REGNUM (38)
|
|||
|
+
|
|||
|
+#define NIOS2_OPCODE_SIZE 4
|
|||
|
+
|
|||
|
+/* Structures */
|
|||
|
+struct register_info
|
|||
|
+{
|
|||
|
+ int size;
|
|||
|
+ char *name;
|
|||
|
+ struct type **type;
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* The current value in the register is the value in r[base] at the start of
|
|||
|
+ * the function + offset ; unless base < 0 in which case it's unknown.
|
|||
|
+ */
|
|||
|
+typedef struct
|
|||
|
+{
|
|||
|
+ int reg;
|
|||
|
+ unsigned int offset;
|
|||
|
+
|
|||
|
+} REG_VALUE;
|
|||
|
+
|
|||
|
+
|
|||
|
+typedef struct
|
|||
|
+{
|
|||
|
+ int basereg;
|
|||
|
+ CORE_ADDR addr;
|
|||
|
+
|
|||
|
+} REG_SAVED;
|
|||
|
+
|
|||
|
+struct nios2_unwind_cache
|
|||
|
+{
|
|||
|
+ /* The frame's base, optionally used by the high-level debug info. */
|
|||
|
+ CORE_ADDR base;
|
|||
|
+
|
|||
|
+ /* The previous frame's inner most stack address. Used as this
|
|||
|
+ frame ID's stack_addr. */
|
|||
|
+ CORE_ADDR cfa;
|
|||
|
+
|
|||
|
+ /* The address of the first instruction in this function */
|
|||
|
+ CORE_ADDR pc;
|
|||
|
+
|
|||
|
+ /* Which register holds the return address for the frame. */
|
|||
|
+ int return_regnum;
|
|||
|
+
|
|||
|
+ /* Table indicating what changes have been made to each register */
|
|||
|
+ REG_VALUE reg_value[NIOS2_NUM_REGS];
|
|||
|
+
|
|||
|
+ /* Table indicating where each register has been saved. */
|
|||
|
+ REG_SAVED reg_saved[NIOS2_NUM_REGS];
|
|||
|
+};
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Function prototypes */
|
|||
|
+CORE_ADDR nios2_saved_pc_after_call (struct frame_info *fi);
|
|||
|
+
|
|||
|
+/* nios2_register_info_table[i] is the number of bytes of storage in
|
|||
|
+ GDB's register array occupied by register i. */
|
|||
|
+static struct register_info nios2_register_info_table[] = {
|
|||
|
+ /* 0 */ {4, "zero", &builtin_type_uint32},
|
|||
|
+ /* 1 */ {4, "at", &builtin_type_uint32},
|
|||
|
+ /* 2 */ {4, "r2", &builtin_type_uint32},
|
|||
|
+ /* 3 */ {4, "r3", &builtin_type_uint32},
|
|||
|
+ /* 4 */ {4, "r4", &builtin_type_uint32},
|
|||
|
+ /* 5 */ {4, "r5", &builtin_type_uint32},
|
|||
|
+ /* 6 */ {4, "r6", &builtin_type_uint32},
|
|||
|
+ /* 7 */ {4, "r7", &builtin_type_uint32},
|
|||
|
+ /* 8 */ {4, "r8", &builtin_type_uint32},
|
|||
|
+ /* 9 */ {4, "r9", &builtin_type_uint32},
|
|||
|
+ /* 10 */ {4, "r10", &builtin_type_uint32},
|
|||
|
+ /* 11 */ {4, "r11", &builtin_type_uint32},
|
|||
|
+ /* 12 */ {4, "r12", &builtin_type_uint32},
|
|||
|
+ /* 13 */ {4, "r13", &builtin_type_uint32},
|
|||
|
+ /* 14 */ {4, "r14", &builtin_type_uint32},
|
|||
|
+ /* 15 */ {4, "r15", &builtin_type_uint32},
|
|||
|
+ /* 16 */ {4, "r16", &builtin_type_uint32},
|
|||
|
+ /* 17 */ {4, "r17", &builtin_type_uint32},
|
|||
|
+ /* 18 */ {4, "r18", &builtin_type_uint32},
|
|||
|
+ /* 19 */ {4, "r19", &builtin_type_uint32},
|
|||
|
+ /* 20 */ {4, "r20", &builtin_type_uint32},
|
|||
|
+ /* 21 */ {4, "r21", &builtin_type_uint32},
|
|||
|
+ /* 22 */ {4, "r22", &builtin_type_uint32},
|
|||
|
+ /* 23 */ {4, "r23", &builtin_type_uint32},
|
|||
|
+ /* 24 */ {4, "et", &builtin_type_uint32},
|
|||
|
+ /* 25 */ {4, "bt", &builtin_type_uint32},
|
|||
|
+ /* 26 */ {4, "gp", &builtin_type_uint32},
|
|||
|
+ /* 27 */ {4, "sp", &builtin_type_uint32},
|
|||
|
+ /* 28 */ {4, "fp", &builtin_type_uint32},
|
|||
|
+ /* 29 */ {4, "ea", &builtin_type_uint32},
|
|||
|
+ /* 30 */ {4, "ba", &builtin_type_uint32},
|
|||
|
+ /* 31 */ {4, "ra", &builtin_type_uint32},
|
|||
|
+ /* 32 */ {4, "pc", &builtin_type_uint32},
|
|||
|
+ /* 33 */ {4, "status", &builtin_type_uint32},
|
|||
|
+ /* 34 */ {4, "estatus", &builtin_type_uint32},
|
|||
|
+ /* 35 */ {4, "bstatus", &builtin_type_uint32},
|
|||
|
+ /* 36 */ {4, "ienable", &builtin_type_uint32},
|
|||
|
+ /* 37 */ {4, "ipending", &builtin_type_uint32},
|
|||
|
+ /* 38 */ {4, "cpuid", &builtin_type_uint32},
|
|||
|
+ /* 39 */ {4, "ctl6", &builtin_type_uint32},
|
|||
|
+ /* 40 */ {4, "ctl7", &builtin_type_uint32},
|
|||
|
+ /* 41 */ {4, "pteaddr", &builtin_type_uint32},
|
|||
|
+ /* 42 */ {4, "tlbacc", &builtin_type_uint32},
|
|||
|
+ /* 43 */ {4, "tlbmisc", &builtin_type_uint32}
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* This array is a mapping from Dwarf-2 register
|
|||
|
+ numbering to GDB's */
|
|||
|
+static int nios2_dwarf2gdb_regno_map[] = {
|
|||
|
+ 0, 1, 2, 3,
|
|||
|
+ 4, 5, 6, 7,
|
|||
|
+ 8, 9, 10, 11,
|
|||
|
+ 12, 13, 14, 15,
|
|||
|
+ 16, 17, 18, 19,
|
|||
|
+ 20, 21, 22, 23,
|
|||
|
+ 24, 25,
|
|||
|
+ GP_REGNUM, /* 26 */
|
|||
|
+ SP_REGNUM, /* 27 */
|
|||
|
+ FP_REGNUM, /* 28 */
|
|||
|
+ EA_REGNUM, /* 29 */
|
|||
|
+ BA_REGNUM, /* 30 */
|
|||
|
+ RA_REGNUM, /* 31 */
|
|||
|
+ PC_REGNUM, /* 32 */
|
|||
|
+ STATUS_REGNUM, /* 33 */
|
|||
|
+ ESTATUS_REGNUM, /* 34 */
|
|||
|
+ BSTATUS_REGNUM, /* 35 */
|
|||
|
+ IENABLE_REGNUM, /* 36 */
|
|||
|
+ IPENDING_REGNUM, /* 37 */
|
|||
|
+ 38, 39, 40, 41, 42, 43
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* Dwarf-2 <-> GDB register numbers mapping. */
|
|||
|
+int
|
|||
|
+nios2_dwarf_reg_to_regnum (int dw_reg)
|
|||
|
+{
|
|||
|
+ if (dw_reg < 0 || dw_reg > NIOS2_NUM_REGS)
|
|||
|
+ {
|
|||
|
+ warning ("Dwarf-2 uses unmapped register #%d\n", dw_reg);
|
|||
|
+ return dw_reg;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return nios2_dwarf2gdb_regno_map[dw_reg];
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Same as read_memory_u6signed_integer, but don't report an error if
|
|||
|
+ can't read. */
|
|||
|
+int
|
|||
|
+nios2_read_memory_unsigned_integer (CORE_ADDR memaddr, int len, ULONGEST *ret)
|
|||
|
+{
|
|||
|
+ char buf[sizeof (ULONGEST)];
|
|||
|
+ int error;
|
|||
|
+
|
|||
|
+ error = target_read_memory (memaddr, buf, len);
|
|||
|
+ if (error != 0)
|
|||
|
+ return 0;
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ *ret = extract_unsigned_integer (buf, len);
|
|||
|
+ return 1;
|
|||
|
+ }
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Find the name for the specified NIOS2 regno */
|
|||
|
+static const char *
|
|||
|
+nios2_register_name (int regno)
|
|||
|
+{
|
|||
|
+ /* Don't display any registers after NIOS2_MAX_REG_DISPLAYED_REGNUM */
|
|||
|
+ if (regno < 0)
|
|||
|
+ return NULL;
|
|||
|
+ else if (regno > NIOS2_MAX_REG_DISPLAYED_REGNUM)
|
|||
|
+ return NULL;
|
|||
|
+ return nios2_register_info_table[regno].name;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Returns the default type for register N. */
|
|||
|
+static struct type *
|
|||
|
+nios2_register_type (struct gdbarch *gdbarch, int regno)
|
|||
|
+{
|
|||
|
+/* FIXME Do we need some checks on regno ? */
|
|||
|
+ return *nios2_register_info_table[regno].type;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* nios2_register_byte_table[i] is the offset into the register file of the
|
|||
|
+ start of register number i. We initialize this from
|
|||
|
+ nios2_register_info_table. */
|
|||
|
+int nios2_register_byte_table[NIOS2_NUM_REGS];
|
|||
|
+
|
|||
|
+/* Index within `registers' of the first byte of the space for register REGNO. */
|
|||
|
+int
|
|||
|
+nios2_register_byte (int regno)
|
|||
|
+{
|
|||
|
+ return nios2_register_byte_table[regno];
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Number of bytes of storage in the actual machine representation for
|
|||
|
+ register 'regno'. */
|
|||
|
+static int
|
|||
|
+nios2_register_raw_size (int regno)
|
|||
|
+{
|
|||
|
+ return nios2_register_info_table[regno].size;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Number of bytes of storage in the program's representation for
|
|||
|
+ register 'regno'. */
|
|||
|
+static int
|
|||
|
+nios2_register_virtual_size (int regno)
|
|||
|
+{
|
|||
|
+ return nios2_register_info_table[regno].size;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Return the GDB type object for the "standard" data type
|
|||
|
+ of data in register 'regno'. */
|
|||
|
+static struct type *
|
|||
|
+nios2_register_virtual_type (int regno)
|
|||
|
+{
|
|||
|
+ return *nios2_register_info_table[regno].type;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Does this register need conversion betwen raw and virtual formats */
|
|||
|
+int
|
|||
|
+nios2_register_convertible (int regno)
|
|||
|
+{
|
|||
|
+ if (nios2_register_raw_size (regno) == nios2_register_virtual_size (regno))
|
|||
|
+ return 0;
|
|||
|
+ else
|
|||
|
+ return 1;
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Given a return value in `regcache' with a type `valtype',
|
|||
|
+ extract and copy its value into `valbuf'. */
|
|||
|
+/* FIXME: check this function*/
|
|||
|
+void
|
|||
|
+nios2_extract_return_value (struct type *valtype, struct regcache *regcache, void *valbuf)
|
|||
|
+{
|
|||
|
+#ifdef PORTINGTO61
|
|||
|
+ int len = TYPE_LENGTH (valtype);
|
|||
|
+
|
|||
|
+ /* pointer types are returned in register r2,
|
|||
|
+ up to 16-bit types in r2
|
|||
|
+ up to 32-bit types in r2,r3 */
|
|||
|
+ if (len <= nios2_register_raw_size (R2_REGNUM))
|
|||
|
+ memcpy (valbuf, regbuf + REGISTER_BYTE (R2_REGNUM), len);
|
|||
|
+ else if (len <= (nios2_register_raw_size (R2_REGNUM)
|
|||
|
+ + nios2_register_raw_size (R3_REGNUM)))
|
|||
|
+ memcpy (valbuf, regbuf + REGISTER_BYTE (R2_REGNUM), len);
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ /* Can I get the returned value here ? */
|
|||
|
+ memset(valbuf, 0, len);
|
|||
|
+ }
|
|||
|
+#endif
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Write into appropriate registers a function return value
|
|||
|
+ of type TYPE, given in virtual format. */
|
|||
|
+/* FIXME: check if required */
|
|||
|
+void
|
|||
|
+nios2_store_return_value (struct type *valtype, void *valbuf)
|
|||
|
+{
|
|||
|
+#ifdef PORTINGTO61
|
|||
|
+ int len = TYPE_LENGTH (valtype);
|
|||
|
+
|
|||
|
+ /* return values of up to 8 bytes are returned in $r2 $r3 */
|
|||
|
+
|
|||
|
+ if (len <= nios2_register_raw_size (R2_REGNUM))
|
|||
|
+ write_register_bytes (REGISTER_BYTE (R2_REGNUM),
|
|||
|
+ valbuf,
|
|||
|
+ len);
|
|||
|
+ else if (len <= (nios2_register_raw_size (R2_REGNUM)
|
|||
|
+ + nios2_register_raw_size (R3_REGNUM)))
|
|||
|
+ write_register_bytes (REGISTER_BYTE (R2_REGNUM),
|
|||
|
+ valbuf,
|
|||
|
+ len);
|
|||
|
+#endif
|
|||
|
+}
|
|||
|
+
|
|||
|
+#ifdef PORTINGTO61
|
|||
|
+
|
|||
|
+/* Setup the function arguments for calling a function in the inferior. */
|
|||
|
+static CORE_ADDR
|
|||
|
+nios2_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
|
|||
|
+ int struct_return, CORE_ADDR struct_addr)
|
|||
|
+{
|
|||
|
+ int argreg;
|
|||
|
+ int argnum;
|
|||
|
+ struct stack_arg
|
|||
|
+ {
|
|||
|
+ int len;
|
|||
|
+ char *val;
|
|||
|
+ } *stack_args;
|
|||
|
+ int nstack_args = 0;
|
|||
|
+
|
|||
|
+ stack_args = (struct stack_arg *) alloca (nargs * sizeof (struct stack_arg));
|
|||
|
+
|
|||
|
+ /* The lowest register number containing arguments */
|
|||
|
+ argreg = FIRST_ARGREG;
|
|||
|
+
|
|||
|
+ /* Align the stack. It will be needed
|
|||
|
+ if we call a function which has argument overflow. */
|
|||
|
+ sp &= ~3;
|
|||
|
+
|
|||
|
+ /* If this function returns a struct which does not fit in the
|
|||
|
+ return registers, we must pass a buffer to the function
|
|||
|
+ which it can use to save the return value. */
|
|||
|
+ if (struct_return)
|
|||
|
+ write_register (R2_REGNUM, struct_addr);
|
|||
|
+
|
|||
|
+ /* FIXME: what about unions? */
|
|||
|
+ for (argnum = 0; argnum < nargs; argnum++)
|
|||
|
+ {
|
|||
|
+ char *val = (char *) VALUE_CONTENTS (args[argnum]);
|
|||
|
+ int len = TYPE_LENGTH (VALUE_TYPE (args[argnum]));
|
|||
|
+ struct type *type = VALUE_TYPE (args[argnum]);
|
|||
|
+ int olen;
|
|||
|
+
|
|||
|
+ if ((argreg <= LAST_ARGREG && len <= (LAST_ARGREG - argreg + 1) * DEPRECATED_REGISTER_SIZE)
|
|||
|
+ || (TYPE_CODE (type) == TYPE_CODE_STRUCT))
|
|||
|
+ {
|
|||
|
+ /* Something that will fit entirely into registers or go on the stack. */
|
|||
|
+ while (len > 0 && argreg <= LAST_ARGREG)
|
|||
|
+ { write_register (argreg, extract_unsigned_integer (val, DEPRECATED_REGISTER_SIZE));
|
|||
|
+
|
|||
|
+ argreg++;
|
|||
|
+ val += DEPRECATED_REGISTER_SIZE;
|
|||
|
+ len -= DEPRECATED_REGISTER_SIZE;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Any remainder for the stack is noted below... */
|
|||
|
+ }
|
|||
|
+ else if (TYPE_CODE (VALUE_TYPE (args[argnum])) != TYPE_CODE_STRUCT
|
|||
|
+ && len > DEPRECATED_REGISTER_SIZE)
|
|||
|
+ {
|
|||
|
+ /* All subsequent args go onto the stack. */
|
|||
|
+ argnum = LAST_ARGREG + 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (len > 0)
|
|||
|
+ {
|
|||
|
+ /* Note that this must be saved onto the stack */
|
|||
|
+ stack_args[nstack_args].val = val;
|
|||
|
+ stack_args[nstack_args].len = len;
|
|||
|
+ nstack_args++;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* We're done with registers and stack allocation. Now do the actual
|
|||
|
+ stack pushes. */
|
|||
|
+ while (nstack_args--)
|
|||
|
+ {
|
|||
|
+ sp -= stack_args[nstack_args].len;
|
|||
|
+ write_memory (sp, stack_args[nstack_args].val, stack_args[nstack_args].len);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Return adjusted stack pointer. */
|
|||
|
+ return sp;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Function: push_return_address (pc)
|
|||
|
+ Set up the return address for the inferior function call.*/
|
|||
|
+/* FIXME: Check if required */
|
|||
|
+static CORE_ADDR
|
|||
|
+nios2_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
|
|||
|
+{
|
|||
|
+ write_register (RA_REGNUM, CALL_DUMMY_ADDRESS ());
|
|||
|
+ return sp;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Extract from an array regcache containing the (raw) register state
|
|||
|
+ the address in which a function should return its structure value,
|
|||
|
+ as a CORE_ADDR (or an expression that can be used as one). */
|
|||
|
+/* FIXME: Check if required */
|
|||
|
+
|
|||
|
+static CORE_ADDR
|
|||
|
+nios2_extract_struct_value_address (char *regbuf)
|
|||
|
+{
|
|||
|
+ return (extract_address ((regbuf) + REGISTER_BYTE (R4_REGNUM),
|
|||
|
+ REGISTER_RAW_SIZE (R4_REGNUM)));
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Store the address of the place in which to copy the structure the
|
|||
|
+ subroutine will return. This is called from call_function. */
|
|||
|
+
|
|||
|
+/* FIXME: Check if required */
|
|||
|
+static void
|
|||
|
+nios2_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
|
|||
|
+{
|
|||
|
+ write_register (R4_REGNUM, (addr));
|
|||
|
+}
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+
|
|||
|
+/* This function analyzes the function prologue and tries to work
|
|||
|
+ out where registers are saved and how long the prologue is.
|
|||
|
+ The prologue will consist of the following parts:
|
|||
|
+ 1) Optional profiling instrumentation. The old version uses six
|
|||
|
+ instructions. We step over this if there is an exact match.
|
|||
|
+ nextpc r8
|
|||
|
+ mov r9, ra
|
|||
|
+ movhi r10, %hiadj(.LP2)
|
|||
|
+ addi r10, r10, %lo(.LP2)
|
|||
|
+ call mcount
|
|||
|
+ mov ra, r9
|
|||
|
+ The new version uses two or three instructions (the last of
|
|||
|
+ these might get merged in with the STW which saves RA to the
|
|||
|
+ stack). We interpret these.
|
|||
|
+ mov r8, ra
|
|||
|
+ call mcount
|
|||
|
+ mov ra, r8
|
|||
|
+
|
|||
|
+ 2) Optional interrupt entry decision. Again, we step over
|
|||
|
+ this if there is an exact match.
|
|||
|
+ rdctl et,estatus
|
|||
|
+ andi et,et,1
|
|||
|
+ beq et,zero, <software_exception>
|
|||
|
+ rdctl et,ipending
|
|||
|
+ beq et,zero, <software_exception>
|
|||
|
+
|
|||
|
+ 3) A stack adjustment or stack which, which will be one of:
|
|||
|
+ addi sp, sp, -constant
|
|||
|
+ or:
|
|||
|
+ movi r8, constant
|
|||
|
+ sub sp, sp, r8
|
|||
|
+ or
|
|||
|
+ movhi r8, constant
|
|||
|
+ addi r8, r8, constant
|
|||
|
+ sub sp, sp, r8
|
|||
|
+ or
|
|||
|
+ movhi rx, %hiadj(newstack)
|
|||
|
+ addhi rx, rx, %lo(newstack)
|
|||
|
+ stw sp, constant(rx)
|
|||
|
+ mov sp, rx
|
|||
|
+
|
|||
|
+ 4) An optional stack check, which can take either of these forms:
|
|||
|
+ bgeu sp, rx, +8
|
|||
|
+ break 3
|
|||
|
+ or
|
|||
|
+ bltu sp, rx, .Lstack_overflow
|
|||
|
+ ...
|
|||
|
+ .Lstack_overflow:
|
|||
|
+ break 3
|
|||
|
+
|
|||
|
+ 5) Saving any registers which need to be saved. These will
|
|||
|
+ normally just be stored onto the stack:
|
|||
|
+ stw rx, constant(sp)
|
|||
|
+ but in the large frame case will use r8 as an offset back
|
|||
|
+ to the cfa:
|
|||
|
+ add r8, r8, sp
|
|||
|
+ stw rx, -constant(r8)
|
|||
|
+
|
|||
|
+ Saving control registers looks slightly different:
|
|||
|
+ rdctl rx, ctlN
|
|||
|
+ stw rx, constant(sp)
|
|||
|
+
|
|||
|
+ 6) An optional FP setup, either if the user has requested a
|
|||
|
+ frame pointer or if the function calls alloca.
|
|||
|
+ This is always:
|
|||
|
+ mov fp, sp
|
|||
|
+
|
|||
|
+ The prologue instructions may be interleaved, and the register
|
|||
|
+ saves and FP setup can occur in either order.
|
|||
|
+
|
|||
|
+ To cope with all this variability we decode all the instructions
|
|||
|
+ from the start of the prologue until we hit a branch, call or
|
|||
|
+ return. For each of the instructions mentioned in 3, 4 and 5 we
|
|||
|
+ handle the limited cases of stores to the stack and operations
|
|||
|
+ on constant values.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+typedef struct
|
|||
|
+{
|
|||
|
+ unsigned int insn;
|
|||
|
+ unsigned int mask;
|
|||
|
+} wild_insn;
|
|||
|
+
|
|||
|
+static const wild_insn profiler_insn[] =
|
|||
|
+{
|
|||
|
+ { 0x0010e03a, 0x00000000 }, // nextpc r8
|
|||
|
+ { 0xf813883a, 0x00000000 }, // mov r9,ra
|
|||
|
+ { 0x02800034, 0x003FFFC0 }, // movhi r10,257
|
|||
|
+ { 0x52800004, 0x003FFFC0 }, // addi r10,r10,-31992
|
|||
|
+ { 0x00000000, 0xFFFFFFC0 }, // call <mcount>
|
|||
|
+ { 0x483f883a, 0x00000000 } // mov ra,r9
|
|||
|
+};
|
|||
|
+
|
|||
|
+static const wild_insn irqentry_insn[] =
|
|||
|
+{
|
|||
|
+ { 0x0031307a, 0x00000000 }, // rdctl et,estatus
|
|||
|
+ { 0xc600004c, 0x00000000 }, // andi et,et,1
|
|||
|
+ { 0xc0000026, 0x003FFFC0 }, // beq et,zero, <software_exception>
|
|||
|
+ { 0x0031313a, 0x00000000 }, // rdctl et,ipending
|
|||
|
+ { 0xc0000026, 0x003FFFC0 } // beq et,zero, <software_exception>
|
|||
|
+};
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_setup_default(struct nios2_unwind_cache *cache)
|
|||
|
+{
|
|||
|
+ int i;
|
|||
|
+
|
|||
|
+ for (i = 0; i < NIOS2_NUM_REGS; i++)
|
|||
|
+ {
|
|||
|
+ /* All registers start off holding their previous values */
|
|||
|
+ cache->reg_value[i].reg = i;
|
|||
|
+ cache->reg_value[i].offset = 0;
|
|||
|
+
|
|||
|
+ /* All registers start off not saved */
|
|||
|
+ cache->reg_saved[i].basereg = -1;
|
|||
|
+ cache->reg_saved[i].addr = 0;
|
|||
|
+ }
|
|||
|
+}
|
|||
|
+
|
|||
|
+static int
|
|||
|
+nios2_match_sequence(CORE_ADDR start_pc, const wild_insn * sequence, int count)
|
|||
|
+{
|
|||
|
+ CORE_ADDR pc = start_pc;
|
|||
|
+ int i;
|
|||
|
+ unsigned int insn;
|
|||
|
+
|
|||
|
+ for (i = 0 ; i < count ; i++)
|
|||
|
+ {
|
|||
|
+ insn = read_memory_unsigned_integer (pc, NIOS2_OPCODE_SIZE);
|
|||
|
+ if ((insn & ~sequence[i].mask) != sequence[i].insn)
|
|||
|
+ return 0;
|
|||
|
+
|
|||
|
+ pc += NIOS2_OPCODE_SIZE;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return 1;
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+CORE_ADDR
|
|||
|
+nios2_analyze_prologue (const CORE_ADDR start_pc, const CORE_ADDR current_pc,
|
|||
|
+ struct nios2_unwind_cache *cache, struct frame_info *next_frame)
|
|||
|
+{
|
|||
|
+ /* Maximum lines of prologue to check */
|
|||
|
+ /* Note that this number should not be too large, else we can potentially */
|
|||
|
+ /* end up iterating through unmapped memory */
|
|||
|
+ CORE_ADDR limit_pc = start_pc + 200;
|
|||
|
+ int regno;
|
|||
|
+
|
|||
|
+ /* Does the frame set up the FP register? */
|
|||
|
+ int base_reg = 0;
|
|||
|
+
|
|||
|
+ REG_VALUE * value = cache->reg_value;
|
|||
|
+ REG_VALUE temp_value[NIOS2_NUM_REGS];
|
|||
|
+
|
|||
|
+ int i;
|
|||
|
+
|
|||
|
+ /* Save the starting PC so we can correct the pc after running */
|
|||
|
+ /* through the prolog, using symbol info */
|
|||
|
+ CORE_ADDR pc = start_pc;
|
|||
|
+
|
|||
|
+ /* Is this an exception handler? */
|
|||
|
+ int exception_handler = 0;
|
|||
|
+
|
|||
|
+ /* What was the original value of SP (or fake original value for
|
|||
|
+ * functions which switch stacks?
|
|||
|
+ */
|
|||
|
+ CORE_ADDR frame_high;
|
|||
|
+
|
|||
|
+ /* Is this the end of the prologue? */
|
|||
|
+ int within_prologue = 1;
|
|||
|
+
|
|||
|
+ CORE_ADDR prologue_end;
|
|||
|
+
|
|||
|
+ /* Is this the innermost function? */
|
|||
|
+ int innermost = (frame_relative_level(next_frame) < 0);
|
|||
|
+
|
|||
|
+#ifdef DEBUG_PRINT
|
|||
|
+ fprintf_unfiltered (gdb_stdlog,
|
|||
|
+ "{ nios2_analyze_prologue start=0x%s, current=0x%s ",
|
|||
|
+ paddr_nz (start_pc), paddr_nz (current_pc));
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+ /* Set up the default values of the registers. */
|
|||
|
+ nios2_setup_default(cache);
|
|||
|
+
|
|||
|
+ /* If the first few instructions are the profile entry then skip over them. */
|
|||
|
+ /* Newer versions of the compiler use more efficient profiling code. */
|
|||
|
+ if (nios2_match_sequence(pc, profiler_insn, sizeof(profiler_insn)/sizeof(profiler_insn[0])))
|
|||
|
+ pc += sizeof(profiler_insn)/sizeof(profiler_insn[0]) * NIOS2_OPCODE_SIZE;
|
|||
|
+
|
|||
|
+ /* If the first few are an interrupt entry then skip over them too */
|
|||
|
+ if (nios2_match_sequence(pc, irqentry_insn, sizeof(irqentry_insn)/sizeof(irqentry_insn[0])))
|
|||
|
+ {
|
|||
|
+ pc += sizeof(irqentry_insn)/sizeof(irqentry_insn[0]) * NIOS2_OPCODE_SIZE;
|
|||
|
+ exception_handler = 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ prologue_end = start_pc;
|
|||
|
+
|
|||
|
+ /* Find the prologue instructions. */
|
|||
|
+ /* Fortunately we're in 32bit paradise */
|
|||
|
+ while (pc < limit_pc && within_prologue)
|
|||
|
+ {
|
|||
|
+ /* Present instruction. */
|
|||
|
+ unsigned int insn;
|
|||
|
+
|
|||
|
+ int prologue_insn = 0;
|
|||
|
+
|
|||
|
+ if (pc == current_pc)
|
|||
|
+ {
|
|||
|
+ /*
|
|||
|
+ * When we reach the current PC we must save the current register
|
|||
|
+ * state (for the backtrace) but keep analysing because there might
|
|||
|
+ * be more to find out (eg. is this an exception handler).
|
|||
|
+ */
|
|||
|
+ memcpy(temp_value, value, sizeof(temp_value));
|
|||
|
+ value = temp_value;
|
|||
|
+#ifdef DEBUG_PRINT
|
|||
|
+ fprintf_unfiltered (gdb_stdlog, "*");
|
|||
|
+#endif
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ insn = read_memory_unsigned_integer (pc, NIOS2_OPCODE_SIZE);
|
|||
|
+ pc += NIOS2_OPCODE_SIZE;
|
|||
|
+
|
|||
|
+#ifdef DEBUG_PRINT
|
|||
|
+ fprintf_unfiltered (gdb_stdlog, "[%08X]", insn);
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+ /* The following instructions can appear in the prologue */
|
|||
|
+
|
|||
|
+ if ((insn & 0x0001FFFF) == 0x0001883A)
|
|||
|
+ {
|
|||
|
+ /* ADD rc, ra, rb (also used for MOV) */
|
|||
|
+
|
|||
|
+ int ra = GET_IW_A(insn);
|
|||
|
+ int rb = GET_IW_B(insn);
|
|||
|
+ int rc = GET_IW_C(insn);
|
|||
|
+
|
|||
|
+ if (rc == SP_REGNUM && rb == 0 && value[ra].reg == cache->reg_saved[SP_REGNUM].basereg)
|
|||
|
+ {
|
|||
|
+ /* If the previous value of SP is available somewhere near the new
|
|||
|
+ * stack pointer value then this is a stack switch.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+ /* If any registers were saved on the stack before then we can't backtrace
|
|||
|
+ * into them now.
|
|||
|
+ */
|
|||
|
+ for (i = 0 ; i < NIOS2_NUM_REGS ; i++)
|
|||
|
+ {
|
|||
|
+ if (cache->reg_saved[i].basereg == SP_REGNUM)
|
|||
|
+ cache->reg_saved[i].basereg = -1;
|
|||
|
+ if (value[i].reg == SP_REGNUM)
|
|||
|
+ value[i].reg = -1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Create a fake "high water mark" 4 bytes above where SP was stored
|
|||
|
+ * and fake up the registers to be consistent with that.
|
|||
|
+ */
|
|||
|
+ value[SP_REGNUM].reg = SP_REGNUM;
|
|||
|
+ value[SP_REGNUM].offset = value[ra].offset - cache->reg_saved[SP_REGNUM].addr - 4;
|
|||
|
+
|
|||
|
+ cache->reg_saved[SP_REGNUM].basereg = SP_REGNUM;
|
|||
|
+ cache->reg_saved[SP_REGNUM].addr = -4;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if (rc != 0)
|
|||
|
+ {
|
|||
|
+ if (value[rb].reg == 0)
|
|||
|
+ value[rc].reg = value[ra].reg;
|
|||
|
+ else if (value[ra].reg == 0)
|
|||
|
+ value[rc].reg = value[rb].reg;
|
|||
|
+ else
|
|||
|
+ value[rc].reg = -1;
|
|||
|
+
|
|||
|
+ value[rc].offset = value[ra].offset + value[rb].offset;
|
|||
|
+ }
|
|||
|
+ prologue_insn = 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if ((insn & 0x0001FFFF) == 0x0001983A)
|
|||
|
+ {
|
|||
|
+ /* SUB rc, ra, rb */
|
|||
|
+
|
|||
|
+ int ra = GET_IW_A(insn);
|
|||
|
+ int rb = GET_IW_B(insn);
|
|||
|
+ int rc = GET_IW_C(insn);
|
|||
|
+
|
|||
|
+ if (rc != 0)
|
|||
|
+ {
|
|||
|
+ if (value[rb].reg == 0)
|
|||
|
+ value[rc].reg = value[ra].reg;
|
|||
|
+ else
|
|||
|
+ value[rc].reg = -1;
|
|||
|
+
|
|||
|
+ value[rc].offset = value[ra].offset - value[rb].offset;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if ((insn & 0x0000003F) == 0x00000004)
|
|||
|
+ {
|
|||
|
+ /* ADDI rb, ra, immed (also used for MOVI) */
|
|||
|
+ short immed = GET_IW_IMM16(insn);
|
|||
|
+ int ra = GET_IW_A(insn);
|
|||
|
+ int rb = GET_IW_B(insn);
|
|||
|
+
|
|||
|
+ if (rb == SP_REGNUM)
|
|||
|
+ {
|
|||
|
+ /* The first stack adjustment is part of the prologue. Any subsequent
|
|||
|
+ stack adjustments are either down to alloca or the epilogue so stop
|
|||
|
+ analysing when we hit them. */
|
|||
|
+ if (value[rb].offset != 0 || value[ra].reg != SP_REGNUM)
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (rb != 0)
|
|||
|
+ {
|
|||
|
+ value[rb].reg = value[ra].reg;
|
|||
|
+ value[rb].offset = value[ra].offset + immed;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ prologue_insn = 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if ((insn & 0x0000003F) == 0x00000034)
|
|||
|
+ {
|
|||
|
+ /* ORHI rb, ra, immed (also used for MOVHI) */
|
|||
|
+ unsigned int immed = GET_IW_IMM16(insn);
|
|||
|
+ int ra = GET_IW_A(insn);
|
|||
|
+ int rb = GET_IW_B(insn);
|
|||
|
+
|
|||
|
+ if (rb != 0)
|
|||
|
+ {
|
|||
|
+ value[rb].reg = (value[ra].reg == 0) ? 0 : -1;
|
|||
|
+ value[rb].offset = value[ra].offset | (immed << 16);
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if (((insn & IW_OP_MASK) == OP_STW || (insn & IW_OP_MASK) == OP_STWIO))
|
|||
|
+ {
|
|||
|
+ /* STW rb, immediate(ra) */
|
|||
|
+
|
|||
|
+ short immed16 = GET_IW_IMM16(insn);
|
|||
|
+ int ra = GET_IW_A(insn);
|
|||
|
+ int rb = GET_IW_B(insn);
|
|||
|
+
|
|||
|
+ /* Are we storing the original value of a register? For exception handlers
|
|||
|
+ * the value of EA-4 (return address from interrupts etc) is sometimes stored.
|
|||
|
+ */
|
|||
|
+ int orig = value[rb].reg;
|
|||
|
+ if (orig > 0 && (value[rb].offset == 0 || (orig == EA_REGNUM && value[rb].offset == -4)))
|
|||
|
+ {
|
|||
|
+ /* We are most interested in stores to the stack, but will also take note
|
|||
|
+ * of stores to other places as they might be useful later.
|
|||
|
+ */
|
|||
|
+ if ((value[ra].reg == SP_REGNUM && cache->reg_saved[orig].basereg != SP_REGNUM) ||
|
|||
|
+ cache->reg_saved[orig].basereg == -1)
|
|||
|
+ {
|
|||
|
+ if (pc < current_pc)
|
|||
|
+ {
|
|||
|
+ /* Save off callee saved registers */
|
|||
|
+ cache->reg_saved[orig].basereg = value[ra].reg;
|
|||
|
+ cache->reg_saved[orig].addr = value[ra].offset + GET_IW_IMM16(insn);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ prologue_insn = 1;
|
|||
|
+
|
|||
|
+ if (orig == EA_REGNUM || orig == ESTATUS_REGNUM)
|
|||
|
+ exception_handler = 1;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if ((insn & 0xFFC1F83F) == 0x0001303A)
|
|||
|
+ {
|
|||
|
+ /* RDCTL rC, ctlN */
|
|||
|
+ int rc = GET_IW_C(insn);
|
|||
|
+ int n = GET_IW_CONTROL_REGNUM(insn);
|
|||
|
+
|
|||
|
+ if (rc != 0)
|
|||
|
+ {
|
|||
|
+ value[rc].reg = STATUS_REGNUM + n;
|
|||
|
+ value[rc].offset = 0;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ prologue_insn = 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if ((insn & 0x0000003F) == 0 &&
|
|||
|
+ value[8].reg == RA_REGNUM && value[8].offset == 0 &&
|
|||
|
+ value[SP_REGNUM].reg == SP_REGNUM && value[SP_REGNUM].offset == 0)
|
|||
|
+ {
|
|||
|
+ /* A CALL instruction. This is treated as a call to mcount if ra
|
|||
|
+ * has been stored into r8 beforehand and if it's before the stack adjust.
|
|||
|
+ * mcount corrupts r2-r3, r9-r15 & ra
|
|||
|
+ */
|
|||
|
+ for (i = 2 ; i <= 3 ; i++)
|
|||
|
+ value[i].reg = -1;
|
|||
|
+ for (i = 9 ; i <= 15 ; i++)
|
|||
|
+ value[i].reg = -1;
|
|||
|
+ value[RA_REGNUM].reg = -1;
|
|||
|
+
|
|||
|
+ prologue_insn = 1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if ((insn & 0xF83FFFFF) == 0xD800012E)
|
|||
|
+ {
|
|||
|
+ /* BGEU sp, rx, +8
|
|||
|
+ * BREAK 3
|
|||
|
+ * This instruction sequence is used in stack checking - we can ignore it
|
|||
|
+ */
|
|||
|
+ unsigned int next_insn = read_memory_unsigned_integer(pc, NIOS2_OPCODE_SIZE);
|
|||
|
+
|
|||
|
+ if (next_insn != 0x003DA0FA)
|
|||
|
+ within_prologue = 0;
|
|||
|
+ else
|
|||
|
+ pc += NIOS2_OPCODE_SIZE;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ else if ((insn & 0xF800003F) == 0xD8000036)
|
|||
|
+ {
|
|||
|
+ /* BLTU sp, rx, .Lstackoverflow
|
|||
|
+ * If the location branched to holds a BREAK 3 instruction then this is
|
|||
|
+ * also stack overflow detection. We can ignore it.
|
|||
|
+ */
|
|||
|
+ CORE_ADDR target_pc = pc + ((insn & 0x3FFFC0) >> 6);
|
|||
|
+ unsigned int target_insn = read_memory_unsigned_integer(target_pc, NIOS2_OPCODE_SIZE);
|
|||
|
+
|
|||
|
+ if (target_insn != 0x003DA0FA)
|
|||
|
+ within_prologue = 0;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Any other instructions are allowed to be moved up into the prologue. If we
|
|||
|
+ reach a branch, call or return then the prologue is considered over */
|
|||
|
+ /* We also consider a second stack adjustment as terminating the prologue (see
|
|||
|
+ above) */
|
|||
|
+
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ switch (GET_IW_OP(insn))
|
|||
|
+ {
|
|||
|
+ case OP_BEQ:
|
|||
|
+ case OP_BGE:
|
|||
|
+ case OP_BGEU:
|
|||
|
+ case OP_BLT:
|
|||
|
+ case OP_BLTU:
|
|||
|
+ case OP_BNE:
|
|||
|
+ case OP_BR:
|
|||
|
+ case OP_CALL:
|
|||
|
+ within_prologue = 0;
|
|||
|
+ break;
|
|||
|
+ case OP_OPX:
|
|||
|
+ if (GET_IW_OPX(insn) == OPX_RET ||
|
|||
|
+ GET_IW_OPX(insn) == OPX_ERET ||
|
|||
|
+ GET_IW_OPX(insn) == OPX_BRET ||
|
|||
|
+ GET_IW_OPX(insn) == OPX_CALLR ||
|
|||
|
+ GET_IW_OPX(insn) == OPX_JMP)
|
|||
|
+ {
|
|||
|
+ within_prologue = 0;
|
|||
|
+ }
|
|||
|
+ default:
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (prologue_insn)
|
|||
|
+ prologue_end = pc;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Are we within the function epilogue? If so then we should go back to the
|
|||
|
+ original register values */
|
|||
|
+ if (innermost && current_pc > start_pc)
|
|||
|
+ {
|
|||
|
+ /* First check whether the previous instruction was a stack
|
|||
|
+ adjustment. */
|
|||
|
+ unsigned int insn = read_memory_unsigned_integer (current_pc - NIOS2_OPCODE_SIZE, NIOS2_OPCODE_SIZE);
|
|||
|
+
|
|||
|
+ if ((insn & 0xFFC0003C) == 0xDEC00004 || /* ADDI sp, sp, */
|
|||
|
+ (insn & 0xFFC1FFFF) == 0xDEC1883A || /* ADD sp, sp, */
|
|||
|
+ (insn & 0xFFC0003F) == 0xDEC00017) /* LDW sp, constant(sp) */
|
|||
|
+ {
|
|||
|
+ /* Then check if it's followed by a return or a tail call */
|
|||
|
+ insn = read_memory_unsigned_integer (current_pc, NIOS2_OPCODE_SIZE);
|
|||
|
+
|
|||
|
+ if (insn == 0xF800283A || /* RET */
|
|||
|
+ insn == 0xE800083A || /* ERET */
|
|||
|
+ (insn & 0x07FFFFFF) == 0x0000683A || /* JMP */
|
|||
|
+ (insn & 0xFFC0003F) == 6) /* BR */
|
|||
|
+ {
|
|||
|
+ /* Go back to default value of the registers */
|
|||
|
+ nios2_setup_default(cache);
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Exception handlers use a different return address register. */
|
|||
|
+ if (exception_handler)
|
|||
|
+ cache->return_regnum = EA_REGNUM;
|
|||
|
+
|
|||
|
+#ifdef DEBUG_PRINT
|
|||
|
+ fprintf_unfiltered (gdb_stdlog, "\n-> retreg=%d, ", cache->return_regnum);
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+ if (cache->reg_value[FP_REGNUM].reg == SP_REGNUM)
|
|||
|
+ {
|
|||
|
+ /* If the FP now holds an offset from the CFA then this is a normal
|
|||
|
+ frame which uses the frame pointer. */
|
|||
|
+ base_reg = FP_REGNUM;
|
|||
|
+ }
|
|||
|
+ else if (cache->reg_value[SP_REGNUM].reg == SP_REGNUM)
|
|||
|
+ {
|
|||
|
+ /* FP doesn't hold an offset from the CFA. If SP still holds an
|
|||
|
+ offset from the CFA then we might be in a function which omits
|
|||
|
+ the frame pointer, or we might be partway through the prologue.
|
|||
|
+ In both cases we can find the CFA using SP. */
|
|||
|
+ base_reg = SP_REGNUM;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ /* Somehow the stack pointer has been corrupted. We can't return. */
|
|||
|
+#ifdef DEBUG_PRINT
|
|||
|
+ fprintf_unfiltered (gdb_stdlog, "<can't reach cfa> }\n");
|
|||
|
+#endif
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (cache->reg_value[base_reg].offset == 0 ||
|
|||
|
+ cache->reg_saved[RA_REGNUM].basereg != SP_REGNUM ||
|
|||
|
+ cache->reg_saved[cache->return_regnum].basereg != SP_REGNUM)
|
|||
|
+ {
|
|||
|
+ /*
|
|||
|
+ * If the frame didn't adjust the stack, didn't save RA or didn't save
|
|||
|
+ * EA in an exception handler then it must either be a leaf function
|
|||
|
+ * (doesn't call any other functions) or it can't return. If it has
|
|||
|
+ * called another function then it can't be a leaf, so set base == 0
|
|||
|
+ * to indicate that we can't backtrace past it.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+ if (!innermost)
|
|||
|
+ {
|
|||
|
+ /* If it isn't the innermost function then it can't be a leaf, unless
|
|||
|
+ * it was interrupted. Check whether RA for this frame is the same
|
|||
|
+ * as PC. If so then it probably wan't interrupted.
|
|||
|
+ */
|
|||
|
+ char buf[8];
|
|||
|
+ CORE_ADDR ra;
|
|||
|
+
|
|||
|
+ frame_unwind_register (next_frame, RA_REGNUM, buf);
|
|||
|
+ ra = extract_typed_address (buf, builtin_type_void_func_ptr);
|
|||
|
+
|
|||
|
+ if (ra == current_pc)
|
|||
|
+ {
|
|||
|
+#ifdef DEBUG_PRINT
|
|||
|
+ fprintf_unfiltered (gdb_stdlog, "<noreturn ADJUST 0x%s, r31@r%d+?>, r%d@r%d+?> }\n",
|
|||
|
+ paddr_nz(cache->reg_value[base_reg].offset),
|
|||
|
+ cache->reg_saved[RA_REGNUM].basereg,
|
|||
|
+ cache->return_regnum, cache->reg_saved[cache->return_regnum].basereg);
|
|||
|
+#endif
|
|||
|
+ return 0;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Get the value of whichever register we are using for the base. */
|
|||
|
+ cache->base = frame_unwind_register_unsigned (next_frame, base_reg);
|
|||
|
+
|
|||
|
+ /* What was the value of SP at the start of this function (or just
|
|||
|
+ * after the stack switch).
|
|||
|
+ */
|
|||
|
+ frame_high = cache->base - cache->reg_value[base_reg].offset;
|
|||
|
+
|
|||
|
+ /* Adjust all the saved registers such that they contain addresses
|
|||
|
+ instead of offsets. */
|
|||
|
+ for (i = 0; i < NIOS2_NUM_REGS; i++)
|
|||
|
+ if (cache->reg_saved[i].basereg == SP_REGNUM)
|
|||
|
+ {
|
|||
|
+ cache->reg_saved[i].basereg = Z_REGNUM;
|
|||
|
+ cache->reg_saved[i].addr += frame_high;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ for (i = 0; i < NIOS2_NUM_REGS; i++)
|
|||
|
+ if (cache->reg_saved[i].basereg == GP_REGNUM)
|
|||
|
+ {
|
|||
|
+ CORE_ADDR gp = frame_unwind_register_unsigned (next_frame, GP_REGNUM);
|
|||
|
+
|
|||
|
+ for ( ; i < NIOS2_NUM_REGS; i++)
|
|||
|
+ if (cache->reg_saved[i].basereg == GP_REGNUM)
|
|||
|
+ {
|
|||
|
+ cache->reg_saved[i].basereg = Z_REGNUM;
|
|||
|
+ cache->reg_saved[i].addr += gp;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Work out what the value of SP was on the first instruction of this
|
|||
|
+ * function. If we didn't switch stacks then this can be trivially
|
|||
|
+ * computed from the base address.
|
|||
|
+ */
|
|||
|
+ if (cache->reg_saved[SP_REGNUM].basereg == Z_REGNUM)
|
|||
|
+ {
|
|||
|
+ cache->cfa = read_memory_unsigned_integer(cache->reg_saved[SP_REGNUM].addr, 4);
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ cache->cfa = frame_high;
|
|||
|
+
|
|||
|
+ /* Exception handlers restore ESTATUS into STATUS. */
|
|||
|
+ if (exception_handler)
|
|||
|
+ {
|
|||
|
+ cache->reg_saved[STATUS_REGNUM] = cache->reg_saved[ESTATUS_REGNUM];
|
|||
|
+ cache->reg_saved[ESTATUS_REGNUM].basereg = -1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+#ifdef DEBUG_PRINT
|
|||
|
+ fprintf_unfiltered (gdb_stdlog, "cfa=0x%s }\n", paddr_nz(cache->cfa));
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+ return prologue_end;
|
|||
|
+}
|
|||
|
+
|
|||
|
+struct frame_info *
|
|||
|
+setup_arbitrary_frame (int argc, CORE_ADDR *argv)
|
|||
|
+{
|
|||
|
+ if (argc != 2)
|
|||
|
+ error ("Nios II frame specifications require two arguments: sp and pc");
|
|||
|
+
|
|||
|
+ return create_new_frame (argv[0], argv[1]);
|
|||
|
+}
|
|||
|
+
|
|||
|
+#ifdef PORTINGTO61
|
|||
|
+/* Should be handled by unwind informations. */
|
|||
|
+/* However, doing this manually until we can find */
|
|||
|
+/* use the CFA information to examine the stack */
|
|||
|
+void
|
|||
|
+nios2_frame_init_saved_regs (struct frame_info *fi)
|
|||
|
+{
|
|||
|
+ CORE_ADDR ip;
|
|||
|
+
|
|||
|
+ /* Examine the entire prologue. */
|
|||
|
+ register int frameless_p = 0;
|
|||
|
+
|
|||
|
+ /* Has this frame's registers already been initialized? */
|
|||
|
+ if (fi->saved_regs)
|
|||
|
+ return;
|
|||
|
+
|
|||
|
+ frame_saved_regs_zalloc (fi);
|
|||
|
+
|
|||
|
+ ip = get_pc_function_start (fi->pc);
|
|||
|
+ nios2_examine (ip, fi, frameless_p);
|
|||
|
+}
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Given a PC value corresponding to the start of a function, return the PC
|
|||
|
+ of the first instruction after the function prologue. */
|
|||
|
+
|
|||
|
+CORE_ADDR
|
|||
|
+nios2_skip_prologue (CORE_ADDR start_pc)
|
|||
|
+{
|
|||
|
+ CORE_ADDR func_addr, func_end;
|
|||
|
+ struct symtab_and_line sal;
|
|||
|
+ CORE_ADDR pc_after_prologue;
|
|||
|
+
|
|||
|
+ /* If we have line debugging information, then the end of the prologue
|
|||
|
+ should the first assembly instruction of the first source line. */
|
|||
|
+ if (find_pc_partial_function (start_pc, NULL, &func_addr, &func_end))
|
|||
|
+ {
|
|||
|
+ sal = find_pc_line (func_addr, 0);
|
|||
|
+ if (sal.end > 0 && sal.end < func_end)
|
|||
|
+ return sal.end;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return start_pc;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* nios2_software_single_step() is called just before we want to resume
|
|||
|
+ the inferior, if we want to single-step it but there is no hardware
|
|||
|
+ or kernel single-step support (NIOS2 on GNU/Linux for example). We find
|
|||
|
+ the target of the coming instruction and breakpoint it.
|
|||
|
+
|
|||
|
+ single_step is also called just after the inferior stops. If we had
|
|||
|
+ set up a simulated single-step, we undo our damage. */
|
|||
|
+
|
|||
|
+void
|
|||
|
+nios2_software_single_step (enum target_signal sig, int insert_breakpoints_p)
|
|||
|
+{
|
|||
|
+ int ii;
|
|||
|
+ unsigned int insn;
|
|||
|
+ CORE_ADDR pc;
|
|||
|
+ CORE_ADDR breaks[2];
|
|||
|
+ int imme;
|
|||
|
+
|
|||
|
+ if (insert_breakpoints_p)
|
|||
|
+ {
|
|||
|
+ pc = read_pc ();
|
|||
|
+ breaks[0] = pc + 4;
|
|||
|
+ breaks[1] = -1;
|
|||
|
+ insn = read_memory_unsigned_integer (pc, 4);
|
|||
|
+
|
|||
|
+ /* Calculate the destination of a branch/jump */
|
|||
|
+ switch (GET_IW_OP(insn))
|
|||
|
+ {
|
|||
|
+ /* I-type branch */
|
|||
|
+ case OP_BEQ:
|
|||
|
+ case OP_BGE:
|
|||
|
+ case OP_BGEU:
|
|||
|
+ case OP_BLT:
|
|||
|
+ case OP_BLTU:
|
|||
|
+ case OP_BNE:
|
|||
|
+ imme = (short) GET_IW_IMM16(insn);
|
|||
|
+ breaks[1] = pc + 4 + imme;
|
|||
|
+ break;
|
|||
|
+ case OP_BR:
|
|||
|
+ imme = (short) GET_IW_IMM16(insn);
|
|||
|
+ breaks[0] = pc + 4 + imme;
|
|||
|
+ break;
|
|||
|
+ /* J-type branch */
|
|||
|
+ case OP_CALL:
|
|||
|
+ case OP_JMPI:
|
|||
|
+ imme = GET_IW_IMM26(insn);
|
|||
|
+ breaks[0] = (pc & 0xf0000000) | (imme * 4);
|
|||
|
+ break;
|
|||
|
+ /* R-type branch */
|
|||
|
+ case OP_OPX:
|
|||
|
+ switch (GET_IW_OPX(insn))
|
|||
|
+ {
|
|||
|
+ case OPX_CALLR:
|
|||
|
+ case OPX_JMP:
|
|||
|
+ case OPX_RET:
|
|||
|
+ imme = read_register (GET_IW_A(insn));
|
|||
|
+ breaks[0] = imme;
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Don't put two breakpoints on the same address. */
|
|||
|
+ if (breaks[1] == breaks[0])
|
|||
|
+ breaks[1] = -1;
|
|||
|
+
|
|||
|
+ for (ii = 0; ii < 2; ++ii)
|
|||
|
+ {
|
|||
|
+ /* ignore invalid breakpoint. */
|
|||
|
+ if (breaks[ii] == -1)
|
|||
|
+ continue;
|
|||
|
+ insert_single_step_breakpoint (breaks[ii]);
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ remove_single_step_breakpoints ();
|
|||
|
+
|
|||
|
+}
|
|||
|
+
|
|||
|
+const unsigned char*
|
|||
|
+nios2_breakpoint_from_pc (CORE_ADDR *bp_addr, int *bp_size)
|
|||
|
+{
|
|||
|
+ /* break encoding: 31->27 26->22 21->17 16->11 10->6 5->0 */
|
|||
|
+ /* 00000 00000 0x1e 0x34 00000 0x3a */
|
|||
|
+ /* 00000 00000 11110 110100 00000 111010 */
|
|||
|
+ /* In bytes: 00000000 00111101 10100000 00111010 */
|
|||
|
+ /* 0x0 0x3d 0xa0 0x3a */
|
|||
|
+#if 0
|
|||
|
+ static unsigned char breakpoint[] = {0x3a, 0xa0, 0x3d, 0x0};
|
|||
|
+#else
|
|||
|
+ static unsigned char breakpoint[] = {0x7a, 0x68, 0x3b, 0x0}; /* Trap instr. w/imm=0x01 */
|
|||
|
+#endif
|
|||
|
+ *bp_size = 4;
|
|||
|
+ return breakpoint;
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+int
|
|||
|
+gdb_print_insn_nios2 (bfd_vma memaddr, disassemble_info *info)
|
|||
|
+{
|
|||
|
+ if (info->endian == BFD_ENDIAN_BIG)
|
|||
|
+ {
|
|||
|
+ return print_insn_big_nios2 (memaddr, info);
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ return print_insn_little_nios2 (memaddr, info);
|
|||
|
+ }
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Adjust the address downward (direction of stack growth) so that it
|
|||
|
+ is correctly aligned for a new stack frame. */
|
|||
|
+
|
|||
|
+/* ??? Big endian issues here? */
|
|||
|
+
|
|||
|
+static CORE_ADDR
|
|||
|
+nios2_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
|
|||
|
+{
|
|||
|
+ return align_down (addr, 4);
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/* We don't convert anything at the moment */
|
|||
|
+static int
|
|||
|
+nios2_convert_register_p (int regnum, struct type *type)
|
|||
|
+{
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_register_to_value (struct frame_info *frame, int regnum,
|
|||
|
+ struct type *type, void *to)
|
|||
|
+{
|
|||
|
+ get_frame_register (frame, regnum + 0, (char *) to + 0);
|
|||
|
+ get_frame_register (frame, regnum + 0, (char *) to + 0);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_value_to_register (struct frame_info *frame, int regnum,
|
|||
|
+ struct type *type, const void *from)
|
|||
|
+{
|
|||
|
+ put_frame_register (frame, regnum + 0, (const char *) from + 0);
|
|||
|
+ put_frame_register (frame, regnum + 0, (const char *) from + 0);
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Determine, for architecture GDBARCH, how a return value of TYPE
|
|||
|
+ should be returned. If it is supposed to be returned in registers,
|
|||
|
+ and READBUF is non-zero, read the appropriate value from REGCACHE,
|
|||
|
+ and copy it into READBUF. If WRITEBUF is non-zero, write the value
|
|||
|
+ from WRITEBUF into REGCACHE. */
|
|||
|
+
|
|||
|
+static enum return_value_convention
|
|||
|
+nios2_return_value (struct gdbarch *gdbarch, struct type *type,
|
|||
|
+ struct regcache *regcache, void *readbuf,
|
|||
|
+ const void *writebuf)
|
|||
|
+{
|
|||
|
+ enum type_code code = TYPE_CODE (type);
|
|||
|
+
|
|||
|
+ /* FIXME PBrookes add struct return function */
|
|||
|
+ if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
|
|||
|
+ /*&& !nios2_reg_struct_return_p (gdbarch, type)*/)
|
|||
|
+ return RETURN_VALUE_STRUCT_CONVENTION;
|
|||
|
+
|
|||
|
+
|
|||
|
+ if (readbuf)
|
|||
|
+ nios2_extract_return_value (type, regcache, readbuf);
|
|||
|
+ if (writebuf)
|
|||
|
+ nios2_store_return_value (type, regcache);
|
|||
|
+
|
|||
|
+ return RETURN_VALUE_REGISTER_CONVENTION;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
|
|||
|
+ dummy frame. The frame ID's base needs to match the TOS value
|
|||
|
+ saved by save_dummy_frame_tos() and returned from
|
|||
|
+ nios2_push_dummy_call, and the PC needs to match the dummy frame's
|
|||
|
+ breakpoint. */
|
|||
|
+
|
|||
|
+static struct frame_id
|
|||
|
+nios2_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
|||
|
+{
|
|||
|
+ return frame_id_build (frame_unwind_register_unsigned (next_frame, SP_REGNUM),
|
|||
|
+ frame_pc_unwind (next_frame));
|
|||
|
+}
|
|||
|
+
|
|||
|
+static CORE_ADDR
|
|||
|
+nios2_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
|||
|
+{
|
|||
|
+ char buf[8];
|
|||
|
+
|
|||
|
+ frame_unwind_register (next_frame, PC_REGNUM, buf);
|
|||
|
+ return extract_typed_address (buf, builtin_type_void_func_ptr);
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Frame base handling. */
|
|||
|
+
|
|||
|
+struct nios2_unwind_cache *
|
|||
|
+nios2_frame_unwind_cache (struct frame_info *next_frame,
|
|||
|
+ void **this_prologue_cache)
|
|||
|
+{
|
|||
|
+ CORE_ADDR current_pc;
|
|||
|
+ struct nios2_unwind_cache *cache;
|
|||
|
+ int i;
|
|||
|
+
|
|||
|
+ if (*this_prologue_cache)
|
|||
|
+ return *this_prologue_cache;
|
|||
|
+
|
|||
|
+ cache = FRAME_OBSTACK_ZALLOC (struct nios2_unwind_cache);
|
|||
|
+ (*this_prologue_cache) = cache;
|
|||
|
+
|
|||
|
+ /* Zero all fields. */
|
|||
|
+ cache->base = 0;
|
|||
|
+ cache->cfa = 0;
|
|||
|
+ cache->pc = 0;
|
|||
|
+
|
|||
|
+ cache->return_regnum = RA_REGNUM;
|
|||
|
+
|
|||
|
+ nios2_setup_default(cache);
|
|||
|
+
|
|||
|
+ cache->pc = frame_func_unwind (next_frame);
|
|||
|
+ current_pc = frame_pc_unwind (next_frame);
|
|||
|
+
|
|||
|
+ /* Prologue analysis does the rest... */
|
|||
|
+ if (cache->pc != 0)
|
|||
|
+ nios2_analyze_prologue (cache->pc, current_pc, cache, next_frame);
|
|||
|
+
|
|||
|
+ return cache;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_frame_this_id (struct frame_info *next_frame, void **this_cache,
|
|||
|
+ struct frame_id *this_id)
|
|||
|
+{
|
|||
|
+ struct nios2_unwind_cache *cache =
|
|||
|
+ nios2_frame_unwind_cache (next_frame, this_cache);
|
|||
|
+
|
|||
|
+ /* This marks the outermost frame. */
|
|||
|
+ if (cache->base == 0)
|
|||
|
+ return;
|
|||
|
+
|
|||
|
+ (*this_id) = frame_id_build (cache->cfa, cache->pc);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
+nios2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
|
|||
|
+ int regnum, int *optimizedp,
|
|||
|
+ enum lval_type *lvalp, CORE_ADDR *addrp,
|
|||
|
+ int *realnump, void *valuep)
|
|||
|
+{
|
|||
|
+ struct nios2_unwind_cache *cache =
|
|||
|
+ nios2_frame_unwind_cache (next_frame, this_cache);
|
|||
|
+
|
|||
|
+ gdb_assert (regnum >= 0);
|
|||
|
+
|
|||
|
+ /* The PC of the previous frame is stored in the RA register of
|
|||
|
+ the current frame. Frob regnum so that we pull the value from
|
|||
|
+ the correct place. */
|
|||
|
+ if (regnum == PC_REGNUM)
|
|||
|
+ regnum = cache->return_regnum;
|
|||
|
+
|
|||
|
+ /* If we've worked out where a register is stored then load it from there.
|
|||
|
+ */
|
|||
|
+ if (regnum < NIOS2_NUM_REGS && cache->reg_saved[regnum].basereg == Z_REGNUM)
|
|||
|
+ {
|
|||
|
+ *optimizedp = 0;
|
|||
|
+ *lvalp = lval_memory;
|
|||
|
+ *addrp = cache->reg_saved[regnum].addr;
|
|||
|
+ *realnump = -1;
|
|||
|
+ if (valuep)
|
|||
|
+ {
|
|||
|
+ /* Read the value in from memory. */
|
|||
|
+ read_memory (*addrp, valuep,
|
|||
|
+ register_size (current_gdbarch, regnum));
|
|||
|
+ }
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (regnum == SP_REGNUM && cache->cfa)
|
|||
|
+ {
|
|||
|
+ *optimizedp = 0;
|
|||
|
+ *lvalp = not_lval;
|
|||
|
+ *addrp = 0;
|
|||
|
+ *realnump = -1;
|
|||
|
+ if (valuep)
|
|||
|
+ {
|
|||
|
+ /* Store the value. */
|
|||
|
+ store_unsigned_integer (valuep, 8, cache->cfa);
|
|||
|
+ }
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ frame_register_unwind (next_frame, regnum,
|
|||
|
+ optimizedp, lvalp, addrp, realnump, valuep);
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+static const struct frame_unwind nios2_frame_unwind =
|
|||
|
+{
|
|||
|
+ NORMAL_FRAME,
|
|||
|
+ nios2_frame_this_id,
|
|||
|
+ nios2_frame_prev_register
|
|||
|
+};
|
|||
|
+
|
|||
|
+static CORE_ADDR
|
|||
|
+nios2_frame_base_address (struct frame_info *next_frame, void **this_cache)
|
|||
|
+{
|
|||
|
+ struct nios2_unwind_cache *info
|
|||
|
+ = nios2_frame_unwind_cache (next_frame, this_cache);
|
|||
|
+ return info->base;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static const struct frame_base nios2_frame_base =
|
|||
|
+{
|
|||
|
+ &nios2_frame_unwind,
|
|||
|
+ nios2_frame_base_address,
|
|||
|
+ nios2_frame_base_address,
|
|||
|
+ nios2_frame_base_address
|
|||
|
+};
|
|||
|
+
|
|||
|
+static const struct frame_unwind *
|
|||
|
+nios2_frame_sniffer (struct frame_info *next_frame)
|
|||
|
+{
|
|||
|
+ return &nios2_frame_unwind;
|
|||
|
+}
|
|||
|
+
|
|||
|
+
|
|||
|
+static struct gdbarch *
|
|||
|
+nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
|
+{
|
|||
|
+ struct gdbarch *gdbarch;
|
|||
|
+ int register_bytes, i;
|
|||
|
+
|
|||
|
+ /* Change the register names based on the current machine type. */
|
|||
|
+ if (info.bfd_arch_info->arch != bfd_arch_nios2)
|
|||
|
+ return NULL;
|
|||
|
+
|
|||
|
+ /* None found, create a new architecture from the information
|
|||
|
+ provided. We don't have any architecture specific state, so just
|
|||
|
+ pass in 0 for the struct gdbarch_tdep parameter. */
|
|||
|
+ gdbarch = gdbarch_alloc (&info, NULL);
|
|||
|
+
|
|||
|
+ /* Data type sizes. */
|
|||
|
+ set_gdbarch_ptr_bit (gdbarch, 32);
|
|||
|
+ set_gdbarch_addr_bit (gdbarch, 32);
|
|||
|
+ set_gdbarch_short_bit (gdbarch, 16);
|
|||
|
+ set_gdbarch_int_bit (gdbarch, 32);
|
|||
|
+ set_gdbarch_long_bit (gdbarch, 32);
|
|||
|
+ set_gdbarch_long_long_bit (gdbarch, 64);
|
|||
|
+ set_gdbarch_float_bit (gdbarch, 32);
|
|||
|
+ set_gdbarch_double_bit (gdbarch, 64);
|
|||
|
+
|
|||
|
+ switch (info.byte_order)
|
|||
|
+ {
|
|||
|
+ case BFD_ENDIAN_BIG:
|
|||
|
+ set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
|
|||
|
+ set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ case BFD_ENDIAN_LITTLE:
|
|||
|
+ set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
|
|||
|
+ set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ default:
|
|||
|
+ internal_error (__FILE__, __LINE__,
|
|||
|
+ "nios2_gdbarch_init: bad byte ordering");
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* The register set. */
|
|||
|
+ set_gdbarch_num_regs (gdbarch, NIOS2_NUM_REGS);
|
|||
|
+ set_gdbarch_sp_regnum (gdbarch, SP_REGNUM);
|
|||
|
+ set_gdbarch_pc_regnum (gdbarch, PC_REGNUM); /* Pseudo register PC */
|
|||
|
+
|
|||
|
+ set_gdbarch_register_name (gdbarch, nios2_register_name);
|
|||
|
+ /* Length of ordinary registers used in push_word and a few other
|
|||
|
+ places. DEPRECATED_REGISTER_RAW_SIZE is the real way to know how
|
|||
|
+ big a register is. */
|
|||
|
+/* FIXME
|
|||
|
+ set_gdbarch_deprecated_register_size (gdbarch, 4);
|
|||
|
+ set_gdbarch_deprecated_register_virtual_type (gdbarch,
|
|||
|
+ nios2_register_virtual_type);
|
|||
|
+*/
|
|||
|
+
|
|||
|
+ set_gdbarch_register_type (gdbarch, nios2_register_type);
|
|||
|
+
|
|||
|
+ /* The "default" register numbering scheme for AMD64 is referred to
|
|||
|
+ as the "DWARF Register Number Mapping" in the System V psABI.
|
|||
|
+ The preferred debugging format for all known Nios II targets is
|
|||
|
+ actually DWARF2, and GCC doesn't seem to support DWARF (that is
|
|||
|
+ DWARF-1), but we provide the same mapping just in case. This
|
|||
|
+ mapping is also used for stabs, which GCC does support. */
|
|||
|
+ set_gdbarch_stab_reg_to_regnum (gdbarch, nios2_dwarf_reg_to_regnum);
|
|||
|
+ set_gdbarch_dwarf_reg_to_regnum (gdbarch, nios2_dwarf_reg_to_regnum);
|
|||
|
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, nios2_dwarf_reg_to_regnum);
|
|||
|
+
|
|||
|
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
|
|||
|
+
|
|||
|
+ /* Call dummy code. */
|
|||
|
+ set_gdbarch_frame_align (gdbarch, nios2_frame_align);
|
|||
|
+
|
|||
|
+ /* Some registers require conversion from raw format to virtual format. */
|
|||
|
+/* FIXME
|
|||
|
+ set_gdbarch_deprecated_register_convertible (gdbarch, nios2_register_convertible);
|
|||
|
+*/
|
|||
|
+
|
|||
|
+ set_gdbarch_convert_register_p (gdbarch, nios2_convert_register_p);
|
|||
|
+ set_gdbarch_register_to_value (gdbarch, nios2_register_to_value);
|
|||
|
+ set_gdbarch_value_to_register (gdbarch, nios2_value_to_register);
|
|||
|
+
|
|||
|
+ set_gdbarch_return_value (gdbarch, nios2_return_value);
|
|||
|
+
|
|||
|
+ set_gdbarch_skip_prologue (gdbarch, nios2_skip_prologue);
|
|||
|
+ set_gdbarch_breakpoint_from_pc (gdbarch, nios2_breakpoint_from_pc);
|
|||
|
+ set_gdbarch_software_single_step (gdbarch, nios2_software_single_step);
|
|||
|
+
|
|||
|
+ set_gdbarch_unwind_dummy_id (gdbarch, nios2_unwind_dummy_id);
|
|||
|
+ set_gdbarch_unwind_pc (gdbarch, nios2_unwind_pc);
|
|||
|
+
|
|||
|
+ /* The dwarf2 unwinder will normally produce the best results if the
|
|||
|
+ debug information is available, so register it first. */
|
|||
|
+ frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
|
|||
|
+
|
|||
|
+ /* FIXME: PBrookes - copied from AMD64-TDEP.c (kettenis/20021026):
|
|||
|
+ This is ELF-specific. Fine for now, since all supported NIOS II
|
|||
|
+ targets are ELF, but that might change in the future. */
|
|||
|
+/* FIXME again.. Does not exist anymore...
|
|||
|
+ set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
|
|||
|
+*/
|
|||
|
+
|
|||
|
+ frame_unwind_append_sniffer (gdbarch, nios2_frame_sniffer);
|
|||
|
+
|
|||
|
+ frame_base_set_default (gdbarch, &nios2_frame_base);
|
|||
|
+
|
|||
|
+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_nios2);
|
|||
|
+
|
|||
|
+ return gdbarch;
|
|||
|
+}
|
|||
|
+
|
|||
|
+void
|
|||
|
+_initialize_nios2_tdep (void)
|
|||
|
+{
|
|||
|
+ register_gdbarch_init (bfd_arch_nios2, nios2_gdbarch_init);
|
|||
|
+
|
|||
|
+ int i, offset = 0;
|
|||
|
+
|
|||
|
+ /* Do not display anything after NIOS2_MAX_REG_DISPLAYED_REGNUM */
|
|||
|
+ for (i = 0; i <= NIOS2_MAX_REG_DISPLAYED_REGNUM; i++)
|
|||
|
+ {
|
|||
|
+ nios2_register_byte_table[i] = offset;
|
|||
|
+ offset += nios2_register_info_table[i].size;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ for (i = NIOS2_MAX_REG_DISPLAYED_REGNUM + 1; i <= NIOS2_NUM_REGS; i++)
|
|||
|
+ {
|
|||
|
+ nios2_register_byte_table[i] = -1;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+}
|
|||
|
diff --git a/gdb/regformats/reg-nios2.dat b/gdb/regformats/reg-nios2.dat
|
|||
|
new file mode 100644
|
|||
|
index 0000000..77b39a9
|
|||
|
--- /dev/null
|
|||
|
+++ b/gdb/regformats/reg-nios2.dat
|
|||
|
@@ -0,0 +1,46 @@
|
|||
|
+name:nios2
|
|||
|
+expedite:sp,fp,pc
|
|||
|
+32:zero
|
|||
|
+32:at
|
|||
|
+32:r2
|
|||
|
+32:r3
|
|||
|
+32:r4
|
|||
|
+32:r5
|
|||
|
+32:r6
|
|||
|
+32:r7
|
|||
|
+32:r8
|
|||
|
+32:r9
|
|||
|
+32:r10
|
|||
|
+32:r11
|
|||
|
+32:r12
|
|||
|
+32:r13
|
|||
|
+32:r14
|
|||
|
+32:r15
|
|||
|
+32:r16
|
|||
|
+32:r17
|
|||
|
+32:r18
|
|||
|
+32:r19
|
|||
|
+32:r20
|
|||
|
+32:r21
|
|||
|
+32:r22
|
|||
|
+32:r23
|
|||
|
+32:et
|
|||
|
+32:bt
|
|||
|
+32:gp
|
|||
|
+32:sp
|
|||
|
+32:fp
|
|||
|
+32:ea
|
|||
|
+32:ba
|
|||
|
+32:ra
|
|||
|
+32:pc
|
|||
|
+32:status
|
|||
|
+32:estatus
|
|||
|
+32:bstatus
|
|||
|
+32:ienable
|
|||
|
+32:ipending
|
|||
|
+32:cpuid
|
|||
|
+32:ctl6
|
|||
|
+32:ctl7
|
|||
|
+32:pteaddr
|
|||
|
+32:tlbacc
|
|||
|
+32:tlbmisc
|
|||
|
diff --git a/gdb/testsuite/config/nios2-iss.exp b/gdb/testsuite/config/nios2-iss.exp
|
|||
|
new file mode 100644
|
|||
|
index 0000000..624f831
|
|||
|
--- /dev/null
|
|||
|
+++ b/gdb/testsuite/config/nios2-iss.exp
|
|||
|
@@ -0,0 +1,233 @@
|
|||
|
+# Test framework for GDB (remote protocol) using a "gdbserver",
|
|||
|
+# ie. a debug agent running as a native process on the same or
|
|||
|
+# a different host.
|
|||
|
+
|
|||
|
+# Copyright 2000, 2002 Free Software Foundation, Inc.
|
|||
|
+
|
|||
|
+# This program is free software; you can redistribute it and/or modify
|
|||
|
+# it under the terms of 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.
|
|||
|
+#
|
|||
|
+# This program 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 a copy of the GNU General Public License
|
|||
|
+# along with this program; if not, write to the Free Software
|
|||
|
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
+
|
|||
|
+# Please email any bugs, comments, and/or additions to this file to:
|
|||
|
+# bug-gdb@prep.ai.mit.edu
|
|||
|
+
|
|||
|
+# This file was written by Michael Snyder. (msnyder@redhat.com)
|
|||
|
+
|
|||
|
+#
|
|||
|
+# This module to be used for testing gdb with a "gdbserver"
|
|||
|
+# built either from libremote or from gdb/gdbserver.
|
|||
|
+#
|
|||
|
+
|
|||
|
+# Load the basic testing library, and the remote stuff.
|
|||
|
+load_lib ../config/monitor.exp
|
|||
|
+
|
|||
|
+#
|
|||
|
+# To be addressed or set in your baseboard config file:
|
|||
|
+#
|
|||
|
+# set_board_info gdb_protocol "remote"
|
|||
|
+# Unles you have a gdbserver that uses a different protocol...
|
|||
|
+#
|
|||
|
+# set_board_info use_gdb_stub 1
|
|||
|
+# This tells the rest of the test suite not to do things
|
|||
|
+# like "run" which don't work well on remote targets.
|
|||
|
+#
|
|||
|
+# set_board_info gdb,do_reload_on_run 1
|
|||
|
+# Unles you have a gdbserver that can handle multiple sessions.
|
|||
|
+#
|
|||
|
+# set_board_info noargs 1
|
|||
|
+# At present there is no provision in the remote protocol
|
|||
|
+# for passing arguments. This test framework does not
|
|||
|
+# address the issue, so it's best to set this variable
|
|||
|
+# in your baseboard configuration file.
|
|||
|
+# FIXME: there's no reason why the test harness couldn't
|
|||
|
+# pass commandline args when it spawns gdbserver.
|
|||
|
+#
|
|||
|
+# set_board_info gdb,noinferiorio 1
|
|||
|
+# Neither the traditional gdbserver nor the one in libremote
|
|||
|
+# can presently capture stdout and relay it to GDB via the
|
|||
|
+# 'O' packet. This means that tests involving printf will
|
|||
|
+# fail unles you set this varibale in your baseboard
|
|||
|
+# configuration file.
|
|||
|
+#
|
|||
|
+# set_board_info gdb,no_hardware_watchpoints 1
|
|||
|
+# Unles you have a gdbserver that supports hardware watchpoints.
|
|||
|
+# FIXME: gdb should detect if the target doesn't support them,
|
|||
|
+# and fall back to using software watchpoints.
|
|||
|
+#
|
|||
|
+# set_board_info gdb_server_prog
|
|||
|
+# This will be the path to the gdbserver program you want to test.
|
|||
|
+# Defaults to "gdbserver".
|
|||
|
+#
|
|||
|
+# set_board_info sockethost
|
|||
|
+# The name of the host computer whose socket is being used.
|
|||
|
+# Defaults to "localhost". Note: old gdbserver requires
|
|||
|
+# that you define this, but libremote/gdbserver does not.
|
|||
|
+#
|
|||
|
+# set_board_info socketport
|
|||
|
+# Port id to use for socket connection. If not set explicitly,
|
|||
|
+# it will start at "9996" and increment for each use.
|
|||
|
+#
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+#
|
|||
|
+# gdb_load -- load a file into the debugger.
|
|||
|
+# return a -1 if anything goes wrong.
|
|||
|
+#
|
|||
|
+
|
|||
|
+global server_exec;
|
|||
|
+global portnum;
|
|||
|
+set portnum "9996";
|
|||
|
+
|
|||
|
+proc gdb_load { arg } {
|
|||
|
+ global host_exec;
|
|||
|
+ global server_exec;
|
|||
|
+ global portnum;
|
|||
|
+ global verbose;
|
|||
|
+ global gdb_prompt;
|
|||
|
+
|
|||
|
+ regsub "/cygdrive/c" $arg "c:" arg
|
|||
|
+ regsub "/cygdrive/d" $arg "d:" arg
|
|||
|
+ regsub "/cygdrive/e" $arg "e:" arg
|
|||
|
+ regsub "/cygdrive/q" $arg "q:" arg
|
|||
|
+ regsub "/cygdrive/r" $arg "r:" arg
|
|||
|
+
|
|||
|
+ # Always kill and restart quest (or try to before loading)
|
|||
|
+ slay quest
|
|||
|
+ slay gdb
|
|||
|
+
|
|||
|
+ # Port id -- either specified in baseboard file, or managed here.
|
|||
|
+ if [target_info exists gdb,socketport] {
|
|||
|
+ set portnum [target_info gdb,socketport];
|
|||
|
+ } else {
|
|||
|
+ # Bump the port number to avoid conflicts with hung ports.
|
|||
|
+ incr portnum;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ verbose "gdb_load : portnum = $portnum arg = $arg"
|
|||
|
+ # Extract the local and remote host ids from the target board struct.
|
|||
|
+
|
|||
|
+ if [target_info exists sockethost] {
|
|||
|
+ set debughost [target_info sockethost];
|
|||
|
+ } else {
|
|||
|
+ set debughost "localhost:";
|
|||
|
+ }
|
|||
|
+ # Extract the protocol
|
|||
|
+ if [target_info exists gdb_protocol] {
|
|||
|
+ set protocol [target_info gdb_protocol];
|
|||
|
+ } else {
|
|||
|
+ set protocol "remote";
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ # Extract the name of the gdbserver, if known (default 'gdbserver').
|
|||
|
+ if [target_info exists gdb_server_prog] {
|
|||
|
+ set gdbserver [target_info gdb_server_prog];
|
|||
|
+ } else {
|
|||
|
+ set gdbserver "gdbserver";
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ verbose "gdbserver is set to $gdbserver"
|
|||
|
+ # Extract the socket hostname
|
|||
|
+ if [target_info exists sockethost] {
|
|||
|
+ set sockethost [target_info sockethost];
|
|||
|
+ } else {
|
|||
|
+ set sockethost ""
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ # Export the host:port pair.
|
|||
|
+ set gdbport $debughost$portnum;
|
|||
|
+ verbose "gdbport is now $gdbport"
|
|||
|
+ # Remember new exec file.
|
|||
|
+ if { $arg == "" } {
|
|||
|
+ if { ! [info exists host_exec] } {
|
|||
|
+ send_gdb "info files\n";
|
|||
|
+ gdb_expect 30 {
|
|||
|
+ -re "Symbols from \"(\[^\"\]+)\"" {
|
|||
|
+ set host_exec $expect_out(1,string);
|
|||
|
+ exp_continue;
|
|||
|
+ }
|
|||
|
+ -re "Local exec file:\[\r\n\]+\[ \t\]*`(\[^'\]+)'," {
|
|||
|
+ set host_exec $expect_out(1,string);
|
|||
|
+ exp_continue;
|
|||
|
+ }
|
|||
|
+ -re "$gdb_prompt $" { }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ } else {
|
|||
|
+ set host_exec $arg
|
|||
|
+ if [info exists server_exec] { unset server_exec }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ # Fire off the debug agent
|
|||
|
+ if [target_info exists gdb_server_args] {
|
|||
|
+ # This flavour of gdbserver takes as arguments those specified
|
|||
|
+ # in the board configuration file
|
|||
|
+ set custom_args [target_info gdb_server_args];
|
|||
|
+ set launch_return [eval remote_spawn host \{ $gdbserver $custom_args \} $arg ]
|
|||
|
+ verbose "spawned $gdbserver $custom_args $arg with return code $launch_return"
|
|||
|
+ } else {
|
|||
|
+ # This flavour of gdbserver takes as arguments the port information
|
|||
|
+ # and the name of the executable file to be debugged.
|
|||
|
+ set server_spawn_id [remote_spawn target\
|
|||
|
+ "$gdbserver $sockethost$portnum "]
|
|||
|
+ verbose "remote_spawn $gdbserver $sockethost$portnum"
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ # We can't call close, because if gdbserver is local then that means
|
|||
|
+ # that it will get a SIGHUP.
|
|||
|
+ ## close -i $server_spawn_id
|
|||
|
+ #wait -nowait -i $server_spawn_id
|
|||
|
+
|
|||
|
+ # Give it a little time to establish
|
|||
|
+ sleep 1
|
|||
|
+
|
|||
|
+ # tell gdb what file we are debugging
|
|||
|
+ if { $arg != "" } {
|
|||
|
+ if [gdb_file_cmd $arg] {
|
|||
|
+ return -1;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ verbose "gdb_file_cmd has been called with $arg"
|
|||
|
+
|
|||
|
+ # attach to the "serial port"
|
|||
|
+ gdb_target_cmd $protocol $gdbport;
|
|||
|
+
|
|||
|
+ # do the real load if needed
|
|||
|
+ if [target_info exists gdb_server_do_load] {
|
|||
|
+ send_gdb "load\n"
|
|||
|
+ set timeout 2400
|
|||
|
+ verbose "Timeout is now $timeout seconds" 2
|
|||
|
+ gdb_expect {
|
|||
|
+ -re ".*$gdb_prompt $" {
|
|||
|
+ if $verbose>1 then {
|
|||
|
+ send_user "Loaded $arg into $GDB\n"
|
|||
|
+ }
|
|||
|
+ set timeout 30
|
|||
|
+ verbose "Timeout is now $timeout seconds" 2
|
|||
|
+ return 1
|
|||
|
+ }
|
|||
|
+ -re "$gdb_prompt $" {
|
|||
|
+ if $verbose>1 then {
|
|||
|
+ perror "GDB couldn't load."
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ timeout {
|
|||
|
+ if $verbose>1 then {
|
|||
|
+ perror "Timed out trying to load $arg."
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
diff --git a/include/dis-asm.h b/include/dis-asm.h
|
|||
|
index af48e85..e3d84ab 100644
|
|||
|
--- a/include/dis-asm.h
|
|||
|
+++ b/include/dis-asm.h
|
|||
|
@@ -280,6 +280,8 @@ extern int print_insn_xtensa (bfd_vma, disassemble_info *);
|
|||
|
extern int print_insn_z80 (bfd_vma, disassemble_info *);
|
|||
|
extern int print_insn_z8001 (bfd_vma, disassemble_info *);
|
|||
|
extern int print_insn_z8002 (bfd_vma, disassemble_info *);
|
|||
|
+extern int print_insn_little_nios2 (bfd_vma, disassemble_info *);
|
|||
|
+extern int print_insn_big_nios2 (bfd_vma, disassemble_info *);
|
|||
|
|
|||
|
extern disassembler_ftype arc_get_disassembler (void *);
|
|||
|
extern disassembler_ftype cris_get_disassembler (bfd *);
|
|||
|
diff --git a/include/elf/nios2.h b/include/elf/nios2.h
|
|||
|
new file mode 100644
|
|||
|
index 0000000..ef810c5
|
|||
|
--- /dev/null
|
|||
|
+++ b/include/elf/nios2.h
|
|||
|
@@ -0,0 +1,65 @@
|
|||
|
+/* Altera New Jersey ELF support for BFD
|
|||
|
+
|
|||
|
+ Copyright (C) 2003
|
|||
|
+ by Nigel Gray (ngray@altera.com).
|
|||
|
+
|
|||
|
+This file is part of BFD, the Binary File Descriptor library.
|
|||
|
+
|
|||
|
+This program is free software; you can redistribute it and/or modify
|
|||
|
+it under the terms of 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.
|
|||
|
+
|
|||
|
+This program 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 a copy of the GNU General Public License
|
|||
|
+along with this program; if not, write to the Free Software
|
|||
|
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+/* This file holds definitions specific to the Altera New Jersey ELF ABI. Note
|
|||
|
+ that most of this is not actually implemented by BFD. */
|
|||
|
+
|
|||
|
+#ifndef _ELF_NIOS2_H
|
|||
|
+#define _ELF_NIOS2_H
|
|||
|
+
|
|||
|
+#include "elf/reloc-macros.h"
|
|||
|
+
|
|||
|
+/* the order of these numbers must match the order in
|
|||
|
+ the elf_nios2_howto_table_rel table for the lookup
|
|||
|
+ function to work properly */
|
|||
|
+
|
|||
|
+START_RELOC_NUMBERS (elf_nios2_reloc_type)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_NONE, 0)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_S16, 1)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_U16, 2)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_PCREL16, 3)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_CALL26, 4)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_IMM5, 5)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_CACHE_OPX, 6)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_IMM6, 7)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_IMM8, 8)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_HI16, 9)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_LO16, 10)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_HIADJ16, 11)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_BFD_RELOC_32, 12)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_BFD_RELOC_16, 13)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_BFD_RELOC_8, 14)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_GPREL, 15)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_GNU_VTINHERIT, 16)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_GNU_VTENTRY, 17)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_UJMP, 18)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_CJMP, 19)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_CALLR, 20)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_ALIGN, 21)
|
|||
|
+ RELOC_NUMBER (R_NIOS2_ILLEGAL, 22)
|
|||
|
+END_RELOC_NUMBERS (R_NIOS2_maxext)
|
|||
|
+
|
|||
|
+/* Processor specific section flags */
|
|||
|
+
|
|||
|
+/* This is used to mark gp-relative sections */
|
|||
|
+#define SHF_NIOS2_GPREL 0x10000000
|
|||
|
+
|
|||
|
+#endif //_ELF_NIOS2_H
|
|||
|
diff --git a/include/opcode/nios2-isa.h b/include/opcode/nios2-isa.h
|
|||
|
new file mode 100644
|
|||
|
index 0000000..0023880
|
|||
|
--- /dev/null
|
|||
|
+++ b/include/opcode/nios2-isa.h
|
|||
|
@@ -0,0 +1,1860 @@
|
|||
|
+/*
|
|||
|
+ * This file defines Nios II instruction set constants.
|
|||
|
+ * To include it in assembly code (.S file), define ALT_ASM_SRC
|
|||
|
+ * before including this file.
|
|||
|
+ *
|
|||
|
+ * This file is automatically generated by gen_isa.pl - do not edit
|
|||
|
+ */
|
|||
|
+
|
|||
|
+#ifndef _NIOS2_ISA_H_
|
|||
|
+#define _NIOS2_ISA_H_
|
|||
|
+
|
|||
|
+/* OP instruction opcode values (index is OP field) */
|
|||
|
+#define NUM_OP_INSTS 64
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern const char* op_names[NUM_OP_INSTS];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+/* OPX instruction opcode values (index is OPX field) */
|
|||
|
+#define NUM_OPX_INSTS 64
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern const char* opx_names[NUM_OPX_INSTS];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+/* Constants for instruction fields and ISA */
|
|||
|
+#define CPU_RESET_EXC_ID 1
|
|||
|
+#define DIV_ERROR_EXC_ID 9
|
|||
|
+#define DTLB_MISS_EXC_ID 15
|
|||
|
+#define DTLB_PERM_EXC_ID 16
|
|||
|
+#define FAST_INTR_EXC_ID 3
|
|||
|
+#define HBREAK_EXC_ID 0
|
|||
|
+#define ITLB_MISS_EXC_ID 13
|
|||
|
+#define ITLB_PERM_EXC_ID 14
|
|||
|
+#define MISALIGNED_DATA_ADDR_EXC_ID 7
|
|||
|
+#define MISALIGNED_TARGET_PC_EXC_ID 8
|
|||
|
+#define NMI_EXC_ID 2
|
|||
|
+#define NORM_INTR_EXC_ID 4
|
|||
|
+#define SBREAK_EXC_ID 6
|
|||
|
+#define SLAVE_DATA_ACCESS_ERROR_EXC_ID 18
|
|||
|
+#define SLAVE_INST_ACCESS_ERROR_EXC_ID 17
|
|||
|
+#define SUPERVISOR_DATA_ADDR_EXC_ID 12
|
|||
|
+#define SUPERVISOR_INST_ADDR_EXC_ID 10
|
|||
|
+#define SUPERVISOR_INST_EXC_ID 11
|
|||
|
+#define TRAP_EXC_ID 5
|
|||
|
+#define AT_REGNUM 1
|
|||
|
+#define BRETADDR_REGNUM 30
|
|||
|
+#define BSTATUS_REG_LSB 2
|
|||
|
+#define BSTATUS_REG_MMU_LSB 0
|
|||
|
+#define BSTATUS_REG_MMU_MSB 2
|
|||
|
+#define BSTATUS_REG_MMU_SZ 3
|
|||
|
+#define BSTATUS_REG_MMU_MASK 0x7
|
|||
|
+#define BSTATUS_REG_NO_MMU_LSB 0
|
|||
|
+#define BSTATUS_REG_NO_MMU_MSB 0
|
|||
|
+#define BSTATUS_REG_NO_MMU_SZ 1
|
|||
|
+#define BSTATUS_REG_NO_MMU_MASK 0x1
|
|||
|
+#define BSTATUS_REG_REGNUM 2
|
|||
|
+#define BSTATUS_REG_SZ 3
|
|||
|
+#define BSTATUS_REG_MASK 0x7
|
|||
|
+#define BT_REGNUM 25
|
|||
|
+#define CACHE_MAX_BYTES 65536
|
|||
|
+#define CACHE_MAX_LINE_BYTES 32
|
|||
|
+#define CACHE_MIN_LINE_BYTES 4
|
|||
|
+#define COMPARE_OP_EQ 0x0
|
|||
|
+#define COMPARE_OP_GE 0x1
|
|||
|
+#define COMPARE_OP_LSB 3
|
|||
|
+#define COMPARE_OP_LT 0x2
|
|||
|
+#define COMPARE_OP_MSB 4
|
|||
|
+#define COMPARE_OP_NE 0x3
|
|||
|
+#define COMPARE_OP_SZ 2
|
|||
|
+#define COMPARE_OP_MASK 0x3
|
|||
|
+#define CPUID_REG_LSB 0
|
|||
|
+#define CPUID_REG_MSB 31
|
|||
|
+#define CPUID_REG_REGNUM 5
|
|||
|
+#define CPUID_REG_SZ 32
|
|||
|
+#define CPUID_REG_MASK 0xffffffff
|
|||
|
+#define DATAPATH_LOG2_SZ 5
|
|||
|
+#define DATAPATH_LOG2_MASK 0x1f
|
|||
|
+#define DATAPATH_LSB 0
|
|||
|
+#define DATAPATH_MSB 31
|
|||
|
+#define DATAPATH_SZ 32
|
|||
|
+#define DATAPATH_MASK 0xffffffff
|
|||
|
+#define EMPTY_CRST_IW 127034
|
|||
|
+#define EMPTY_HBREAK_IW 4040762
|
|||
|
+#define EMPTY_INTR_IW 3926074
|
|||
|
+#define EMPTY_NOP_IW 100410
|
|||
|
+#define EMPTY_RET_IW 4160759866
|
|||
|
+#define ERETADDR_REGNUM 29
|
|||
|
+#define ESTATUS_REG_LSB 0
|
|||
|
+#define ESTATUS_REG_MMU_LSB 0
|
|||
|
+#define ESTATUS_REG_MMU_MSB 2
|
|||
|
+#define ESTATUS_REG_MMU_SZ 3
|
|||
|
+#define ESTATUS_REG_MMU_MASK 0x7
|
|||
|
+#define ESTATUS_REG_MSB 2
|
|||
|
+#define ESTATUS_REG_NO_MMU_LSB 0
|
|||
|
+#define ESTATUS_REG_NO_MMU_MSB 0
|
|||
|
+#define ESTATUS_REG_NO_MMU_SZ 1
|
|||
|
+#define ESTATUS_REG_NO_MMU_MASK 0x1
|
|||
|
+#define ESTATUS_REG_REGNUM 1
|
|||
|
+#define ESTATUS_REG_SZ 3
|
|||
|
+#define ESTATUS_REG_MASK 0x7
|
|||
|
+#define ET_REGNUM 24
|
|||
|
+#define EXCEPTION_REG_LSB 0
|
|||
|
+#define EXCEPTION_REG_MEA_LSB 0
|
|||
|
+#define EXCEPTION_REG_MEA_MSB 0
|
|||
|
+#define EXCEPTION_REG_MEA_SZ 1
|
|||
|
+#define EXCEPTION_REG_MEA_MASK 0x1
|
|||
|
+#define EXCEPTION_REG_MEE_LSB 1
|
|||
|
+#define EXCEPTION_REG_MEE_MSB 1
|
|||
|
+#define EXCEPTION_REG_MEE_SZ 1
|
|||
|
+#define EXCEPTION_REG_MEE_MASK 0x1
|
|||
|
+#define EXCEPTION_REG_MSB 1
|
|||
|
+#define EXCEPTION_REG_REGNUM 7
|
|||
|
+#define EXCEPTION_REG_SZ 2
|
|||
|
+#define EXCEPTION_REG_MASK 0x3
|
|||
|
+#define FP_REGNUM 28
|
|||
|
+#define FSTATUS_REG_REGNUM 11
|
|||
|
+#define GP_REGNUM 26
|
|||
|
+#define IENABLE_REG_LSB 0
|
|||
|
+#define IENABLE_REG_MSB 31
|
|||
|
+#define IENABLE_REG_REGNUM 3
|
|||
|
+#define IENABLE_REG_SZ 32
|
|||
|
+#define IENABLE_REG_MASK 0xffffffff
|
|||
|
+#define IPENDING_REG_LSB 0
|
|||
|
+#define IPENDING_REG_MSB 31
|
|||
|
+#define IPENDING_REG_REGNUM 4
|
|||
|
+#define IPENDING_REG_SZ 32
|
|||
|
+#define IPENDING_REG_MASK 0xffffffff
|
|||
|
+#define IW_A_LSB 27
|
|||
|
+#define IW_A_MSB 31
|
|||
|
+#define IW_A_SZ 5
|
|||
|
+#define IW_A_MASK 0x1f
|
|||
|
+#define IW_B_LSB 22
|
|||
|
+#define IW_B_MSB 26
|
|||
|
+#define IW_B_SZ 5
|
|||
|
+#define IW_B_MASK 0x1f
|
|||
|
+#define IW_C_LSB 17
|
|||
|
+#define IW_C_MSB 21
|
|||
|
+#define IW_C_SZ 5
|
|||
|
+#define IW_C_MASK 0x1f
|
|||
|
+#define IW_CONTROL_REGNUM_BASE 0
|
|||
|
+#define IW_CONTROL_REGNUM_LSB 6
|
|||
|
+#define IW_CONTROL_REGNUM_MSB 9
|
|||
|
+#define IW_CONTROL_REGNUM_SZ 4
|
|||
|
+#define IW_CONTROL_REGNUM_MASK 0xf
|
|||
|
+#define IW_CUSTOM_N_LSB 6
|
|||
|
+#define IW_CUSTOM_N_MSB 13
|
|||
|
+#define IW_CUSTOM_N_SZ 8
|
|||
|
+#define IW_CUSTOM_N_MASK 0xff
|
|||
|
+#define IW_CUSTOM_READRA_LSB 16
|
|||
|
+#define IW_CUSTOM_READRA_MSB 16
|
|||
|
+#define IW_CUSTOM_READRA_SZ 1
|
|||
|
+#define IW_CUSTOM_READRA_MASK 0x1
|
|||
|
+#define IW_CUSTOM_READRB_LSB 15
|
|||
|
+#define IW_CUSTOM_READRB_MSB 15
|
|||
|
+#define IW_CUSTOM_READRB_SZ 1
|
|||
|
+#define IW_CUSTOM_READRB_MASK 0x1
|
|||
|
+#define IW_CUSTOM_WRITERC_LSB 14
|
|||
|
+#define IW_CUSTOM_WRITERC_MSB 14
|
|||
|
+#define IW_CUSTOM_WRITERC_SZ 1
|
|||
|
+#define IW_CUSTOM_WRITERC_MASK 0x1
|
|||
|
+#define IW_IMM16_LSB 6
|
|||
|
+#define IW_IMM16_MSB 21
|
|||
|
+#define IW_IMM16_SZ 16
|
|||
|
+#define IW_IMM16_MASK 0xffff
|
|||
|
+#define IW_IMM26_LSB 6
|
|||
|
+#define IW_IMM26_MSB 31
|
|||
|
+#define IW_IMM26_SZ 26
|
|||
|
+#define IW_IMM26_MASK 0x3ffffff
|
|||
|
+#define IW_MEMSZ_BYTE 0x0
|
|||
|
+#define IW_MEMSZ_HWORD 0x1
|
|||
|
+#define IW_MEMSZ_LSB 3
|
|||
|
+#define IW_MEMSZ_MSB 4
|
|||
|
+#define IW_MEMSZ_SZ 2
|
|||
|
+#define IW_MEMSZ_MASK 0x3
|
|||
|
+#define IW_MEMSZ_WORD 0x2
|
|||
|
+#define IW_MEMSZ_WORD_MSB 0x1
|
|||
|
+#define IW_OP_LSB 0
|
|||
|
+#define IW_OP_MSB 5
|
|||
|
+#define IW_OP_SZ 6
|
|||
|
+#define IW_OP_MASK 0x3f
|
|||
|
+#define IW_OPX_LSB 11
|
|||
|
+#define IW_OPX_MSB 16
|
|||
|
+#define IW_OPX_SZ 6
|
|||
|
+#define IW_OPX_MASK 0x3f
|
|||
|
+#define IW_SHIFT_IMM5_LSB 6
|
|||
|
+#define IW_SHIFT_IMM5_MSB 10
|
|||
|
+#define IW_SHIFT_IMM5_SZ 5
|
|||
|
+#define IW_SHIFT_IMM5_MASK 0x1f
|
|||
|
+#define IW_SZ 32
|
|||
|
+#define IW_MASK 0xffffffff
|
|||
|
+#define IW_TRAP_BREAK_IMM5_LSB 6
|
|||
|
+#define IW_TRAP_BREAK_IMM5_MSB 10
|
|||
|
+#define IW_TRAP_BREAK_IMM5_SZ 5
|
|||
|
+#define IW_TRAP_BREAK_IMM5_MASK 0x1f
|
|||
|
+#define JMP_CALLR_VS_RET_IS_RET 0
|
|||
|
+#define JMP_CALLR_VS_RET_OPX_BIT 3
|
|||
|
+#define LOGIC_OP_AND 0x1
|
|||
|
+#define LOGIC_OP_LSB 3
|
|||
|
+#define LOGIC_OP_MSB 4
|
|||
|
+#define LOGIC_OP_NOR 0x0
|
|||
|
+#define LOGIC_OP_OR 0x2
|
|||
|
+#define LOGIC_OP_SZ 2
|
|||
|
+#define LOGIC_OP_MASK 0x3
|
|||
|
+#define LOGIC_OP_XOR 0x3
|
|||
|
+#define MMU_ADDR_BYPASS_TLB 0x3
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE 0x0
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB 29
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_MSB 29
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_SZ 1
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK 0x1
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_LSB 30
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_MSB 31
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_PADDR_LSB 0
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_PADDR_MSB 28
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_PADDR_SZ 29
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_PADDR_MASK 0x1fffffff
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_SZ 2
|
|||
|
+#define MMU_ADDR_BYPASS_TLB_MASK 0x3
|
|||
|
+#define MMU_ADDR_IO_REGION 0x7
|
|||
|
+#define MMU_ADDR_IO_REGION_LSB 29
|
|||
|
+#define MMU_ADDR_IO_REGION_MSB 31
|
|||
|
+#define MMU_ADDR_IO_REGION_SZ 3
|
|||
|
+#define MMU_ADDR_IO_REGION_MASK 0x7
|
|||
|
+#define MMU_ADDR_IO_REGION_VPN 0xe0000
|
|||
|
+#define MMU_ADDR_KERNEL_MMU_REGION 0x2
|
|||
|
+#define MMU_ADDR_KERNEL_MMU_REGION_LSB 30
|
|||
|
+#define MMU_ADDR_KERNEL_MMU_REGION_MSB 31
|
|||
|
+#define MMU_ADDR_KERNEL_MMU_REGION_SZ 2
|
|||
|
+#define MMU_ADDR_KERNEL_MMU_REGION_MASK 0x3
|
|||
|
+#define MMU_ADDR_KERNEL_REGION 0x6
|
|||
|
+#define MMU_ADDR_KERNEL_REGION_INT 6
|
|||
|
+#define MMU_ADDR_KERNEL_REGION_LSB 29
|
|||
|
+#define MMU_ADDR_KERNEL_REGION_MSB 31
|
|||
|
+#define MMU_ADDR_KERNEL_REGION_SZ 3
|
|||
|
+#define MMU_ADDR_KERNEL_REGION_MASK 0x7
|
|||
|
+#define MMU_ADDR_PAGE_OFFSET_LSB 0
|
|||
|
+#define MMU_ADDR_PAGE_OFFSET_MSB 11
|
|||
|
+#define MMU_ADDR_PAGE_OFFSET_SZ 12
|
|||
|
+#define MMU_ADDR_PAGE_OFFSET_MASK 0xfff
|
|||
|
+#define MMU_ADDR_PFN_LSB 12
|
|||
|
+#define MMU_ADDR_PFN_MSB 31
|
|||
|
+#define MMU_ADDR_PFN_SZ 20
|
|||
|
+#define MMU_ADDR_PFN_MASK 0xfffff
|
|||
|
+#define MMU_ADDR_USER_REGION 0x0
|
|||
|
+#define MMU_ADDR_USER_REGION_LSB 31
|
|||
|
+#define MMU_ADDR_USER_REGION_MSB 31
|
|||
|
+#define MMU_ADDR_USER_REGION_SZ 1
|
|||
|
+#define MMU_ADDR_USER_REGION_MASK 0x1
|
|||
|
+#define MMU_ADDR_VPN_LSB 12
|
|||
|
+#define MMU_ADDR_VPN_MSB 31
|
|||
|
+#define MMU_ADDR_VPN_SZ 20
|
|||
|
+#define MMU_ADDR_VPN_MASK 0xfffff
|
|||
|
+#define PTEADDR_REG_LSB 0
|
|||
|
+#define PTEADDR_REG_MSB 31
|
|||
|
+#define PTEADDR_REG_PTBASE_LSB 22
|
|||
|
+#define PTEADDR_REG_PTBASE_MSB 31
|
|||
|
+#define PTEADDR_REG_PTBASE_SZ 10
|
|||
|
+#define PTEADDR_REG_PTBASE_MASK 0x3ff
|
|||
|
+#define PTEADDR_REG_REGNUM 8
|
|||
|
+#define PTEADDR_REG_RSV_LSB 0
|
|||
|
+#define PTEADDR_REG_RSV_MSB 1
|
|||
|
+#define PTEADDR_REG_RSV_SZ 2
|
|||
|
+#define PTEADDR_REG_RSV_MASK 0x3
|
|||
|
+#define PTEADDR_REG_SZ 32
|
|||
|
+#define PTEADDR_REG_MASK 0xffffffff
|
|||
|
+#define PTEADDR_REG_VPN_LSB 2
|
|||
|
+#define PTEADDR_REG_VPN_MSB 21
|
|||
|
+#define PTEADDR_REG_VPN_SZ 20
|
|||
|
+#define PTEADDR_REG_VPN_MASK 0xfffff
|
|||
|
+#define REGNUM_SZ 5
|
|||
|
+#define REGNUM_MASK 0x1f
|
|||
|
+#define RETADDR_REGNUM 31
|
|||
|
+#define RF_ADDR_SZ 5
|
|||
|
+#define RF_ADDR_MASK 0x1f
|
|||
|
+#define RF_NUM_REG 32
|
|||
|
+#define SIM_REG_LSB 0
|
|||
|
+#define SIM_REG_MSB 3
|
|||
|
+#define SIM_REG_PERF_CNT_CLR_LSB 2
|
|||
|
+#define SIM_REG_PERF_CNT_CLR_MSB 2
|
|||
|
+#define SIM_REG_PERF_CNT_CLR_SZ 1
|
|||
|
+#define SIM_REG_PERF_CNT_CLR_MASK 0x1
|
|||
|
+#define SIM_REG_PERF_CNT_EN_LSB 1
|
|||
|
+#define SIM_REG_PERF_CNT_EN_MSB 1
|
|||
|
+#define SIM_REG_PERF_CNT_EN_SZ 1
|
|||
|
+#define SIM_REG_PERF_CNT_EN_MASK 0x1
|
|||
|
+#define SIM_REG_REGNUM 6
|
|||
|
+#define SIM_REG_SHOW_DTLB_LSB 4
|
|||
|
+#define SIM_REG_SHOW_DTLB_MSB 4
|
|||
|
+#define SIM_REG_SHOW_DTLB_SZ 1
|
|||
|
+#define SIM_REG_SHOW_DTLB_MASK 0x1
|
|||
|
+#define SIM_REG_SHOW_ITLB_LSB 3
|
|||
|
+#define SIM_REG_SHOW_ITLB_MSB 3
|
|||
|
+#define SIM_REG_SHOW_ITLB_SZ 1
|
|||
|
+#define SIM_REG_SHOW_ITLB_MASK 0x1
|
|||
|
+#define SIM_REG_SHOW_MMU_REGS_LSB 5
|
|||
|
+#define SIM_REG_SHOW_MMU_REGS_MSB 5
|
|||
|
+#define SIM_REG_SHOW_MMU_REGS_SZ 1
|
|||
|
+#define SIM_REG_SHOW_MMU_REGS_MASK 0x1
|
|||
|
+#define SIM_REG_STOP_LSB 0
|
|||
|
+#define SIM_REG_STOP_MSB 0
|
|||
|
+#define SIM_REG_STOP_SZ 1
|
|||
|
+#define SIM_REG_STOP_MASK 0x1
|
|||
|
+#define SIM_REG_SZ 4
|
|||
|
+#define SIM_REG_MASK 0xf
|
|||
|
+#define SP_REGNUM 27
|
|||
|
+#define STATUS_REG_EH_LSB 2
|
|||
|
+#define STATUS_REG_EH_MSB 2
|
|||
|
+#define STATUS_REG_EH_SZ 1
|
|||
|
+#define STATUS_REG_EH_MASK 0x1
|
|||
|
+#define STATUS_REG_LSB 0
|
|||
|
+#define STATUS_REG_MMU_LSB 0
|
|||
|
+#define STATUS_REG_MMU_MSB 2
|
|||
|
+#define STATUS_REG_MMU_RSV_LSB 3
|
|||
|
+#define STATUS_REG_MMU_RSV_MSB 31
|
|||
|
+#define STATUS_REG_MMU_RSV_SZ 29
|
|||
|
+#define STATUS_REG_MMU_RSV_MASK 0x1fffffff
|
|||
|
+#define STATUS_REG_MMU_SZ 3
|
|||
|
+#define STATUS_REG_MMU_MASK 0x7
|
|||
|
+#define STATUS_REG_MSB 2
|
|||
|
+#define STATUS_REG_NO_MMU_LSB 0
|
|||
|
+#define STATUS_REG_NO_MMU_MSB 0
|
|||
|
+#define STATUS_REG_NO_MMU_RSV_LSB 1
|
|||
|
+#define STATUS_REG_NO_MMU_RSV_MSB 31
|
|||
|
+#define STATUS_REG_NO_MMU_RSV_SZ 31
|
|||
|
+#define STATUS_REG_NO_MMU_RSV_MASK 0x7fffffff
|
|||
|
+#define STATUS_REG_NO_MMU_SZ 1
|
|||
|
+#define STATUS_REG_NO_MMU_MASK 0x1
|
|||
|
+#define STATUS_REG_PIE_LSB 0
|
|||
|
+#define STATUS_REG_PIE_MSB 0
|
|||
|
+#define STATUS_REG_PIE_SZ 1
|
|||
|
+#define STATUS_REG_PIE_MASK 0x1
|
|||
|
+#define STATUS_REG_REGNUM 0
|
|||
|
+#define STATUS_REG_SZ 3
|
|||
|
+#define STATUS_REG_MASK 0x7
|
|||
|
+#define STATUS_REG_U_LSB 1
|
|||
|
+#define STATUS_REG_U_MSB 1
|
|||
|
+#define STATUS_REG_U_SZ 1
|
|||
|
+#define STATUS_REG_U_MASK 0x1
|
|||
|
+#define TLB_MAX_ENTRIES 1024
|
|||
|
+#define TLB_MAX_LINES 512
|
|||
|
+#define TLB_MAX_PID_SZ 14
|
|||
|
+#define TLB_MAX_PID_MASK 0x3fff
|
|||
|
+#define TLB_MAX_PTR_SZ 10
|
|||
|
+#define TLB_MAX_PTR_MASK 0x3ff
|
|||
|
+#define TLB_MAX_WAYS 8
|
|||
|
+#define TLB_MIN_PID_SZ 1
|
|||
|
+#define TLB_MIN_PID_MASK 0x1
|
|||
|
+#define TLB_MIN_PTR_SZ 7
|
|||
|
+#define TLB_MIN_PTR_MASK 0x7f
|
|||
|
+#define TLB_MIN_WAYS 2
|
|||
|
+#define TLBACC_REG_C_LSB 24
|
|||
|
+#define TLBACC_REG_C_MSB 24
|
|||
|
+#define TLBACC_REG_C_SZ 1
|
|||
|
+#define TLBACC_REG_C_MASK 0x1
|
|||
|
+#define TLBACC_REG_G_LSB 20
|
|||
|
+#define TLBACC_REG_G_MSB 20
|
|||
|
+#define TLBACC_REG_G_SZ 1
|
|||
|
+#define TLBACC_REG_G_MASK 0x1
|
|||
|
+#define TLBACC_REG_IG_LSB 25
|
|||
|
+#define TLBACC_REG_IG_MSB 31
|
|||
|
+#define TLBACC_REG_IG_SZ 7
|
|||
|
+#define TLBACC_REG_IG_MASK 0x7f
|
|||
|
+#define TLBACC_REG_LSB 0
|
|||
|
+#define TLBACC_REG_MSB 24
|
|||
|
+#define TLBACC_REG_PFN_LSB 0
|
|||
|
+#define TLBACC_REG_PFN_MSB 19
|
|||
|
+#define TLBACC_REG_PFN_SZ 20
|
|||
|
+#define TLBACC_REG_PFN_MASK 0xfffff
|
|||
|
+#define TLBACC_REG_R_LSB 23
|
|||
|
+#define TLBACC_REG_R_MSB 23
|
|||
|
+#define TLBACC_REG_R_SZ 1
|
|||
|
+#define TLBACC_REG_R_MASK 0x1
|
|||
|
+#define TLBACC_REG_REGNUM 9
|
|||
|
+#define TLBACC_REG_SZ 25
|
|||
|
+#define TLBACC_REG_MASK 0x1ffffff
|
|||
|
+#define TLBACC_REG_W_LSB 22
|
|||
|
+#define TLBACC_REG_W_MSB 22
|
|||
|
+#define TLBACC_REG_W_SZ 1
|
|||
|
+#define TLBACC_REG_W_MASK 0x1
|
|||
|
+#define TLBACC_REG_X_LSB 21
|
|||
|
+#define TLBACC_REG_X_MSB 21
|
|||
|
+#define TLBACC_REG_X_SZ 1
|
|||
|
+#define TLBACC_REG_X_MASK 0x1
|
|||
|
+#define TLBMISC_REG_BAD_LSB 2
|
|||
|
+#define TLBMISC_REG_BAD_MSB 2
|
|||
|
+#define TLBMISC_REG_BAD_SZ 1
|
|||
|
+#define TLBMISC_REG_BAD_MASK 0x1
|
|||
|
+#define TLBMISC_REG_D_LSB 0
|
|||
|
+#define TLBMISC_REG_D_MSB 0
|
|||
|
+#define TLBMISC_REG_D_SZ 1
|
|||
|
+#define TLBMISC_REG_D_MASK 0x1
|
|||
|
+#define TLBMISC_REG_DBL_LSB 3
|
|||
|
+#define TLBMISC_REG_DBL_MSB 3
|
|||
|
+#define TLBMISC_REG_DBL_SZ 1
|
|||
|
+#define TLBMISC_REG_DBL_MASK 0x1
|
|||
|
+#define TLBMISC_REG_LSB 0
|
|||
|
+#define TLBMISC_REG_MSB 23
|
|||
|
+#define TLBMISC_REG_PERM_LSB 1
|
|||
|
+#define TLBMISC_REG_PERM_MSB 1
|
|||
|
+#define TLBMISC_REG_PERM_SZ 1
|
|||
|
+#define TLBMISC_REG_PERM_MASK 0x1
|
|||
|
+#define TLBMISC_REG_PID_LSB 4
|
|||
|
+#define TLBMISC_REG_PID_MSB 17
|
|||
|
+#define TLBMISC_REG_PID_SZ 14
|
|||
|
+#define TLBMISC_REG_PID_MASK 0x3fff
|
|||
|
+#define TLBMISC_REG_RD_LSB 24
|
|||
|
+#define TLBMISC_REG_RD_MSB 24
|
|||
|
+#define TLBMISC_REG_RD_SZ 1
|
|||
|
+#define TLBMISC_REG_RD_MASK 0x1
|
|||
|
+#define TLBMISC_REG_REGNUM 10
|
|||
|
+#define TLBMISC_REG_RSV0_LSB 18
|
|||
|
+#define TLBMISC_REG_RSV0_MSB 19
|
|||
|
+#define TLBMISC_REG_RSV0_SZ 2
|
|||
|
+#define TLBMISC_REG_RSV0_MASK 0x3
|
|||
|
+#define TLBMISC_REG_RSV1_LSB 25
|
|||
|
+#define TLBMISC_REG_RSV1_MSB 31
|
|||
|
+#define TLBMISC_REG_RSV1_SZ 7
|
|||
|
+#define TLBMISC_REG_RSV1_MASK 0x7f
|
|||
|
+#define TLBMISC_REG_SZ 24
|
|||
|
+#define TLBMISC_REG_MASK 0xffffff
|
|||
|
+#define TLBMISC_REG_WAY_LSB 20
|
|||
|
+#define TLBMISC_REG_WAY_MSB 22
|
|||
|
+#define TLBMISC_REG_WAY_SZ 3
|
|||
|
+#define TLBMISC_REG_WAY_MASK 0x7
|
|||
|
+#define TLBMISC_REG_WE_LSB 23
|
|||
|
+#define TLBMISC_REG_WE_MSB 23
|
|||
|
+#define TLBMISC_REG_WE_SZ 1
|
|||
|
+#define TLBMISC_REG_WE_MASK 0x1
|
|||
|
+
|
|||
|
+/* Macros to extract instruction fields */
|
|||
|
+#define GET_IW_A(Iw) \
|
|||
|
+ (((Iw) >> IW_A_LSB) & IW_A_MASK)
|
|||
|
+#define SET_IW_A(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_A_MASK << IW_A_LSB))) | \
|
|||
|
+ (((Val) & IW_A_MASK) << IW_A_LSB))
|
|||
|
+#define GET_IW_B(Iw) \
|
|||
|
+ (((Iw) >> IW_B_LSB) & IW_B_MASK)
|
|||
|
+#define SET_IW_B(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_B_MASK << IW_B_LSB))) | \
|
|||
|
+ (((Val) & IW_B_MASK) << IW_B_LSB))
|
|||
|
+#define GET_IW_C(Iw) \
|
|||
|
+ (((Iw) >> IW_C_LSB) & IW_C_MASK)
|
|||
|
+#define SET_IW_C(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_C_MASK << IW_C_LSB))) | \
|
|||
|
+ (((Val) & IW_C_MASK) << IW_C_LSB))
|
|||
|
+#define GET_IW_CONTROL_REGNUM(Iw) \
|
|||
|
+ (((Iw) >> IW_CONTROL_REGNUM_LSB) & IW_CONTROL_REGNUM_MASK)
|
|||
|
+#define SET_IW_CONTROL_REGNUM(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_CONTROL_REGNUM_MASK << IW_CONTROL_REGNUM_LSB))) | \
|
|||
|
+ (((Val) & IW_CONTROL_REGNUM_MASK) << IW_CONTROL_REGNUM_LSB))
|
|||
|
+#define GET_IW_CUSTOM_N(Iw) \
|
|||
|
+ (((Iw) >> IW_CUSTOM_N_LSB) & IW_CUSTOM_N_MASK)
|
|||
|
+#define SET_IW_CUSTOM_N(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_CUSTOM_N_MASK << IW_CUSTOM_N_LSB))) | \
|
|||
|
+ (((Val) & IW_CUSTOM_N_MASK) << IW_CUSTOM_N_LSB))
|
|||
|
+#define GET_IW_CUSTOM_READRA(Iw) \
|
|||
|
+ (((Iw) >> IW_CUSTOM_READRA_LSB) & IW_CUSTOM_READRA_MASK)
|
|||
|
+#define SET_IW_CUSTOM_READRA(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_CUSTOM_READRA_MASK << IW_CUSTOM_READRA_LSB))) | \
|
|||
|
+ (((Val) & IW_CUSTOM_READRA_MASK) << IW_CUSTOM_READRA_LSB))
|
|||
|
+#define GET_IW_CUSTOM_READRB(Iw) \
|
|||
|
+ (((Iw) >> IW_CUSTOM_READRB_LSB) & IW_CUSTOM_READRB_MASK)
|
|||
|
+#define SET_IW_CUSTOM_READRB(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_CUSTOM_READRB_MASK << IW_CUSTOM_READRB_LSB))) | \
|
|||
|
+ (((Val) & IW_CUSTOM_READRB_MASK) << IW_CUSTOM_READRB_LSB))
|
|||
|
+#define GET_IW_CUSTOM_WRITERC(Iw) \
|
|||
|
+ (((Iw) >> IW_CUSTOM_WRITERC_LSB) & IW_CUSTOM_WRITERC_MASK)
|
|||
|
+#define SET_IW_CUSTOM_WRITERC(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_CUSTOM_WRITERC_MASK << IW_CUSTOM_WRITERC_LSB))) | \
|
|||
|
+ (((Val) & IW_CUSTOM_WRITERC_MASK) << IW_CUSTOM_WRITERC_LSB))
|
|||
|
+#define GET_IW_IMM16(Iw) \
|
|||
|
+ (((Iw) >> IW_IMM16_LSB) & IW_IMM16_MASK)
|
|||
|
+#define SET_IW_IMM16(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_IMM16_MASK << IW_IMM16_LSB))) | \
|
|||
|
+ (((Val) & IW_IMM16_MASK) << IW_IMM16_LSB))
|
|||
|
+#define GET_IW_IMM26(Iw) \
|
|||
|
+ (((Iw) >> IW_IMM26_LSB) & IW_IMM26_MASK)
|
|||
|
+#define SET_IW_IMM26(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_IMM26_MASK << IW_IMM26_LSB))) | \
|
|||
|
+ (((Val) & IW_IMM26_MASK) << IW_IMM26_LSB))
|
|||
|
+#define GET_IW_MEMSZ(Iw) \
|
|||
|
+ (((Iw) >> IW_MEMSZ_LSB) & IW_MEMSZ_MASK)
|
|||
|
+#define SET_IW_MEMSZ(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_MEMSZ_MASK << IW_MEMSZ_LSB))) | \
|
|||
|
+ (((Val) & IW_MEMSZ_MASK) << IW_MEMSZ_LSB))
|
|||
|
+#define GET_IW_OP(Iw) \
|
|||
|
+ (((Iw) >> IW_OP_LSB) & IW_OP_MASK)
|
|||
|
+#define SET_IW_OP(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_OP_MASK << IW_OP_LSB))) | \
|
|||
|
+ (((Val) & IW_OP_MASK) << IW_OP_LSB))
|
|||
|
+#define GET_IW_OPX(Iw) \
|
|||
|
+ (((Iw) >> IW_OPX_LSB) & IW_OPX_MASK)
|
|||
|
+#define SET_IW_OPX(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_OPX_MASK << IW_OPX_LSB))) | \
|
|||
|
+ (((Val) & IW_OPX_MASK) << IW_OPX_LSB))
|
|||
|
+#define GET_IW_SHIFT_IMM5(Iw) \
|
|||
|
+ (((Iw) >> IW_SHIFT_IMM5_LSB) & IW_SHIFT_IMM5_MASK)
|
|||
|
+#define SET_IW_SHIFT_IMM5(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_SHIFT_IMM5_MASK << IW_SHIFT_IMM5_LSB))) | \
|
|||
|
+ (((Val) & IW_SHIFT_IMM5_MASK) << IW_SHIFT_IMM5_LSB))
|
|||
|
+#define GET_IW_TRAP_BREAK_IMM5(Iw) \
|
|||
|
+ (((Iw) >> IW_TRAP_BREAK_IMM5_LSB) & IW_TRAP_BREAK_IMM5_MASK)
|
|||
|
+#define SET_IW_TRAP_BREAK_IMM5(Iw, Val) \
|
|||
|
+ Iw = (((Iw) & (~(IW_TRAP_BREAK_IMM5_MASK << IW_TRAP_BREAK_IMM5_LSB))) | \
|
|||
|
+ (((Val) & IW_TRAP_BREAK_IMM5_MASK) << IW_TRAP_BREAK_IMM5_LSB))
|
|||
|
+
|
|||
|
+/* Macros to extract control register fields */
|
|||
|
+#define GET_BSTATUS_REG_MMU(Reg) \
|
|||
|
+ (((Reg) >> BSTATUS_REG_MMU_LSB) & BSTATUS_REG_MMU_MASK)
|
|||
|
+#define SET_BSTATUS_REG_MMU(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(BSTATUS_REG_MMU_MASK << BSTATUS_REG_MMU_LSB))) | \
|
|||
|
+ (((Val) & BSTATUS_REG_MMU_MASK) << BSTATUS_REG_MMU_LSB))
|
|||
|
+#define GET_BSTATUS_REG_NO_MMU(Reg) \
|
|||
|
+ (((Reg) >> BSTATUS_REG_NO_MMU_LSB) & BSTATUS_REG_NO_MMU_MASK)
|
|||
|
+#define SET_BSTATUS_REG_NO_MMU(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(BSTATUS_REG_NO_MMU_MASK << BSTATUS_REG_NO_MMU_LSB))) | \
|
|||
|
+ (((Val) & BSTATUS_REG_NO_MMU_MASK) << BSTATUS_REG_NO_MMU_LSB))
|
|||
|
+#define GET_ESTATUS_REG_MMU(Reg) \
|
|||
|
+ (((Reg) >> ESTATUS_REG_MMU_LSB) & ESTATUS_REG_MMU_MASK)
|
|||
|
+#define SET_ESTATUS_REG_MMU(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(ESTATUS_REG_MMU_MASK << ESTATUS_REG_MMU_LSB))) | \
|
|||
|
+ (((Val) & ESTATUS_REG_MMU_MASK) << ESTATUS_REG_MMU_LSB))
|
|||
|
+#define GET_ESTATUS_REG_NO_MMU(Reg) \
|
|||
|
+ (((Reg) >> ESTATUS_REG_NO_MMU_LSB) & ESTATUS_REG_NO_MMU_MASK)
|
|||
|
+#define SET_ESTATUS_REG_NO_MMU(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(ESTATUS_REG_NO_MMU_MASK << ESTATUS_REG_NO_MMU_LSB))) | \
|
|||
|
+ (((Val) & ESTATUS_REG_NO_MMU_MASK) << ESTATUS_REG_NO_MMU_LSB))
|
|||
|
+#define GET_EXCEPTION_REG_MEA(Reg) \
|
|||
|
+ (((Reg) >> EXCEPTION_REG_MEA_LSB) & EXCEPTION_REG_MEA_MASK)
|
|||
|
+#define SET_EXCEPTION_REG_MEA(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(EXCEPTION_REG_MEA_MASK << EXCEPTION_REG_MEA_LSB))) | \
|
|||
|
+ (((Val) & EXCEPTION_REG_MEA_MASK) << EXCEPTION_REG_MEA_LSB))
|
|||
|
+#define GET_EXCEPTION_REG_MEE(Reg) \
|
|||
|
+ (((Reg) >> EXCEPTION_REG_MEE_LSB) & EXCEPTION_REG_MEE_MASK)
|
|||
|
+#define SET_EXCEPTION_REG_MEE(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(EXCEPTION_REG_MEE_MASK << EXCEPTION_REG_MEE_LSB))) | \
|
|||
|
+ (((Val) & EXCEPTION_REG_MEE_MASK) << EXCEPTION_REG_MEE_LSB))
|
|||
|
+#define GET_PTEADDR_REG_PTBASE(Reg) \
|
|||
|
+ (((Reg) >> PTEADDR_REG_PTBASE_LSB) & PTEADDR_REG_PTBASE_MASK)
|
|||
|
+#define SET_PTEADDR_REG_PTBASE(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(PTEADDR_REG_PTBASE_MASK << PTEADDR_REG_PTBASE_LSB))) | \
|
|||
|
+ (((Val) & PTEADDR_REG_PTBASE_MASK) << PTEADDR_REG_PTBASE_LSB))
|
|||
|
+#define GET_PTEADDR_REG_RSV(Reg) \
|
|||
|
+ (((Reg) >> PTEADDR_REG_RSV_LSB) & PTEADDR_REG_RSV_MASK)
|
|||
|
+#define SET_PTEADDR_REG_RSV(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(PTEADDR_REG_RSV_MASK << PTEADDR_REG_RSV_LSB))) | \
|
|||
|
+ (((Val) & PTEADDR_REG_RSV_MASK) << PTEADDR_REG_RSV_LSB))
|
|||
|
+#define GET_PTEADDR_REG_VPN(Reg) \
|
|||
|
+ (((Reg) >> PTEADDR_REG_VPN_LSB) & PTEADDR_REG_VPN_MASK)
|
|||
|
+#define SET_PTEADDR_REG_VPN(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(PTEADDR_REG_VPN_MASK << PTEADDR_REG_VPN_LSB))) | \
|
|||
|
+ (((Val) & PTEADDR_REG_VPN_MASK) << PTEADDR_REG_VPN_LSB))
|
|||
|
+#define GET_SIM_REG_PERF_CNT_CLR(Reg) \
|
|||
|
+ (((Reg) >> SIM_REG_PERF_CNT_CLR_LSB) & SIM_REG_PERF_CNT_CLR_MASK)
|
|||
|
+#define SET_SIM_REG_PERF_CNT_CLR(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(SIM_REG_PERF_CNT_CLR_MASK << SIM_REG_PERF_CNT_CLR_LSB))) | \
|
|||
|
+ (((Val) & SIM_REG_PERF_CNT_CLR_MASK) << SIM_REG_PERF_CNT_CLR_LSB))
|
|||
|
+#define GET_SIM_REG_PERF_CNT_EN(Reg) \
|
|||
|
+ (((Reg) >> SIM_REG_PERF_CNT_EN_LSB) & SIM_REG_PERF_CNT_EN_MASK)
|
|||
|
+#define SET_SIM_REG_PERF_CNT_EN(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(SIM_REG_PERF_CNT_EN_MASK << SIM_REG_PERF_CNT_EN_LSB))) | \
|
|||
|
+ (((Val) & SIM_REG_PERF_CNT_EN_MASK) << SIM_REG_PERF_CNT_EN_LSB))
|
|||
|
+#define GET_SIM_REG_SHOW_DTLB(Reg) \
|
|||
|
+ (((Reg) >> SIM_REG_SHOW_DTLB_LSB) & SIM_REG_SHOW_DTLB_MASK)
|
|||
|
+#define SET_SIM_REG_SHOW_DTLB(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(SIM_REG_SHOW_DTLB_MASK << SIM_REG_SHOW_DTLB_LSB))) | \
|
|||
|
+ (((Val) & SIM_REG_SHOW_DTLB_MASK) << SIM_REG_SHOW_DTLB_LSB))
|
|||
|
+#define GET_SIM_REG_SHOW_ITLB(Reg) \
|
|||
|
+ (((Reg) >> SIM_REG_SHOW_ITLB_LSB) & SIM_REG_SHOW_ITLB_MASK)
|
|||
|
+#define SET_SIM_REG_SHOW_ITLB(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(SIM_REG_SHOW_ITLB_MASK << SIM_REG_SHOW_ITLB_LSB))) | \
|
|||
|
+ (((Val) & SIM_REG_SHOW_ITLB_MASK) << SIM_REG_SHOW_ITLB_LSB))
|
|||
|
+#define GET_SIM_REG_SHOW_MMU_REGS(Reg) \
|
|||
|
+ (((Reg) >> SIM_REG_SHOW_MMU_REGS_LSB) & SIM_REG_SHOW_MMU_REGS_MASK)
|
|||
|
+#define SET_SIM_REG_SHOW_MMU_REGS(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(SIM_REG_SHOW_MMU_REGS_MASK << SIM_REG_SHOW_MMU_REGS_LSB))) | \
|
|||
|
+ (((Val) & SIM_REG_SHOW_MMU_REGS_MASK) << SIM_REG_SHOW_MMU_REGS_LSB))
|
|||
|
+#define GET_SIM_REG_STOP(Reg) \
|
|||
|
+ (((Reg) >> SIM_REG_STOP_LSB) & SIM_REG_STOP_MASK)
|
|||
|
+#define SET_SIM_REG_STOP(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(SIM_REG_STOP_MASK << SIM_REG_STOP_LSB))) | \
|
|||
|
+ (((Val) & SIM_REG_STOP_MASK) << SIM_REG_STOP_LSB))
|
|||
|
+#define GET_STATUS_REG_EH(Reg) \
|
|||
|
+ (((Reg) >> STATUS_REG_EH_LSB) & STATUS_REG_EH_MASK)
|
|||
|
+#define SET_STATUS_REG_EH(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(STATUS_REG_EH_MASK << STATUS_REG_EH_LSB))) | \
|
|||
|
+ (((Val) & STATUS_REG_EH_MASK) << STATUS_REG_EH_LSB))
|
|||
|
+#define GET_STATUS_REG_MMU(Reg) \
|
|||
|
+ (((Reg) >> STATUS_REG_MMU_LSB) & STATUS_REG_MMU_MASK)
|
|||
|
+#define SET_STATUS_REG_MMU(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(STATUS_REG_MMU_MASK << STATUS_REG_MMU_LSB))) | \
|
|||
|
+ (((Val) & STATUS_REG_MMU_MASK) << STATUS_REG_MMU_LSB))
|
|||
|
+#define GET_STATUS_REG_MMU_RSV(Reg) \
|
|||
|
+ (((Reg) >> STATUS_REG_MMU_RSV_LSB) & STATUS_REG_MMU_RSV_MASK)
|
|||
|
+#define SET_STATUS_REG_MMU_RSV(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(STATUS_REG_MMU_RSV_MASK << STATUS_REG_MMU_RSV_LSB))) | \
|
|||
|
+ (((Val) & STATUS_REG_MMU_RSV_MASK) << STATUS_REG_MMU_RSV_LSB))
|
|||
|
+#define GET_STATUS_REG_NO_MMU(Reg) \
|
|||
|
+ (((Reg) >> STATUS_REG_NO_MMU_LSB) & STATUS_REG_NO_MMU_MASK)
|
|||
|
+#define SET_STATUS_REG_NO_MMU(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(STATUS_REG_NO_MMU_MASK << STATUS_REG_NO_MMU_LSB))) | \
|
|||
|
+ (((Val) & STATUS_REG_NO_MMU_MASK) << STATUS_REG_NO_MMU_LSB))
|
|||
|
+#define GET_STATUS_REG_NO_MMU_RSV(Reg) \
|
|||
|
+ (((Reg) >> STATUS_REG_NO_MMU_RSV_LSB) & STATUS_REG_NO_MMU_RSV_MASK)
|
|||
|
+#define SET_STATUS_REG_NO_MMU_RSV(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(STATUS_REG_NO_MMU_RSV_MASK << STATUS_REG_NO_MMU_RSV_LSB))) | \
|
|||
|
+ (((Val) & STATUS_REG_NO_MMU_RSV_MASK) << STATUS_REG_NO_MMU_RSV_LSB))
|
|||
|
+#define GET_STATUS_REG_PIE(Reg) \
|
|||
|
+ (((Reg) >> STATUS_REG_PIE_LSB) & STATUS_REG_PIE_MASK)
|
|||
|
+#define SET_STATUS_REG_PIE(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(STATUS_REG_PIE_MASK << STATUS_REG_PIE_LSB))) | \
|
|||
|
+ (((Val) & STATUS_REG_PIE_MASK) << STATUS_REG_PIE_LSB))
|
|||
|
+#define GET_STATUS_REG_U(Reg) \
|
|||
|
+ (((Reg) >> STATUS_REG_U_LSB) & STATUS_REG_U_MASK)
|
|||
|
+#define SET_STATUS_REG_U(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(STATUS_REG_U_MASK << STATUS_REG_U_LSB))) | \
|
|||
|
+ (((Val) & STATUS_REG_U_MASK) << STATUS_REG_U_LSB))
|
|||
|
+#define GET_TLBACC_REG_C(Reg) \
|
|||
|
+ (((Reg) >> TLBACC_REG_C_LSB) & TLBACC_REG_C_MASK)
|
|||
|
+#define SET_TLBACC_REG_C(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBACC_REG_C_MASK << TLBACC_REG_C_LSB))) | \
|
|||
|
+ (((Val) & TLBACC_REG_C_MASK) << TLBACC_REG_C_LSB))
|
|||
|
+#define GET_TLBACC_REG_G(Reg) \
|
|||
|
+ (((Reg) >> TLBACC_REG_G_LSB) & TLBACC_REG_G_MASK)
|
|||
|
+#define SET_TLBACC_REG_G(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBACC_REG_G_MASK << TLBACC_REG_G_LSB))) | \
|
|||
|
+ (((Val) & TLBACC_REG_G_MASK) << TLBACC_REG_G_LSB))
|
|||
|
+#define GET_TLBACC_REG_IG(Reg) \
|
|||
|
+ (((Reg) >> TLBACC_REG_IG_LSB) & TLBACC_REG_IG_MASK)
|
|||
|
+#define SET_TLBACC_REG_IG(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBACC_REG_IG_MASK << TLBACC_REG_IG_LSB))) | \
|
|||
|
+ (((Val) & TLBACC_REG_IG_MASK) << TLBACC_REG_IG_LSB))
|
|||
|
+#define GET_TLBACC_REG_PFN(Reg) \
|
|||
|
+ (((Reg) >> TLBACC_REG_PFN_LSB) & TLBACC_REG_PFN_MASK)
|
|||
|
+#define SET_TLBACC_REG_PFN(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBACC_REG_PFN_MASK << TLBACC_REG_PFN_LSB))) | \
|
|||
|
+ (((Val) & TLBACC_REG_PFN_MASK) << TLBACC_REG_PFN_LSB))
|
|||
|
+#define GET_TLBACC_REG_R(Reg) \
|
|||
|
+ (((Reg) >> TLBACC_REG_R_LSB) & TLBACC_REG_R_MASK)
|
|||
|
+#define SET_TLBACC_REG_R(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBACC_REG_R_MASK << TLBACC_REG_R_LSB))) | \
|
|||
|
+ (((Val) & TLBACC_REG_R_MASK) << TLBACC_REG_R_LSB))
|
|||
|
+#define GET_TLBACC_REG_W(Reg) \
|
|||
|
+ (((Reg) >> TLBACC_REG_W_LSB) & TLBACC_REG_W_MASK)
|
|||
|
+#define SET_TLBACC_REG_W(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBACC_REG_W_MASK << TLBACC_REG_W_LSB))) | \
|
|||
|
+ (((Val) & TLBACC_REG_W_MASK) << TLBACC_REG_W_LSB))
|
|||
|
+#define GET_TLBACC_REG_X(Reg) \
|
|||
|
+ (((Reg) >> TLBACC_REG_X_LSB) & TLBACC_REG_X_MASK)
|
|||
|
+#define SET_TLBACC_REG_X(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBACC_REG_X_MASK << TLBACC_REG_X_LSB))) | \
|
|||
|
+ (((Val) & TLBACC_REG_X_MASK) << TLBACC_REG_X_LSB))
|
|||
|
+#define GET_TLBMISC_REG_BAD(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_BAD_LSB) & TLBMISC_REG_BAD_MASK)
|
|||
|
+#define SET_TLBMISC_REG_BAD(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_BAD_MASK << TLBMISC_REG_BAD_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_BAD_MASK) << TLBMISC_REG_BAD_LSB))
|
|||
|
+#define GET_TLBMISC_REG_D(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_D_LSB) & TLBMISC_REG_D_MASK)
|
|||
|
+#define SET_TLBMISC_REG_D(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_D_MASK << TLBMISC_REG_D_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_D_MASK) << TLBMISC_REG_D_LSB))
|
|||
|
+#define GET_TLBMISC_REG_DBL(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_DBL_LSB) & TLBMISC_REG_DBL_MASK)
|
|||
|
+#define SET_TLBMISC_REG_DBL(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_DBL_MASK << TLBMISC_REG_DBL_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_DBL_MASK) << TLBMISC_REG_DBL_LSB))
|
|||
|
+#define GET_TLBMISC_REG_PERM(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_PERM_LSB) & TLBMISC_REG_PERM_MASK)
|
|||
|
+#define SET_TLBMISC_REG_PERM(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_PERM_MASK << TLBMISC_REG_PERM_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_PERM_MASK) << TLBMISC_REG_PERM_LSB))
|
|||
|
+#define GET_TLBMISC_REG_PID(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_PID_LSB) & TLBMISC_REG_PID_MASK)
|
|||
|
+#define SET_TLBMISC_REG_PID(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_PID_MASK << TLBMISC_REG_PID_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_PID_MASK) << TLBMISC_REG_PID_LSB))
|
|||
|
+#define GET_TLBMISC_REG_RD(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_RD_LSB) & TLBMISC_REG_RD_MASK)
|
|||
|
+#define SET_TLBMISC_REG_RD(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_RD_MASK << TLBMISC_REG_RD_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_RD_MASK) << TLBMISC_REG_RD_LSB))
|
|||
|
+#define GET_TLBMISC_REG_RSV0(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_RSV0_LSB) & TLBMISC_REG_RSV0_MASK)
|
|||
|
+#define SET_TLBMISC_REG_RSV0(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_RSV0_MASK << TLBMISC_REG_RSV0_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_RSV0_MASK) << TLBMISC_REG_RSV0_LSB))
|
|||
|
+#define GET_TLBMISC_REG_RSV1(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_RSV1_LSB) & TLBMISC_REG_RSV1_MASK)
|
|||
|
+#define SET_TLBMISC_REG_RSV1(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_RSV1_MASK << TLBMISC_REG_RSV1_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_RSV1_MASK) << TLBMISC_REG_RSV1_LSB))
|
|||
|
+#define GET_TLBMISC_REG_WAY(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_WAY_LSB) & TLBMISC_REG_WAY_MASK)
|
|||
|
+#define SET_TLBMISC_REG_WAY(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_WAY_MASK << TLBMISC_REG_WAY_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_WAY_MASK) << TLBMISC_REG_WAY_LSB))
|
|||
|
+#define GET_TLBMISC_REG_WE(Reg) \
|
|||
|
+ (((Reg) >> TLBMISC_REG_WE_LSB) & TLBMISC_REG_WE_MASK)
|
|||
|
+#define SET_TLBMISC_REG_WE(Reg, Val) \
|
|||
|
+ Reg = (((Reg) & (~(TLBMISC_REG_WE_MASK << TLBMISC_REG_WE_LSB))) | \
|
|||
|
+ (((Val) & TLBMISC_REG_WE_MASK) << TLBMISC_REG_WE_LSB))
|
|||
|
+
|
|||
|
+/* Macros to extract MMU fields */
|
|||
|
+#define GET_MMU_ADDR_BYPASS_TLB_CACHEABLE(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB) & MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK)
|
|||
|
+#define SET_MMU_ADDR_BYPASS_TLB_CACHEABLE(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK << MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_BYPASS_TLB_CACHEABLE_MASK) << MMU_ADDR_BYPASS_TLB_CACHEABLE_LSB))
|
|||
|
+#define GET_MMU_ADDR_BYPASS_TLB(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_BYPASS_TLB_LSB) & MMU_ADDR_BYPASS_TLB_MASK)
|
|||
|
+#define SET_MMU_ADDR_BYPASS_TLB(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_BYPASS_TLB_MASK << MMU_ADDR_BYPASS_TLB_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_BYPASS_TLB_MASK) << MMU_ADDR_BYPASS_TLB_LSB))
|
|||
|
+#define GET_MMU_ADDR_BYPASS_TLB_PADDR(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_BYPASS_TLB_PADDR_LSB) & MMU_ADDR_BYPASS_TLB_PADDR_MASK)
|
|||
|
+#define SET_MMU_ADDR_BYPASS_TLB_PADDR(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_BYPASS_TLB_PADDR_MASK << MMU_ADDR_BYPASS_TLB_PADDR_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_BYPASS_TLB_PADDR_MASK) << MMU_ADDR_BYPASS_TLB_PADDR_LSB))
|
|||
|
+#define GET_MMU_ADDR_IO_REGION(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_IO_REGION_LSB) & MMU_ADDR_IO_REGION_MASK)
|
|||
|
+#define SET_MMU_ADDR_IO_REGION(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_IO_REGION_MASK << MMU_ADDR_IO_REGION_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_IO_REGION_MASK) << MMU_ADDR_IO_REGION_LSB))
|
|||
|
+#define GET_MMU_ADDR_KERNEL_MMU_REGION(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_KERNEL_MMU_REGION_LSB) & MMU_ADDR_KERNEL_MMU_REGION_MASK)
|
|||
|
+#define SET_MMU_ADDR_KERNEL_MMU_REGION(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_KERNEL_MMU_REGION_MASK << MMU_ADDR_KERNEL_MMU_REGION_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_KERNEL_MMU_REGION_MASK) << MMU_ADDR_KERNEL_MMU_REGION_LSB))
|
|||
|
+#define GET_MMU_ADDR_KERNEL_REGION(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_KERNEL_REGION_LSB) & MMU_ADDR_KERNEL_REGION_MASK)
|
|||
|
+#define SET_MMU_ADDR_KERNEL_REGION(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_KERNEL_REGION_MASK << MMU_ADDR_KERNEL_REGION_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_KERNEL_REGION_MASK) << MMU_ADDR_KERNEL_REGION_LSB))
|
|||
|
+#define GET_MMU_ADDR_PAGE_OFFSET(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_PAGE_OFFSET_LSB) & MMU_ADDR_PAGE_OFFSET_MASK)
|
|||
|
+#define SET_MMU_ADDR_PAGE_OFFSET(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_PAGE_OFFSET_MASK << MMU_ADDR_PAGE_OFFSET_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_PAGE_OFFSET_MASK) << MMU_ADDR_PAGE_OFFSET_LSB))
|
|||
|
+#define GET_MMU_ADDR_PFN(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_PFN_LSB) & MMU_ADDR_PFN_MASK)
|
|||
|
+#define SET_MMU_ADDR_PFN(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_PFN_MASK << MMU_ADDR_PFN_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_PFN_MASK) << MMU_ADDR_PFN_LSB))
|
|||
|
+#define GET_MMU_ADDR_USER_REGION(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_USER_REGION_LSB) & MMU_ADDR_USER_REGION_MASK)
|
|||
|
+#define SET_MMU_ADDR_USER_REGION(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_USER_REGION_MASK << MMU_ADDR_USER_REGION_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_USER_REGION_MASK) << MMU_ADDR_USER_REGION_LSB))
|
|||
|
+#define GET_MMU_ADDR_VPN(Addr) \
|
|||
|
+ (((Addr) >> MMU_ADDR_VPN_LSB) & MMU_ADDR_VPN_MASK)
|
|||
|
+#define SET_MMU_ADDR_VPN(Addr, Val) \
|
|||
|
+ Addr = (((Addr) & (~(MMU_ADDR_VPN_MASK << MMU_ADDR_VPN_LSB))) | \
|
|||
|
+ (((Val) & MMU_ADDR_VPN_MASK) << MMU_ADDR_VPN_LSB))
|
|||
|
+
|
|||
|
+/* OP instruction values */
|
|||
|
+#define OP_ADDI 4
|
|||
|
+#define OP_ANDHI 44
|
|||
|
+#define OP_ANDI 12
|
|||
|
+#define OP_BEQ 38
|
|||
|
+#define OP_BGE 14
|
|||
|
+#define OP_BGEU 46
|
|||
|
+#define OP_BLT 22
|
|||
|
+#define OP_BLTU 54
|
|||
|
+#define OP_BNE 30
|
|||
|
+#define OP_BR 6
|
|||
|
+#define OP_CALL 0
|
|||
|
+#define OP_CMPEQI 32
|
|||
|
+#define OP_CMPGEI 8
|
|||
|
+#define OP_CMPGEUI 40
|
|||
|
+#define OP_CMPLTI 16
|
|||
|
+#define OP_CMPLTUI 48
|
|||
|
+#define OP_CMPNEI 24
|
|||
|
+#define OP_CUSTOM 50
|
|||
|
+#define OP_FLUSHD 59
|
|||
|
+#define OP_FLUSHDA 27
|
|||
|
+#define OP_INITD 51
|
|||
|
+#define OP_JMPI 1
|
|||
|
+#define OP_LDB 7
|
|||
|
+#define OP_LDBIO 39
|
|||
|
+#define OP_LDBU 3
|
|||
|
+#define OP_LDBUIO 35
|
|||
|
+#define OP_LDH 15
|
|||
|
+#define OP_LDHIO 47
|
|||
|
+#define OP_LDHU 11
|
|||
|
+#define OP_LDHUIO 43
|
|||
|
+#define OP_LDW 23
|
|||
|
+#define OP_LDWIO 55
|
|||
|
+#define OP_MULI 36
|
|||
|
+#define OP_OPX 58
|
|||
|
+#define OP_ORHI 52
|
|||
|
+#define OP_ORI 20
|
|||
|
+#define OP_STB 5
|
|||
|
+#define OP_STBIO 37
|
|||
|
+#define OP_STH 13
|
|||
|
+#define OP_STHIO 45
|
|||
|
+#define OP_STW 21
|
|||
|
+#define OP_STWIO 53
|
|||
|
+#define OP_XORHI 60
|
|||
|
+#define OP_XORI 28
|
|||
|
+
|
|||
|
+/* OPX instruction values */
|
|||
|
+#define OPX_ADD 49
|
|||
|
+#define OPX_AND 14
|
|||
|
+#define OPX_BREAK 52
|
|||
|
+#define OPX_BRET 9
|
|||
|
+#define OPX_CALLR 29
|
|||
|
+#define OPX_CMPEQ 32
|
|||
|
+#define OPX_CMPGE 8
|
|||
|
+#define OPX_CMPGEU 40
|
|||
|
+#define OPX_CMPLT 16
|
|||
|
+#define OPX_CMPLTU 48
|
|||
|
+#define OPX_CMPNE 24
|
|||
|
+#define OPX_CRST 62
|
|||
|
+#define OPX_DIV 37
|
|||
|
+#define OPX_DIVU 36
|
|||
|
+#define OPX_ERET 1
|
|||
|
+#define OPX_FLUSHI 12
|
|||
|
+#define OPX_FLUSHP 4
|
|||
|
+#define OPX_HBREAK 53
|
|||
|
+#define OPX_INITI 41
|
|||
|
+#define OPX_INTR 61
|
|||
|
+#define OPX_JMP 13
|
|||
|
+#define OPX_MUL 39
|
|||
|
+#define OPX_MULXSS 31
|
|||
|
+#define OPX_MULXSU 23
|
|||
|
+#define OPX_MULXUU 7
|
|||
|
+#define OPX_NEXTPC 28
|
|||
|
+#define OPX_NOR 6
|
|||
|
+#define OPX_OR 22
|
|||
|
+#define OPX_RDCTL 38
|
|||
|
+#define OPX_RET 5
|
|||
|
+#define OPX_ROL 3
|
|||
|
+#define OPX_ROLI 2
|
|||
|
+#define OPX_ROR 11
|
|||
|
+#define OPX_SLL 19
|
|||
|
+#define OPX_SLLI 18
|
|||
|
+#define OPX_SRA 59
|
|||
|
+#define OPX_SRAI 58
|
|||
|
+#define OPX_SRL 27
|
|||
|
+#define OPX_SRLI 26
|
|||
|
+#define OPX_SUB 57
|
|||
|
+#define OPX_SYNC 54
|
|||
|
+#define OPX_TRAP 45
|
|||
|
+#define OPX_WRCTL 46
|
|||
|
+#define OPX_XOR 30
|
|||
|
+
|
|||
|
+/* Macros to detect sub-opcode instructions */
|
|||
|
+#define IS_OPX_INST(Iw) (GET_IW_OP(Iw) == OP_OPX)
|
|||
|
+#define IS_CUSTOM_INST(Iw) (GET_IW_OP(Iw) == OP_CUSTOM)
|
|||
|
+
|
|||
|
+/* Instruction property macros */
|
|||
|
+#define IW_PROP_RESERVED_OP(Iw) (0)
|
|||
|
+
|
|||
|
+#define IW_PROP_RESERVED_OPX(Iw) (0)
|
|||
|
+
|
|||
|
+#define IW_PROP_RESERVED(Iw) (0)
|
|||
|
+
|
|||
|
+#define IW_PROP_SUPERVISOR_ONLY(Iw) ( \
|
|||
|
+ (op_prop_supervisor_only[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_supervisor_only[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_supervisor_only[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_supervisor_only[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_INITI_FLUSHI(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_INITI) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_FLUSHI) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_FLUSH_PIPE(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_flush_pipe[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_flush_pipe[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_JMP_INDIRECT_NON_TRAP(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_jmp_indirect_non_trap[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_jmp_indirect_non_trap[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_JMP_INDIRECT(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_jmp_indirect[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_jmp_indirect[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_JMP_DIRECT(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_CALL)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_JMPI)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_MUL_LSW(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_MULI)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_MUL) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_MULX(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_mulx[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_mulx[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_MUL(Iw) ( \
|
|||
|
+ (op_prop_mul[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_mul[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_mul[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_mul[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_DIV_UNSIGNED(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_DIVU) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_DIV_SIGNED(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_DIV) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_DIV(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_DIVU) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_DIV) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_UNIMPLEMENTED(Iw) (0)
|
|||
|
+
|
|||
|
+#define IW_PROP_IMPLICIT_DST_RETADDR(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_CALL)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_IMPLICIT_DST_ERETADDR(Iw) (0)
|
|||
|
+
|
|||
|
+#define IW_PROP_EXCEPTION(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_TRAP) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_INTR) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_BREAK(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_BREAK) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_HBREAK) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_CRST(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_CRST) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_WR_CTL_REG(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_wr_ctl_reg[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_wr_ctl_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_UNCOND_CTI_NON_BR(Iw) ( \
|
|||
|
+ (op_prop_uncond_cti_non_br[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_uncond_cti_non_br[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_uncond_cti_non_br[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_uncond_cti_non_br[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_RETADDR(Iw) ( \
|
|||
|
+ (op_prop_retaddr[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_retaddr[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_retaddr[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_retaddr[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_LEFT(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_SLLI) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_SLL) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_LOGICAL(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_shift_logical[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_shift_logical[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_ROT_LEFT(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_ROLI) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_ROL) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_ROT_LEFT(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_shift_rot_left[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_shift_rot_left[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_RIGHT_LOGICAL(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_SRLI) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_SRL) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_RIGHT_ARITH(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_SRAI) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_SRA) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_RIGHT(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_shift_right[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_shift_right[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_ROT_RIGHT(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_ROR) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_ROT_RIGHT(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_shift_rot_right[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_shift_rot_right[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_ROT(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_shift_rot[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_shift_rot[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SHIFT_ROT_IMM(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_shift_rot_imm[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_shift_rot_imm[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_ROTATE(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_rotate[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_rotate[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOGIC_REG(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_logic_reg[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_logic_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOGIC_HI_IMM16(Iw) ( \
|
|||
|
+ (op_prop_logic_hi_imm16[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_logic_hi_imm16[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOGIC_LO_IMM16(Iw) ( \
|
|||
|
+ (op_prop_logic_lo_imm16[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_logic_lo_imm16[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOGIC_IMM16(Iw) ( \
|
|||
|
+ (op_prop_logic_imm16[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_logic_imm16[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOGIC(Iw) ( \
|
|||
|
+ (op_prop_logic[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_logic[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_logic[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_logic[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_UNSIGNED_LO_IMM16(Iw) ( \
|
|||
|
+ (op_prop_unsigned_lo_imm16[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_unsigned_lo_imm16[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_unsigned_lo_imm16[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_unsigned_lo_imm16[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_ARITH_IMM16(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_ADDI)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_MULI)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_IMM16(Iw) ( \
|
|||
|
+ (op_prop_cmp_imm16[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_cmp_imm16[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_JMPI(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_JMPI)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_IMM16_WITH_CALL_JMPI(Iw) ( \
|
|||
|
+ (op_prop_cmp_imm16_with_call_jmpi[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_cmp_imm16_with_call_jmpi[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_REG(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_cmp_reg[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_cmp_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SRC_IMM5(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_src_imm5[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_src_imm5[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_WITH_LT(Iw) ( \
|
|||
|
+ (op_prop_cmp_with_lt[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_cmp_with_lt[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_cmp_with_lt[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_cmp_with_lt[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_WITH_EQ(Iw) ( \
|
|||
|
+ (op_prop_cmp_with_eq[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_cmp_with_eq[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_cmp_with_eq[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_cmp_with_eq[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_WITH_GE(Iw) ( \
|
|||
|
+ (op_prop_cmp_with_ge[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_cmp_with_ge[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_cmp_with_ge[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_cmp_with_ge[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_WITH_NE(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_CMPNEI)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_CMPNE) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP_ALU_SIGNED(Iw) ( \
|
|||
|
+ (op_prop_cmp_alu_signed[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_cmp_alu_signed[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_cmp_alu_signed[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_cmp_alu_signed[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_CMP(Iw) ( \
|
|||
|
+ (op_prop_cmp[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_cmp[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_cmp[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_cmp[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_BR_WITH_LT(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BLT)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BLTU)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_BR_WITH_GE(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BGE)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BGEU)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_BR_WITH_EQ(Iw) ( \
|
|||
|
+ (op_prop_br_with_eq[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_br_with_eq[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_BR_WITH_NE(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BNE)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_BR_ALU_SIGNED(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BGE)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BLT)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_BR_COND(Iw) ( \
|
|||
|
+ (op_prop_br_cond[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_br_cond[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_BR_UNCOND(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_BR)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_BR(Iw) ( \
|
|||
|
+ (op_prop_br[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_br[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_ALU_SUB(Iw) ( \
|
|||
|
+ (op_prop_alu_sub[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_alu_sub[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_alu_sub[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_alu_sub[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_FORCE_XOR(Iw) ( \
|
|||
|
+ (op_prop_force_xor[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_force_xor[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_force_xor[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_force_xor[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD8(Iw) ( \
|
|||
|
+ (op_prop_load8[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load8[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD16(Iw) ( \
|
|||
|
+ (op_prop_load16[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load16[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD32(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_LDW)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_LDWIO)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD_SIGNED(Iw) ( \
|
|||
|
+ (op_prop_load_signed[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load_signed[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD_UNSIGNED(Iw) ( \
|
|||
|
+ (op_prop_load_unsigned[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load_unsigned[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD(Iw) ( \
|
|||
|
+ (op_prop_load[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD_INITD_FLUSHD_FLUSHDA(Iw) ( \
|
|||
|
+ (op_prop_load_initd_flushd_flushda[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load_initd_flushd_flushda[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD_NON_IO(Iw) ( \
|
|||
|
+ (op_prop_load_non_io[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load_non_io[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_STORE8(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_STB)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_STBIO)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_STORE16(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_STH)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_STHIO)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_STORE32(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_STW)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_STWIO)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_STORE(Iw) ( \
|
|||
|
+ (op_prop_store[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_store[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_STORE_NON_IO(Iw) ( \
|
|||
|
+ (op_prop_store_non_io[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_store_non_io[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_MEM(Iw) ( \
|
|||
|
+ (op_prop_mem[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_mem[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_INITD(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_INITD)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_FLUSHD(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_FLUSHD)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_INITD_FLUSHD(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_INITD)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_FLUSHD)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_FLUSHDA(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_FLUSHDA)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_FLUSHD_FLUSHDA(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_FLUSHD)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_FLUSHDA)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_INITD_FLUSHD_FLUSHDA(Iw) ( \
|
|||
|
+ (op_prop_initd_flushd_flushda[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_initd_flushd_flushda[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_LOAD_IO(Iw) ( \
|
|||
|
+ (op_prop_load_io[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_load_io[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_STORE_IO(Iw) ( \
|
|||
|
+ (op_prop_store_io[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_store_io[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_MEM_IO(Iw) ( \
|
|||
|
+ (op_prop_mem_io[GET_IW_OP(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_mem_io[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_ARITH(Iw) ( \
|
|||
|
+ (op_prop_arith[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_arith[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_arith[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_arith[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_A_NOT_SRC(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_CALL)) || \
|
|||
|
+ ((GET_IW_OP((Iw)) == OP_JMPI)) \
|
|||
|
+ ) \
|
|||
|
+ || (IS_CUSTOM_INST(Iw) && !GET_IW_CUSTOM_READRA(Iw)) \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_B_NOT_SRC(Iw) ( \
|
|||
|
+ (op_prop_b_not_src[GET_IW_OP(Iw)]) \
|
|||
|
+ || (IS_CUSTOM_INST(Iw) && !GET_IW_CUSTOM_READRB(Iw)))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_b_not_src[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_IGNORE_DST(Iw) ( \
|
|||
|
+ (op_prop_ignore_dst[GET_IW_OP(Iw)]) \
|
|||
|
+ || (IS_CUSTOM_INST(Iw) && !GET_IW_CUSTOM_WRITERC(Iw)))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_ignore_dst[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SRC2_CHOOSE_IMM(Iw) ( \
|
|||
|
+ (op_prop_src2_choose_imm[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_src2_choose_imm[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_src2_choose_imm[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_src2_choose_imm[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_WRCTL_INST(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_WRCTL) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_RDCTL_INST(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_RDCTL) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_MUL_SRC1_SIGNED(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_MULXSS) && IS_OPX_INST(Iw)) || \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_MULXSU) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_MUL_SRC2_SIGNED(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_MULXSS) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_MUL_SHIFT_SRC1_SIGNED(Iw) ( \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_mul_shift_src1_signed[GET_IW_OPX(Iw)]))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_mul_shift_src1_signed[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_MUL_SHIFT_SRC2_SIGNED(Iw) ( \
|
|||
|
+ ( \
|
|||
|
+ ((GET_IW_OPX((Iw)) == OPX_MULXSS) && IS_OPX_INST(Iw)) \
|
|||
|
+ ) \
|
|||
|
+ \
|
|||
|
+)
|
|||
|
+
|
|||
|
+#define IW_PROP_DONT_DISPLAY_DST_REG(Iw) ( \
|
|||
|
+ (op_prop_dont_display_dst_reg[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_dont_display_dst_reg[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_dont_display_dst_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_dont_display_dst_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_DONT_DISPLAY_SRC1_REG(Iw) ( \
|
|||
|
+ (op_prop_dont_display_src1_reg[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_dont_display_src1_reg[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_dont_display_src1_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_dont_display_src1_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_DONT_DISPLAY_SRC2_REG(Iw) ( \
|
|||
|
+ (op_prop_dont_display_src2_reg[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_dont_display_src2_reg[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_dont_display_src2_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_dont_display_src2_reg[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SRC1_NO_X(Iw) ( \
|
|||
|
+ (op_prop_src1_no_x[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_src1_no_x[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_src1_no_x[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_src1_no_x[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#define IW_PROP_SRC2_NO_X(Iw) ( \
|
|||
|
+ (op_prop_src2_no_x[GET_IW_OP(Iw)] || \
|
|||
|
+ (IS_OPX_INST(Iw) && opx_prop_src2_no_x[GET_IW_OPX(Iw)])))
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char op_prop_src2_no_x[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern unsigned char opx_prop_src2_no_x[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+/* Instruction types */
|
|||
|
+#define INST_TYPE_OP 0
|
|||
|
+#define INST_TYPE_OPX 1
|
|||
|
+
|
|||
|
+/* Canonical instruction codes independent of encoding */
|
|||
|
+#define CALL_INST_CODE 0
|
|||
|
+#define JMPI_INST_CODE 1
|
|||
|
+#define LDBU_INST_CODE 2
|
|||
|
+#define ADDI_INST_CODE 3
|
|||
|
+#define STB_INST_CODE 4
|
|||
|
+#define BR_INST_CODE 5
|
|||
|
+#define LDB_INST_CODE 6
|
|||
|
+#define CMPGEI_INST_CODE 7
|
|||
|
+#define LDHU_INST_CODE 8
|
|||
|
+#define ANDI_INST_CODE 9
|
|||
|
+#define STH_INST_CODE 10
|
|||
|
+#define BGE_INST_CODE 11
|
|||
|
+#define LDH_INST_CODE 12
|
|||
|
+#define CMPLTI_INST_CODE 13
|
|||
|
+#define ORI_INST_CODE 14
|
|||
|
+#define STW_INST_CODE 15
|
|||
|
+#define BLT_INST_CODE 16
|
|||
|
+#define LDW_INST_CODE 17
|
|||
|
+#define CMPNEI_INST_CODE 18
|
|||
|
+#define FLUSHDA_INST_CODE 19
|
|||
|
+#define XORI_INST_CODE 20
|
|||
|
+#define BNE_INST_CODE 21
|
|||
|
+#define CMPEQI_INST_CODE 22
|
|||
|
+#define LDBUIO_INST_CODE 23
|
|||
|
+#define MULI_INST_CODE 24
|
|||
|
+#define STBIO_INST_CODE 25
|
|||
|
+#define BEQ_INST_CODE 26
|
|||
|
+#define LDBIO_INST_CODE 27
|
|||
|
+#define CMPGEUI_INST_CODE 28
|
|||
|
+#define LDHUIO_INST_CODE 29
|
|||
|
+#define ANDHI_INST_CODE 30
|
|||
|
+#define STHIO_INST_CODE 31
|
|||
|
+#define BGEU_INST_CODE 32
|
|||
|
+#define LDHIO_INST_CODE 33
|
|||
|
+#define CMPLTUI_INST_CODE 34
|
|||
|
+#define CUSTOM_INST_CODE 35
|
|||
|
+#define INITD_INST_CODE 36
|
|||
|
+#define ORHI_INST_CODE 37
|
|||
|
+#define STWIO_INST_CODE 38
|
|||
|
+#define BLTU_INST_CODE 39
|
|||
|
+#define LDWIO_INST_CODE 40
|
|||
|
+#define FLUSHD_INST_CODE 41
|
|||
|
+#define XORHI_INST_CODE 42
|
|||
|
+#define ERET_INST_CODE 43
|
|||
|
+#define ROLI_INST_CODE 44
|
|||
|
+#define ROL_INST_CODE 45
|
|||
|
+#define FLUSHP_INST_CODE 46
|
|||
|
+#define RET_INST_CODE 47
|
|||
|
+#define NOR_INST_CODE 48
|
|||
|
+#define MULXUU_INST_CODE 49
|
|||
|
+#define CMPGE_INST_CODE 50
|
|||
|
+#define BRET_INST_CODE 51
|
|||
|
+#define ROR_INST_CODE 52
|
|||
|
+#define FLUSHI_INST_CODE 53
|
|||
|
+#define JMP_INST_CODE 54
|
|||
|
+#define AND_INST_CODE 55
|
|||
|
+#define CMPLT_INST_CODE 56
|
|||
|
+#define SLLI_INST_CODE 57
|
|||
|
+#define SLL_INST_CODE 58
|
|||
|
+#define OR_INST_CODE 59
|
|||
|
+#define MULXSU_INST_CODE 60
|
|||
|
+#define CMPNE_INST_CODE 61
|
|||
|
+#define SRLI_INST_CODE 62
|
|||
|
+#define SRL_INST_CODE 63
|
|||
|
+#define NEXTPC_INST_CODE 64
|
|||
|
+#define CALLR_INST_CODE 65
|
|||
|
+#define XOR_INST_CODE 66
|
|||
|
+#define MULXSS_INST_CODE 67
|
|||
|
+#define CMPEQ_INST_CODE 68
|
|||
|
+#define DIVU_INST_CODE 69
|
|||
|
+#define DIV_INST_CODE 70
|
|||
|
+#define RDCTL_INST_CODE 71
|
|||
|
+#define MUL_INST_CODE 72
|
|||
|
+#define CMPGEU_INST_CODE 73
|
|||
|
+#define INITI_INST_CODE 74
|
|||
|
+#define TRAP_INST_CODE 75
|
|||
|
+#define WRCTL_INST_CODE 76
|
|||
|
+#define CMPLTU_INST_CODE 77
|
|||
|
+#define ADD_INST_CODE 78
|
|||
|
+#define BREAK_INST_CODE 79
|
|||
|
+#define HBREAK_INST_CODE 80
|
|||
|
+#define SYNC_INST_CODE 81
|
|||
|
+#define SUB_INST_CODE 82
|
|||
|
+#define SRAI_INST_CODE 83
|
|||
|
+#define SRA_INST_CODE 84
|
|||
|
+#define INTR_INST_CODE 85
|
|||
|
+#define CRST_INST_CODE 86
|
|||
|
+#define RSV_INST_CODE 87
|
|||
|
+#define NUM_NIOS2_INST_CODES 88
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+/* Instruction information entry */
|
|||
|
+typedef struct {
|
|||
|
+ const char* name; /* Assembly-language instruction name */
|
|||
|
+ int instType; /* INST_TYPE_OP or INST_TYPE_OPX */
|
|||
|
+ unsigned opcode; /* Value of instruction word OP/OPX field */
|
|||
|
+} Nios2InstInfo;
|
|||
|
+
|
|||
|
+extern Nios2InstInfo nios2InstInfo[NUM_NIOS2_INST_CODES];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+/* Returns the instruction code given the 32-bit instruction word */
|
|||
|
+#define GET_INST_CODE(Iw) \
|
|||
|
+ (IS_OPX_INST(Iw) ? opxToInstCode[GET_IW_OPX(Iw)] : opToInstCode[GET_IW_OP(Iw)])
|
|||
|
+
|
|||
|
+#ifndef ALT_ASM_SRC
|
|||
|
+extern int opToInstCode[64];
|
|||
|
+extern int opxToInstCode[64];
|
|||
|
+#endif /* ALT_ASM_SRC */
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ * MMU Memory Region Macros
|
|||
|
+ */
|
|||
|
+#define USER_REGION_MIN_VADDR 0x00000000
|
|||
|
+#define USER_REGION_MAX_VADDR 0x7fffffff
|
|||
|
+#define KERNEL_MMU_REGION_MIN_VADDR 0x80000000
|
|||
|
+#define KERNEL_MMU_REGION_MAX_VADDR 0xbfffffff
|
|||
|
+#define KERNEL_REGION_MIN_VADDR 0xc0000000
|
|||
|
+#define KERNEL_REGION_MAX_VADDR 0xdfffffff
|
|||
|
+#define IO_REGION_MIN_VADDR 0xe0000000
|
|||
|
+#define IO_REGION_MAX_VADDR 0xffffffff
|
|||
|
+
|
|||
|
+#define MMU_PAGE_SIZE (0x1 << (MMU_ADDR_PAGE_OFFSET_SZ))
|
|||
|
+
|
|||
|
+#define isMmuUserRegion(Vaddr) \
|
|||
|
+ (GET_MMU_ADDR_USER_REGION(Vaddr) == MMU_ADDR_USER_REGION)
|
|||
|
+#define isMmuKernelMmuRegion(Vaddr) \
|
|||
|
+ (GET_MMU_ADDR_KERNEL_MMU_REGION(Vaddr) == MMU_ADDR_KERNEL_MMU_REGION)
|
|||
|
+#define isMmuKernelRegion(Vaddr) \
|
|||
|
+ (GET_MMU_ADDR_KERNEL_REGION(Vaddr) == MMU_ADDR_KERNEL_REGION)
|
|||
|
+#define isMmuIORegion(Vaddr) \
|
|||
|
+ (GET_MMU_ADDR_IO_REGION(Vaddr) == MMU_ADDR_IO_REGION)
|
|||
|
+
|
|||
|
+/* Does this virtual address bypass the TLB? */
|
|||
|
+#define vaddrBypassTlb(Vaddr) \
|
|||
|
+ (GET_MMU_ADDR_BYPASS_TLB(Vaddr) == MMU_ADDR_BYPASS_TLB)
|
|||
|
+
|
|||
|
+/* If TLB is bypassed, is the address cacheable or uncachable. */
|
|||
|
+#define vaddrBypassTlbCacheable(Vaddr) \
|
|||
|
+ (GET_MMU_ADDR_BYPASS_TLB_CACHEABLE(Vaddr) == MMU_ADDR_BYPASS_TLB_CACHEABLE)
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ * Compute physical address for regions that bypass the TLB.
|
|||
|
+ * Just need to clear some top bits.
|
|||
|
+ */
|
|||
|
+#define bypassTlbVaddrToPaddr(Vaddr) \
|
|||
|
+ ((Vaddr) & (MMU_ADDR_BYPASS_TLB_PADDR_MASK << MMU_ADDR_BYPASS_TLB_PADDR_LSB))
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ * Will the physical address fit in the Kernel/IO region virtual address space?
|
|||
|
+ */
|
|||
|
+#define fitsInKernelRegion(Paddr) \
|
|||
|
+ (GET_MMU_ADDR_KERNEL_REGION(Paddr) == 0)
|
|||
|
+#define fitsInIORegion(Paddr) \
|
|||
|
+ (GET_MMU_ADDR_IO_REGION(Paddr) == 0)
|
|||
|
+
|
|||
|
+/* Convert a physical address to a Kernel/IO region virtual address. */
|
|||
|
+#define paddrToKernelRegionVaddr(Paddr) \
|
|||
|
+ ((Paddr) | (MMU_ADDR_KERNEL_REGION << MMU_ADDR_KERNEL_REGION_LSB))
|
|||
|
+#define paddrToIORegionVaddr(Paddr) \
|
|||
|
+ ((Paddr) | (MMU_ADDR_IO_REGION << MMU_ADDR_IO_REGION_LSB))
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ * Convert a virtual address to a Kernel/IO region virtual address.
|
|||
|
+ * Uses bypassTlbVaddrToPaddr to clear top bits.
|
|||
|
+ */
|
|||
|
+#define vaddrToKernelRegionVaddr(Vaddr) \
|
|||
|
+ paddrToKernelRegionVaddr(bypassTlbVaddrToPaddr(Vaddr))
|
|||
|
+#define vaddrToIORegionVaddr(Vaddr) \
|
|||
|
+ paddrToIORegionVaddr(bypassTlbVaddrToPaddr(Vaddr))
|
|||
|
+
|
|||
|
+/* Convert between VPN/PFN and virtual/physical addresses. */
|
|||
|
+#define vpnToVaddr(Vpn) ((Vpn) << MMU_ADDR_VPN_LSB)
|
|||
|
+#define pfnToPaddr(Pfn) ((Pfn) << MMU_ADDR_PFN_LSB)
|
|||
|
+#define vaddrToVpn(Vaddr) GET_MMU_ADDR_VPN(Vaddr)
|
|||
|
+#define paddrToPfn(Paddr) GET_MMU_ADDR_PFN(Paddr)
|
|||
|
+
|
|||
|
+/* Bitwise OR with a KERNEL region address to make it an IO region address */
|
|||
|
+#define KERNEL_TO_IO_REGION 0x20000000
|
|||
|
+
|
|||
|
+#endif /* _NIOS2_ISA_H_ */
|
|||
|
diff --git a/include/opcode/nios2.h b/include/opcode/nios2.h
|
|||
|
new file mode 100644
|
|||
|
index 0000000..992bb80
|
|||
|
--- /dev/null
|
|||
|
+++ b/include/opcode/nios2.h
|
|||
|
@@ -0,0 +1,361 @@
|
|||
|
+/* nios2.h. Altera New Jersey opcode list for GAS, the GNU assembler.
|
|||
|
+
|
|||
|
+ Copyright (C) 2003
|
|||
|
+ by Nigel Gray (ngray@altera.com).
|
|||
|
+
|
|||
|
+This file is part of GDB, GAS, and the GNU binutils.
|
|||
|
+
|
|||
|
+GDB, GAS, and the GNU binutils are free software; you can redistribute
|
|||
|
+them and/or modify them under the terms of the GNU General Public
|
|||
|
+License as published by the Free Software Foundation; either version
|
|||
|
+1, or (at your option) any later version.
|
|||
|
+
|
|||
|
+GDB, GAS, and the GNU binutils are distributed in the hope that they
|
|||
|
+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 a copy of the GNU General Public License
|
|||
|
+along with this file; see the file COPYING. If not, write to the Free
|
|||
|
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+#ifndef _NIOS2_H_
|
|||
|
+#define _NIOS2_H_
|
|||
|
+
|
|||
|
+
|
|||
|
+/****************************************************************************
|
|||
|
+ * This file contains structures, bit masks and shift counts used
|
|||
|
+ * by the GNU toolchain to define the New Jersey instruction set and
|
|||
|
+ * access various opcode fields.
|
|||
|
+ ****************************************************************************/
|
|||
|
+
|
|||
|
+enum overflow_type
|
|||
|
+{
|
|||
|
+ call_target_overflow = 0,
|
|||
|
+ branch_target_overflow,
|
|||
|
+ address_offset_overflow,
|
|||
|
+ signed_immed16_overflow,
|
|||
|
+ unsigned_immed16_overflow,
|
|||
|
+ unsigned_immed5_overflow,
|
|||
|
+ custom_opcode_overflow,
|
|||
|
+ no_overflow
|
|||
|
+};
|
|||
|
+
|
|||
|
+/*---------------------------------------------------------------------------
|
|||
|
+ This structure holds information for a particular instruction
|
|||
|
+ ---------------------------------------------------------------------------*/
|
|||
|
+
|
|||
|
+/* match When assembling, this
|
|||
|
+ opcode is modified by the arguments to produce the actual opcode
|
|||
|
+ that is used. If pinfo is INSN_MACRO, then this is 0. */
|
|||
|
+
|
|||
|
+/* mask If pinfo is not INSN_MACRO, then this is a bit mask for the
|
|||
|
+ relevant portions of the opcode when disassembling. If the
|
|||
|
+ actual opcode anded with the match field equals the opcode field,
|
|||
|
+ then we have found the correct instruction. If pinfo is
|
|||
|
+ INSN_MACRO, then this field is the macro identifier. */
|
|||
|
+
|
|||
|
+/* For a macro, this is INSN_MACRO. Otherwise, it is a collection
|
|||
|
+ of bits describing the instruction, notably any relevant hazard
|
|||
|
+ information. */
|
|||
|
+
|
|||
|
+struct nios2_opcode
|
|||
|
+{
|
|||
|
+ const char *name; /* The name of the instruction. */
|
|||
|
+ const char *args; /* A string describing the arguments for this instruction. */
|
|||
|
+ const char *args_test; /* Like args, but with an extra argument for the expected opcode */
|
|||
|
+ unsigned long num_args; /* the number of arguments the instruction takes */
|
|||
|
+ unsigned long match; /* The basic opcode for the instruction. */
|
|||
|
+ unsigned long mask; /* mask for the opcode field of the instruction */
|
|||
|
+ unsigned long pinfo; /* is this a real instruction or instruction macro */
|
|||
|
+ enum overflow_type overflow_msg; /* msg template used to generate informative message when fixup overflows */
|
|||
|
+};
|
|||
|
+
|
|||
|
+/* This value is used in the nios2_opcode.pinfo field to indicate that the instruction
|
|||
|
+ is a macro or pseudo-op. This requires special treatment by the assembler, and is
|
|||
|
+ used by the disassembler to determine whether to check for a nop */
|
|||
|
+#define NIOS2_INSN_MACRO 0x80000000
|
|||
|
+#define NIOS2_INSN_MACRO_MOV 0x80000001
|
|||
|
+#define NIOS2_INSN_MACRO_MOVI 0x80000002
|
|||
|
+#define NIOS2_INSN_MACRO_MOVIA 0x80000004
|
|||
|
+
|
|||
|
+#define NIOS2_INSN_RELAXABLE 0x40000000
|
|||
|
+#define NIOS2_INSN_UBRANCH 0x00000010
|
|||
|
+#define NIOS2_INSN_CBRANCH 0x00000020
|
|||
|
+#define NIOS2_INSN_CALL 0x00000040
|
|||
|
+
|
|||
|
+#define NIOS2_INSN_ADDI 0x00000080
|
|||
|
+#define NIOS2_INSN_ANDI 0x00000100
|
|||
|
+#define NIOS2_INSN_ORI 0x00000200
|
|||
|
+#define NIOS2_INSN_XORI 0x00000400
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Associates a register name ($6) with a 5-bit index (eg 6) */
|
|||
|
+struct nios2_reg
|
|||
|
+{
|
|||
|
+ const char *name;
|
|||
|
+ const int index;
|
|||
|
+};
|
|||
|
+
|
|||
|
+
|
|||
|
+/* -------------------------------------------------------------------------
|
|||
|
+ Bitfield masks for New Jersey instructions
|
|||
|
+ -------------------------------------------------------------------------*/
|
|||
|
+
|
|||
|
+/* These are bit masks and shift counts to use to access the various
|
|||
|
+ fields of an instruction. */
|
|||
|
+
|
|||
|
+/* Macros for getting and setting an instruction field */
|
|||
|
+#define GET_INSN_FIELD(X, i) ((i) & OP_MASK_##X) >> OP_SH_##X
|
|||
|
+#define SET_INSN_FIELD(X, i, j) (i) = ((i) &~ (OP_MASK_##X)) | ((j) << OP_SH_##X)
|
|||
|
+
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ We include the auto-generated file nios2-isa.h and define the mask
|
|||
|
+ and shifts below in terms of those in nios2-isa.h. This ensures
|
|||
|
+ that the binutils and hardware are always in sync
|
|||
|
+*/
|
|||
|
+
|
|||
|
+#include "nios2-isa.h"
|
|||
|
+
|
|||
|
+#define OP_MASK_OP (IW_OP_MASK << IW_OP_LSB)
|
|||
|
+#define OP_SH_OP IW_OP_LSB
|
|||
|
+
|
|||
|
+
|
|||
|
+/* Masks and shifts for I-type instructions */
|
|||
|
+
|
|||
|
+#define OP_MASK_IOP (IW_OP_MASK << IW_OP_LSB)
|
|||
|
+#define OP_SH_IOP IW_OP_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_IMM16 (IW_IMM16_MASK << IW_IMM16_LSB)
|
|||
|
+#define OP_SH_IMM16 IW_IMM16_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_IRD (IW_B_MASK << IW_B_LSB) // the same as T for I-type
|
|||
|
+#define OP_SH_IRD IW_B_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_IRT (IW_B_MASK << IW_B_LSB)
|
|||
|
+#define OP_SH_IRT IW_B_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_IRS (IW_A_MASK << IW_A_LSB)
|
|||
|
+#define OP_SH_IRS IW_A_LSB
|
|||
|
+
|
|||
|
+/* Masks and shifts for R-type instructions */
|
|||
|
+
|
|||
|
+#define OP_MASK_ROP (IW_OP_MASK << IW_OP_LSB)
|
|||
|
+#define OP_SH_ROP IW_OP_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_ROPX (IW_OPX_MASK << IW_OPX_LSB)
|
|||
|
+#define OP_SH_ROPX IW_OPX_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_RRD (IW_C_MASK << IW_C_LSB)
|
|||
|
+#define OP_SH_RRD IW_C_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_RRT (IW_B_MASK << IW_B_LSB)
|
|||
|
+#define OP_SH_RRT IW_B_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_RRS (IW_A_MASK << IW_A_LSB)
|
|||
|
+#define OP_SH_RRS IW_A_LSB
|
|||
|
+
|
|||
|
+/* Masks and shifts for J-type instructions */
|
|||
|
+
|
|||
|
+#define OP_MASK_JOP (IW_OP_MASK << IW_OP_LSB)
|
|||
|
+#define OP_SH_JOP IW_OP_LSB
|
|||
|
+
|
|||
|
+#define OP_MASK_IMM26 (IW_IMM26_MASK << IW_IMM26_LSB)
|
|||
|
+#define OP_SH_IMM26 IW_IMM26_LSB
|
|||
|
+
|
|||
|
+/* Masks and shifts for CTL instructions */
|
|||
|
+
|
|||
|
+#define OP_MASK_RCTL 0x000007c0
|
|||
|
+#define OP_SH_RCTL 6
|
|||
|
+
|
|||
|
+/* break instruction imm5 field */
|
|||
|
+#define OP_MASK_TRAP_IMM5 0x000007c0
|
|||
|
+#define OP_SH_TRAP_IMM5 6
|
|||
|
+
|
|||
|
+/* instruction imm5 field */
|
|||
|
+#define OP_MASK_IMM5 (IW_SHIFT_IMM5_MASK << IW_SHIFT_IMM5_LSB)
|
|||
|
+#define OP_SH_IMM5 IW_SHIFT_IMM5_LSB
|
|||
|
+
|
|||
|
+/* cache operation fields (type j,i(s)) */
|
|||
|
+#define OP_MASK_CACHE_OPX (IW_B_MASK << IW_B_LSB)
|
|||
|
+#define OP_SH_CACHE_OPX IW_B_LSB
|
|||
|
+#define OP_MASK_CACHE_RRS (IW_A_MASK << IW_A_LSB)
|
|||
|
+#define OP_SH_CACHE_RRS IW_A_LSB
|
|||
|
+
|
|||
|
+/* custom instruction masks */
|
|||
|
+#define OP_MASK_CUSTOM_A 0x00010000
|
|||
|
+#define OP_SH_CUSTOM_A 16
|
|||
|
+
|
|||
|
+#define OP_MASK_CUSTOM_B 0x00008000
|
|||
|
+#define OP_SH_CUSTOM_B 15
|
|||
|
+
|
|||
|
+#define OP_MASK_CUSTOM_C 0x00004000
|
|||
|
+#define OP_SH_CUSTOM_C 14
|
|||
|
+
|
|||
|
+#define OP_MASK_CUSTOM_N 0x00003fc0
|
|||
|
+#define OP_SH_CUSTOM_N 6
|
|||
|
+#define OP_MAX_CUSTOM_N 255
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ The following macros define the opcode matches for each
|
|||
|
+ instruction
|
|||
|
+ code & OP_MASK_INST == OP_MATCH_INST
|
|||
|
+ */
|
|||
|
+
|
|||
|
+/* OP instruction matches */
|
|||
|
+#define OP_MATCH_ADDI OP_ADDI
|
|||
|
+#define OP_MATCH_ANDHI OP_ANDHI
|
|||
|
+#define OP_MATCH_ANDI OP_ANDI
|
|||
|
+#define OP_MATCH_BEQ OP_BEQ
|
|||
|
+#define OP_MATCH_BGE OP_BGE
|
|||
|
+#define OP_MATCH_BGEU OP_BGEU
|
|||
|
+#define OP_MATCH_BLT OP_BLT
|
|||
|
+#define OP_MATCH_BLTU OP_BLTU
|
|||
|
+#define OP_MATCH_BNE OP_BNE
|
|||
|
+#define OP_MATCH_BR OP_BR
|
|||
|
+#define OP_MATCH_FLUSHD OP_FLUSHD
|
|||
|
+#define OP_MATCH_FLUSHDA OP_FLUSHDA
|
|||
|
+#define OP_MATCH_INITD OP_INITD
|
|||
|
+#define OP_MATCH_CALL OP_CALL
|
|||
|
+#define OP_MATCH_CMPEQI OP_CMPEQI
|
|||
|
+#define OP_MATCH_CMPGEI OP_CMPGEI
|
|||
|
+#define OP_MATCH_CMPGEUI OP_CMPGEUI
|
|||
|
+#define OP_MATCH_CMPLTI OP_CMPLTI
|
|||
|
+#define OP_MATCH_CMPLTUI OP_CMPLTUI
|
|||
|
+#define OP_MATCH_CMPNEI OP_CMPNEI
|
|||
|
+#define OP_MATCH_JMPI OP_JMPI
|
|||
|
+#define OP_MATCH_LDB OP_LDB
|
|||
|
+#define OP_MATCH_LDBIO OP_LDBIO
|
|||
|
+#define OP_MATCH_LDBU OP_LDBU
|
|||
|
+#define OP_MATCH_LDBUIO OP_LDBUIO
|
|||
|
+#define OP_MATCH_LDH OP_LDH
|
|||
|
+#define OP_MATCH_LDHIO OP_LDHIO
|
|||
|
+#define OP_MATCH_LDHU OP_LDHU
|
|||
|
+#define OP_MATCH_LDHUIO OP_LDHUIO
|
|||
|
+#define OP_MATCH_LDW OP_LDW
|
|||
|
+#define OP_MATCH_LDWIO OP_LDWIO
|
|||
|
+#define OP_MATCH_MULI OP_MULI
|
|||
|
+#define OP_MATCH_OPX OP_OPX
|
|||
|
+#define OP_MATCH_ORHI OP_ORHI
|
|||
|
+#define OP_MATCH_ORI OP_ORI
|
|||
|
+#define OP_MATCH_STB OP_STB
|
|||
|
+#define OP_MATCH_STBIO OP_STBIO
|
|||
|
+#define OP_MATCH_STH OP_STH
|
|||
|
+#define OP_MATCH_STHIO OP_STHIO
|
|||
|
+#define OP_MATCH_STW OP_STW
|
|||
|
+#define OP_MATCH_STWIO OP_STWIO
|
|||
|
+#define OP_MATCH_CUSTOM OP_CUSTOM
|
|||
|
+#define OP_MATCH_XORHI OP_XORHI
|
|||
|
+#define OP_MATCH_XORI OP_XORI
|
|||
|
+#define OP_MATCH_OPX OP_OPX
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/* OPX instruction values */
|
|||
|
+#define OP_MATCH_ADD ((OPX_ADD << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_AND ((OPX_AND << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_BREAK ((0x1e << 17) | (OPX_BREAK << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_BRET ((0xf0000000) | (OPX_BRET << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_CALLR ((0x1f << 17) | (OPX_CALLR << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_CMPEQ ((OPX_CMPEQ << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_CMPGE ((OPX_CMPGE << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_CMPGEU ((OPX_CMPGEU << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_CMPLT ((OPX_CMPLT << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_CMPLTU ((OPX_CMPLTU << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_CMPNE ((OPX_CMPNE << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_DIV ((OPX_DIV << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_DIVU ((OPX_DIVU << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_JMP ((OPX_JMP << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_MUL ((OPX_MUL << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_MULXSS ((OPX_MULXSS << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_MULXSU ((OPX_MULXSU << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_MULXUU ((OPX_MULXUU << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_NEXTPC ((OPX_NEXTPC << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_NOR ((OPX_NOR << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_OR ((OPX_OR << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_RDCTL ((OPX_RDCTL << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_RET ((0xf8000000) | (OPX_RET << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_ROL ((OPX_ROL << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_ROLI ((OPX_ROLI << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_ROR ((OPX_ROR << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SLL ((OPX_SLL << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SLLI ((OPX_SLLI << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SRA ((OPX_SRA << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SRAI ((OPX_SRAI << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SRL ((OPX_SRL << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SRLI ((OPX_SRLI << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SUB ((OPX_SUB << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_SYNC ((OPX_SYNC << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_TRAP ((0x1d << 17) | (OPX_TRAP << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_ERET ((0xe8000000) | (OPX_ERET << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_WRCTL ((OPX_WRCTL << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_XOR ((OPX_XOR << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_FLUSHI ((OPX_FLUSHI << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_FLUSHP ((OPX_FLUSHP << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+#define OP_MATCH_INITI ((OPX_INITI << IW_OPX_LSB) | (OP_OPX))
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ Some unusual op masks
|
|||
|
+*/
|
|||
|
+#define OP_MASK_BREAK ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP) & 0xfffff03f)
|
|||
|
+#define OP_MASK_CALLR ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_JMP ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_SYNC ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_TRAP ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP) & 0xfffff83f)
|
|||
|
+#define OP_MASK_WRCTL ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP)) /*& 0xfffff83f */
|
|||
|
+#define OP_MASK_NEXTPC ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_FLUSHI ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_INITI ((OP_MASK_RRT | OP_MASK_RRD | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+
|
|||
|
+#define OP_MASK_ROLI ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_SLLI ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_SRAI ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_SRLI ((OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP))
|
|||
|
+#define OP_MASK_RDCTL ((OP_MASK_RRS | OP_MASK_RRT | OP_MASK_ROPX | OP_MASK_OP)) /*& 0xfffff83f */
|
|||
|
+
|
|||
|
+#ifndef OP_MASK
|
|||
|
+#define OP_MASK 0xffffffff
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+/* These are the data structures we use to hold the instruction information */
|
|||
|
+
|
|||
|
+extern const struct nios2_opcode nios2_builtin_opcodes[];
|
|||
|
+extern const int bfd_nios2_num_builtin_opcodes;
|
|||
|
+extern struct nios2_opcode *nios2_opcodes;
|
|||
|
+extern int bfd_nios2_num_opcodes;
|
|||
|
+
|
|||
|
+/* These are the data structures used to hold the operand parsing information */
|
|||
|
+//extern const struct nios2_arg_parser nios2_arg_parsers[];
|
|||
|
+//extern struct nios2_arg_parser* nios2_arg_parsers;
|
|||
|
+//extern const int nios2_num_builtin_arg_parsers;
|
|||
|
+//extern int nios2_num_arg_parsers;
|
|||
|
+
|
|||
|
+/* These are the data structures used to hold the register information */
|
|||
|
+extern const struct nios2_reg nios2_builtin_regs[];
|
|||
|
+extern struct nios2_reg *nios2_regs;
|
|||
|
+extern const int nios2_num_builtin_regs;
|
|||
|
+extern int nios2_num_regs;
|
|||
|
+
|
|||
|
+/* Machine-independent macro for number of opcodes */
|
|||
|
+
|
|||
|
+#define NUMOPCODES bfd_nios2_num_opcodes
|
|||
|
+#define NUMREGISTERS nios2_num_regs;
|
|||
|
+
|
|||
|
+/* these are used in disassembly to get the correct register names */
|
|||
|
+#define NUMREGNAMES 32
|
|||
|
+#define NUMCTLREGNAMES 32
|
|||
|
+#define CTLREGBASE 42
|
|||
|
+#define COPROCREGBASE 83
|
|||
|
+#define NUMCOPROCREGNAMES 32
|
|||
|
+
|
|||
|
+
|
|||
|
+/* this is made extern so that the assembler can use it to find out
|
|||
|
+ what instruction caused an error */
|
|||
|
+extern const struct nios2_opcode *nios2_find_opcode_hash (unsigned long);
|
|||
|
+
|
|||
|
+/* overflow message strings used in the assembler */
|
|||
|
+extern char *overflow_msgs[];
|
|||
|
+
|
|||
|
+#endif // _NIOS2_H
|
|||
|
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
|
|||
|
index ebd252f..a7ca06b 100644
|
|||
|
--- a/opcodes/Makefile.am
|
|||
|
+++ b/opcodes/Makefile.am
|
|||
|
@@ -146,6 +146,13 @@ CFILES = \
|
|||
|
mt-dis.c \
|
|||
|
mt-ibld.c \
|
|||
|
mt-opc.c \
|
|||
|
+ nios2-opc.c \
|
|||
|
+ nios2-dis.c \
|
|||
|
+ ms1-asm.c \
|
|||
|
+ ms1-desc.c \
|
|||
|
+ ms1-dis.c \
|
|||
|
+ ms1-ibld.c \
|
|||
|
+ ms1-opc.c \
|
|||
|
ns32k-dis.c \
|
|||
|
openrisc-asm.c \
|
|||
|
openrisc-desc.c \
|
|||
|
@@ -281,6 +288,8 @@ ALL_MACHINES = \
|
|||
|
mt-dis.lo \
|
|||
|
mt-ibld.lo \
|
|||
|
mt-opc.lo \
|
|||
|
+ nios2-opc.lo \
|
|||
|
+ nios2-dis.lo \
|
|||
|
ns32k-dis.lo \
|
|||
|
openrisc-asm.lo \
|
|||
|
openrisc-desc.lo \
|
|||
|
@@ -980,6 +989,13 @@ mt-opc.lo: mt-opc.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
mt-desc.h $(INCDIR)/opcode/cgen-bitset.h $(INCDIR)/opcode/cgen.h \
|
|||
|
$(INCDIR)/symcat.h $(INCDIR)/opcode/cgen-bitset.h mt-opc.h \
|
|||
|
$(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h
|
|||
|
+nios2-opc.lo: nios2-opc.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
+ $(INCDIR)/opcode/nios2.h
|
|||
|
+nios2-dis.lo: nios2-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
+ $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/symcat.h $(INCDIR)/opcode/nios2.h \
|
|||
|
+ opintl.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \
|
|||
|
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
|
|||
|
+ $(INCDIR)/elf/nios2.h $(INCDIR)/elf/reloc-macros.h
|
|||
|
ns32k-dis.lo: ns32k-dis.c $(BFD_H) $(INCDIR)/ansidecl.h \
|
|||
|
$(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
$(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/opcode/ns32k.h \
|
|||
|
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
|
|||
|
index 85003e6..9e3baae 100644
|
|||
|
--- a/opcodes/Makefile.in
|
|||
|
+++ b/opcodes/Makefile.in
|
|||
|
@@ -360,6 +360,8 @@ CFILES = \
|
|||
|
mt-dis.c \
|
|||
|
mt-ibld.c \
|
|||
|
mt-opc.c \
|
|||
|
+ nios2-opc.c \
|
|||
|
+ nios2-dis.c \
|
|||
|
ns32k-dis.c \
|
|||
|
openrisc-asm.c \
|
|||
|
openrisc-desc.c \
|
|||
|
@@ -495,6 +497,8 @@ ALL_MACHINES = \
|
|||
|
mt-dis.lo \
|
|||
|
mt-ibld.lo \
|
|||
|
mt-opc.lo \
|
|||
|
+ nios2-opc.lo \
|
|||
|
+ nios2-dis.lo \
|
|||
|
ns32k-dis.lo \
|
|||
|
openrisc-asm.lo \
|
|||
|
openrisc-desc.lo \
|
|||
|
@@ -1517,6 +1521,13 @@ mt-opc.lo: mt-opc.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
mt-desc.h $(INCDIR)/opcode/cgen-bitset.h $(INCDIR)/opcode/cgen.h \
|
|||
|
$(INCDIR)/symcat.h $(INCDIR)/opcode/cgen-bitset.h mt-opc.h \
|
|||
|
$(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h
|
|||
|
+nios2-opc.lo: nios2-opc.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
+ $(INCDIR)/opcode/nios2.h
|
|||
|
+nios2-dis.lo: nios2-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
+ $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/symcat.h $(INCDIR)/opcode/nios2.h \
|
|||
|
+ opintl.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \
|
|||
|
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
|
|||
|
+ $(INCDIR)/elf/nios2.h $(INCDIR)/elf/reloc-macros.h
|
|||
|
ns32k-dis.lo: ns32k-dis.c $(BFD_H) $(INCDIR)/ansidecl.h \
|
|||
|
$(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/ansidecl.h \
|
|||
|
$(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/opcode/ns32k.h \
|
|||
|
diff --git a/opcodes/configure b/opcodes/configure
|
|||
|
index 8e3e27e..a28cc46 100755
|
|||
|
--- a/opcodes/configure
|
|||
|
+++ b/opcodes/configure
|
|||
|
@@ -6561,6 +6561,7 @@ if test x${all_targets} = xfalse ; then
|
|||
|
bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;;
|
|||
|
bfd_mt_arch) ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;;
|
|||
|
bfd_msp430_arch) ta="$ta msp430-dis.lo" ;;
|
|||
|
+ bfd_nios2_arch) ta="$ta nios2-opc.lo nios2-dis.lo" ;;
|
|||
|
bfd_ns32k_arch) ta="$ta ns32k-dis.lo" ;;
|
|||
|
bfd_openrisc_arch) ta="$ta openrisc-asm.lo openrisc-desc.lo openrisc-dis.lo openrisc-ibld.lo openrisc-opc.lo" using_cgen=yes ;;
|
|||
|
bfd_or32_arch) ta="$ta or32-dis.lo or32-opc.lo" using_cgen=yes ;;
|
|||
|
diff --git a/opcodes/configure.in b/opcodes/configure.in
|
|||
|
index d937784..c9df814 100644
|
|||
|
--- a/opcodes/configure.in
|
|||
|
+++ b/opcodes/configure.in
|
|||
|
@@ -190,6 +190,7 @@ if test x${all_targets} = xfalse ; then
|
|||
|
bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;;
|
|||
|
bfd_mt_arch) ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;;
|
|||
|
bfd_msp430_arch) ta="$ta msp430-dis.lo" ;;
|
|||
|
+ bfd_nios2_arch) ta="$ta nios2-opc.lo nios2-dis.lo" ;;
|
|||
|
bfd_ns32k_arch) ta="$ta ns32k-dis.lo" ;;
|
|||
|
bfd_openrisc_arch) ta="$ta openrisc-asm.lo openrisc-desc.lo openrisc-dis.lo openrisc-ibld.lo openrisc-opc.lo" using_cgen=yes ;;
|
|||
|
bfd_or32_arch) ta="$ta or32-dis.lo or32-opc.lo" using_cgen=yes ;;
|
|||
|
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
|
|||
|
index ca28f56..dfacbb9 100644
|
|||
|
--- a/opcodes/disassemble.c
|
|||
|
+++ b/opcodes/disassemble.c
|
|||
|
@@ -80,6 +80,7 @@
|
|||
|
#define ARCH_xtensa
|
|||
|
#define ARCH_z80
|
|||
|
#define ARCH_z8k
|
|||
|
+#define ARCH_nios2
|
|||
|
#define INCLUDE_SHMEDIA
|
|||
|
#endif
|
|||
|
|
|||
|
@@ -424,6 +425,14 @@ disassembler (abfd)
|
|||
|
disassemble = print_insn_iq2000;
|
|||
|
break;
|
|||
|
#endif
|
|||
|
+#ifdef ARCH_nios2
|
|||
|
+ case bfd_arch_nios2:
|
|||
|
+ if (bfd_big_endian (abfd))
|
|||
|
+ disassemble = print_insn_big_nios2;
|
|||
|
+ else
|
|||
|
+ disassemble = print_insn_little_nios2;
|
|||
|
+ break;
|
|||
|
+#endif
|
|||
|
#ifdef ARCH_m32c
|
|||
|
case bfd_arch_m32c:
|
|||
|
disassemble = print_insn_m32c;
|
|||
|
diff --git a/opcodes/nios2-dis.c b/opcodes/nios2-dis.c
|
|||
|
new file mode 100644
|
|||
|
index 0000000..ac9eb0d
|
|||
|
--- /dev/null
|
|||
|
+++ b/opcodes/nios2-dis.c
|
|||
|
@@ -0,0 +1,462 @@
|
|||
|
+/* nios2-dis.c -- Altera New Jersey disassemble routines.
|
|||
|
+
|
|||
|
+ Copyright (C) 2003
|
|||
|
+ by Nigel Gray (ngray@altera.com).
|
|||
|
+
|
|||
|
+This file is part of GDB, GAS, and the GNU binutils.
|
|||
|
+
|
|||
|
+GDB, GAS, and the GNU binutils are free software; you can redistribute
|
|||
|
+them and/or modify them under the terms of the GNU General Public
|
|||
|
+License as published by the Free Software Foundation; either version
|
|||
|
+1, or (at your option) any later version.
|
|||
|
+
|
|||
|
+GDB, GAS, and the GNU binutils are distributed in the hope that they
|
|||
|
+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 a copy of the GNU General Public License
|
|||
|
+along with this file; see the file COPYING. If not, write to the Free
|
|||
|
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+#include <stdlib.h>
|
|||
|
+#include <assert.h>
|
|||
|
+#include <string.h>
|
|||
|
+#include "dis-asm.h"
|
|||
|
+#include "opcode/nios2.h"
|
|||
|
+
|
|||
|
+/* No symbol table is available when this code runs out in an embedded
|
|||
|
+ system as when it is used for disassembler support in a monitor. */
|
|||
|
+
|
|||
|
+#if !defined(EMBEDDED_ENV)
|
|||
|
+#define SYMTAB_AVAILABLE 1
|
|||
|
+#include "elf-bfd.h"
|
|||
|
+#include "elf/nios2.h"
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+/* length of New Jersey instruction in bytes */
|
|||
|
+#define INSNLEN 4
|
|||
|
+
|
|||
|
+/* helper function prototypes */
|
|||
|
+static int nios2_disassemble (bfd_vma, unsigned long, disassemble_info *);
|
|||
|
+static void nios2_init_opcode_hash (void);
|
|||
|
+
|
|||
|
+
|
|||
|
+static int nios2_print_insn_arg (const char *argptr, unsigned long opcode,
|
|||
|
+ bfd_vma address, disassemble_info * info);
|
|||
|
+
|
|||
|
+
|
|||
|
+/* print_insn_nios2 is the main disassemble function for New Jersey.
|
|||
|
+ The function diassembler(abfd) (source in disassemble.c) returns a
|
|||
|
+ pointer to this either print_insn_big_nios2 or
|
|||
|
+ print_insn_little_nios2, which in turn call this function, when the
|
|||
|
+ bfd machine type is New Jersey. print_insn_nios2 reads the
|
|||
|
+ instruction word at the address given, and prints the disassembled
|
|||
|
+ instruction on the stream info->stream using info->fprintf_func. */
|
|||
|
+
|
|||
|
+static int
|
|||
|
+print_insn_nios2 (bfd_vma address, disassemble_info * info,
|
|||
|
+ enum bfd_endian endianness)
|
|||
|
+{
|
|||
|
+ /* buffer into which the instruction bytes are written */
|
|||
|
+ bfd_byte buffer[INSNLEN];
|
|||
|
+ /* used to indicate return status from function calls */
|
|||
|
+ int status;
|
|||
|
+
|
|||
|
+ assert (info != NULL);
|
|||
|
+
|
|||
|
+ status = (*info->read_memory_func) (address, buffer, INSNLEN, info);
|
|||
|
+ if (status == 0)
|
|||
|
+ {
|
|||
|
+ unsigned long insn;
|
|||
|
+ if (endianness == BFD_ENDIAN_BIG)
|
|||
|
+ insn = (unsigned long) bfd_getb32 (buffer);
|
|||
|
+ else
|
|||
|
+ insn = (unsigned long) bfd_getl32 (buffer);
|
|||
|
+ status = nios2_disassemble (address, insn, info);
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ (*info->memory_error_func) (status, address, info);
|
|||
|
+ status = -1;
|
|||
|
+ }
|
|||
|
+ return status;
|
|||
|
+}
|
|||
|
+
|
|||
|
+int
|
|||
|
+print_insn_big_nios2 (bfd_vma address, disassemble_info * info)
|
|||
|
+{
|
|||
|
+ return print_insn_nios2 (address, info, BFD_ENDIAN_BIG);
|
|||
|
+}
|
|||
|
+
|
|||
|
+int
|
|||
|
+print_insn_little_nios2 (bfd_vma address, disassemble_info * info)
|
|||
|
+{
|
|||
|
+ return print_insn_nios2 (address, info, BFD_ENDIAN_LITTLE);
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Data structures used by the opcode hash table */
|
|||
|
+
|
|||
|
+typedef struct _nios2_opcode_hash
|
|||
|
+{
|
|||
|
+ const struct nios2_opcode *opcode;
|
|||
|
+ struct _nios2_opcode_hash *next;
|
|||
|
+} nios2_opcode_hash;
|
|||
|
+
|
|||
|
+static bfd_boolean nios2_hash_init = 0;
|
|||
|
+static nios2_opcode_hash *nios2_hash[(OP_MASK_OP) + 1];
|
|||
|
+
|
|||
|
+/* separate hash table for pseudo-ops */
|
|||
|
+static nios2_opcode_hash *nios2_ps_hash[(OP_MASK_OP) + 1];
|
|||
|
+
|
|||
|
+/* Function to initialize the opcode hash table */
|
|||
|
+
|
|||
|
+void
|
|||
|
+nios2_init_opcode_hash ()
|
|||
|
+{
|
|||
|
+ unsigned int i;
|
|||
|
+ register const struct nios2_opcode *op;
|
|||
|
+ nios2_opcode_hash *tmp_hash;
|
|||
|
+
|
|||
|
+ for (i = 0; i <= OP_MASK_OP; ++i)
|
|||
|
+ {
|
|||
|
+ nios2_hash[0] = NULL;
|
|||
|
+ }
|
|||
|
+ for (i = 0; i <= OP_MASK_OP; i++)
|
|||
|
+ {
|
|||
|
+ for (op = nios2_opcodes; op < &nios2_opcodes[NUMOPCODES]; op++)
|
|||
|
+ {
|
|||
|
+ if ((op->pinfo & NIOS2_INSN_MACRO) == NIOS2_INSN_MACRO)
|
|||
|
+ {
|
|||
|
+ if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP) &&
|
|||
|
+ (op->
|
|||
|
+ pinfo & (NIOS2_INSN_MACRO_MOV | NIOS2_INSN_MACRO_MOVI) &
|
|||
|
+ 0x7fffffff) != 0)
|
|||
|
+ {
|
|||
|
+ tmp_hash = nios2_ps_hash[i];
|
|||
|
+ if (tmp_hash == NULL)
|
|||
|
+ {
|
|||
|
+ tmp_hash =
|
|||
|
+ (nios2_opcode_hash *)
|
|||
|
+ malloc (sizeof (nios2_opcode_hash));
|
|||
|
+ nios2_ps_hash[i] = tmp_hash;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ while (tmp_hash->next != NULL)
|
|||
|
+ tmp_hash = tmp_hash->next;
|
|||
|
+ tmp_hash->next =
|
|||
|
+ (nios2_opcode_hash *)
|
|||
|
+ malloc (sizeof (nios2_opcode_hash));
|
|||
|
+ tmp_hash = tmp_hash->next;
|
|||
|
+ }
|
|||
|
+ if (tmp_hash == NULL)
|
|||
|
+ {
|
|||
|
+ fprintf (stderr,
|
|||
|
+ "error allocating memory...broken disassembler\n");
|
|||
|
+ abort ();
|
|||
|
+ }
|
|||
|
+ tmp_hash->opcode = op;
|
|||
|
+ tmp_hash->next = NULL;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
|
|||
|
+ {
|
|||
|
+ tmp_hash = nios2_hash[i];
|
|||
|
+ if (tmp_hash == NULL)
|
|||
|
+ {
|
|||
|
+ tmp_hash =
|
|||
|
+ (nios2_opcode_hash *) malloc (sizeof (nios2_opcode_hash));
|
|||
|
+ nios2_hash[i] = tmp_hash;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ while (tmp_hash->next != NULL)
|
|||
|
+ tmp_hash = tmp_hash->next;
|
|||
|
+ tmp_hash->next =
|
|||
|
+ (nios2_opcode_hash *) malloc (sizeof (nios2_opcode_hash));
|
|||
|
+ tmp_hash = tmp_hash->next;
|
|||
|
+ }
|
|||
|
+ if (tmp_hash == NULL)
|
|||
|
+ {
|
|||
|
+ fprintf (stderr,
|
|||
|
+ "error allocating memory...broken disassembler\n");
|
|||
|
+ abort ();
|
|||
|
+ }
|
|||
|
+ tmp_hash->opcode = op;
|
|||
|
+ tmp_hash->next = NULL;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ nios2_hash_init = 1;
|
|||
|
+#ifdef DEBUG_HASHTABLE
|
|||
|
+ for (i = 0; i <= OP_MASK_OP; ++i)
|
|||
|
+ {
|
|||
|
+ printf ("index: 0x%02X ops: ", i);
|
|||
|
+ tmp_hash = nios2_hash[i];
|
|||
|
+ if (tmp_hash != NULL)
|
|||
|
+ {
|
|||
|
+ while (tmp_hash != NULL)
|
|||
|
+ {
|
|||
|
+ printf ("%s ", tmp_hash->opcode->name);
|
|||
|
+ tmp_hash = tmp_hash->next;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ printf ("\n");
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ for (i = 0; i <= OP_MASK_OP; ++i)
|
|||
|
+ {
|
|||
|
+ printf ("index: 0x%02X ops: ", i);
|
|||
|
+ tmp_hash = nios2_ps_hash[i];
|
|||
|
+ if (tmp_hash != NULL)
|
|||
|
+ {
|
|||
|
+ while (tmp_hash != NULL)
|
|||
|
+ {
|
|||
|
+ printf ("%s ", tmp_hash->opcode->name);
|
|||
|
+ tmp_hash = tmp_hash->next;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ printf ("\n");
|
|||
|
+ }
|
|||
|
+#endif
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* Function which returns a pointer to an nios2_opcode struct for
|
|||
|
+ a given instruction opcode, or NULL if there is an error */
|
|||
|
+
|
|||
|
+const struct nios2_opcode *
|
|||
|
+nios2_find_opcode_hash (unsigned long opcode)
|
|||
|
+{
|
|||
|
+ nios2_opcode_hash *entry;
|
|||
|
+
|
|||
|
+ /* Build a hash table to shorten the search time. */
|
|||
|
+ if (!nios2_hash_init)
|
|||
|
+ {
|
|||
|
+ nios2_init_opcode_hash ();
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* first look in the pseudo-op hashtable */
|
|||
|
+ entry = nios2_ps_hash[(opcode >> OP_SH_OP) & OP_MASK_OP];
|
|||
|
+
|
|||
|
+ /* look for a match and if we get one, this is the instruction we decode */
|
|||
|
+ while (entry != NULL)
|
|||
|
+ {
|
|||
|
+ if ((entry->opcode->match) == (opcode & entry->opcode->mask))
|
|||
|
+ return entry->opcode;
|
|||
|
+ else
|
|||
|
+ entry = entry->next;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* if we haven't yet returned, then we need to look in the main
|
|||
|
+ hashtable */
|
|||
|
+ entry = nios2_hash[(opcode >> OP_SH_OP) & OP_MASK_OP];
|
|||
|
+
|
|||
|
+ if (entry == NULL)
|
|||
|
+ return NULL;
|
|||
|
+
|
|||
|
+
|
|||
|
+ while (entry != NULL)
|
|||
|
+ {
|
|||
|
+ if ((entry->opcode->match) == (opcode & entry->opcode->mask))
|
|||
|
+ return entry->opcode;
|
|||
|
+ else
|
|||
|
+ entry = entry->next;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return NULL;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* nios2_disassemble does all the work of disassembling a New Jersey
|
|||
|
+ instruction opcode */
|
|||
|
+
|
|||
|
+int
|
|||
|
+nios2_disassemble (bfd_vma address, unsigned long opcode,
|
|||
|
+ disassemble_info * info)
|
|||
|
+{
|
|||
|
+ const struct nios2_opcode *op;
|
|||
|
+ const char *argstr;
|
|||
|
+
|
|||
|
+ info->bytes_per_line = INSNLEN;
|
|||
|
+ info->bytes_per_chunk = INSNLEN;
|
|||
|
+ info->display_endian = info->endian;
|
|||
|
+ info->insn_info_valid = 1;
|
|||
|
+ info->branch_delay_insns = 0;
|
|||
|
+ info->data_size = 0;
|
|||
|
+ info->insn_type = dis_nonbranch;
|
|||
|
+ info->target = 0;
|
|||
|
+ info->target2 = 0;
|
|||
|
+
|
|||
|
+ /* Find the major opcode and use this to disassemble
|
|||
|
+ the instruction and its arguments */
|
|||
|
+ op = nios2_find_opcode_hash (opcode);
|
|||
|
+
|
|||
|
+ if (op != NULL)
|
|||
|
+ {
|
|||
|
+ bfd_boolean is_nop = FALSE;
|
|||
|
+ if (op->pinfo == NIOS2_INSN_MACRO_MOV)
|
|||
|
+ {
|
|||
|
+ /* check for mov r0, r0 and if it is
|
|||
|
+ change to nop */
|
|||
|
+ int dst, src;
|
|||
|
+ dst = GET_INSN_FIELD (RRD, opcode);
|
|||
|
+ src = GET_INSN_FIELD (RRS, opcode);
|
|||
|
+ if (dst == 0 && src == 0)
|
|||
|
+ {
|
|||
|
+ (*info->fprintf_func) (info->stream, "nop");
|
|||
|
+ is_nop = TRUE;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ (*info->fprintf_func) (info->stream, "%s", op->name);
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ (*info->fprintf_func) (info->stream, "%s", op->name);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (!is_nop)
|
|||
|
+ {
|
|||
|
+ argstr = op->args;
|
|||
|
+ if (argstr != NULL && *argstr != '\0')
|
|||
|
+ {
|
|||
|
+ (*info->fprintf_func) (info->stream, "\t");
|
|||
|
+ while (*argstr != '\0')
|
|||
|
+ {
|
|||
|
+ nios2_print_insn_arg (argstr, opcode, address, info);
|
|||
|
+ ++argstr;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ /* Handle undefined instructions. */
|
|||
|
+ info->insn_type = dis_noninsn;
|
|||
|
+ (*info->fprintf_func) (info->stream, "0x%x", (unsigned int) opcode);
|
|||
|
+ }
|
|||
|
+ // this tells the caller how far to advance the program counter
|
|||
|
+ return INSNLEN;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/* The function nios2_print_insn_arg uses the character pointed
|
|||
|
+ to by argptr to determine how it print the next token or separator
|
|||
|
+ character in the arguments to an instruction */
|
|||
|
+int
|
|||
|
+nios2_print_insn_arg (const char *argptr,
|
|||
|
+ unsigned long opcode, bfd_vma address,
|
|||
|
+ disassemble_info * info)
|
|||
|
+{
|
|||
|
+ unsigned long i = 0;
|
|||
|
+ unsigned long reg_base;
|
|||
|
+
|
|||
|
+ assert (argptr != NULL);
|
|||
|
+ assert (info != NULL);
|
|||
|
+
|
|||
|
+ switch (*argptr)
|
|||
|
+ {
|
|||
|
+ case ',':
|
|||
|
+ case '(':
|
|||
|
+ case ')':
|
|||
|
+ (*info->fprintf_func) (info->stream, "%c", *argptr);
|
|||
|
+ break;
|
|||
|
+ case 'd':
|
|||
|
+ i = GET_INSN_FIELD (RRD, opcode);
|
|||
|
+
|
|||
|
+ if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM
|
|||
|
+ && GET_INSN_FIELD (CUSTOM_C, opcode) == 0)
|
|||
|
+ reg_base = COPROCREGBASE;
|
|||
|
+ else
|
|||
|
+ reg_base = 0;
|
|||
|
+
|
|||
|
+ if (i < NUMREGNAMES)
|
|||
|
+ (*info->fprintf_func) (info->stream, "%s",
|
|||
|
+ nios2_regs[i + reg_base].name);
|
|||
|
+ else
|
|||
|
+ (*info->fprintf_func) (info->stream, "unknown");
|
|||
|
+ break;
|
|||
|
+ case 's':
|
|||
|
+ i = GET_INSN_FIELD (RRS, opcode);
|
|||
|
+
|
|||
|
+ if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM
|
|||
|
+ && GET_INSN_FIELD (CUSTOM_A, opcode) == 0)
|
|||
|
+ reg_base = COPROCREGBASE;
|
|||
|
+ else
|
|||
|
+ reg_base = 0;
|
|||
|
+
|
|||
|
+ if (i < NUMREGNAMES)
|
|||
|
+ (*info->fprintf_func) (info->stream, "%s",
|
|||
|
+ nios2_regs[i + reg_base].name);
|
|||
|
+ else
|
|||
|
+ (*info->fprintf_func) (info->stream, "unknown");
|
|||
|
+ break;
|
|||
|
+ case 't':
|
|||
|
+ i = GET_INSN_FIELD (RRT, opcode);
|
|||
|
+
|
|||
|
+ if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM
|
|||
|
+ && GET_INSN_FIELD (CUSTOM_B, opcode) == 0)
|
|||
|
+ reg_base = COPROCREGBASE;
|
|||
|
+ else
|
|||
|
+ reg_base = 0;
|
|||
|
+
|
|||
|
+ if (i < NUMREGNAMES)
|
|||
|
+ (*info->fprintf_func) (info->stream, "%s",
|
|||
|
+ nios2_regs[i + reg_base].name);
|
|||
|
+ else
|
|||
|
+ (*info->fprintf_func) (info->stream, "unknown");
|
|||
|
+ break;
|
|||
|
+ case 'i':
|
|||
|
+ /* 16-bit signed immediate */
|
|||
|
+ i = (signed) (GET_INSN_FIELD (IMM16, opcode) << 16) >> 16;
|
|||
|
+ (*info->fprintf_func) (info->stream, "%d", (int) i);
|
|||
|
+ break;
|
|||
|
+ case 'u':
|
|||
|
+ /* 16-bit unsigned immediate */
|
|||
|
+ i = GET_INSN_FIELD (IMM16, opcode);
|
|||
|
+ (*info->fprintf_func) (info->stream, "%d", (int) i);
|
|||
|
+ break;
|
|||
|
+ case 'o':
|
|||
|
+ /* 16-bit signed immediate address offset */
|
|||
|
+ i = (signed) (GET_INSN_FIELD (IMM16, opcode) << 16) >> 16;
|
|||
|
+ address = address + 4 + i; /* NG changed to byte offset 1/9/03 */
|
|||
|
+ (*info->print_address_func) (address, info);
|
|||
|
+ break;
|
|||
|
+ case 'p':
|
|||
|
+ /* 5-bit unsigned immediate */
|
|||
|
+ i = GET_INSN_FIELD (CACHE_OPX, opcode);
|
|||
|
+ (*info->fprintf_func) (info->stream, "%d", (int) i);
|
|||
|
+ break;
|
|||
|
+ case 'j':
|
|||
|
+ /* 5-bit unsigned immediate */
|
|||
|
+ i = GET_INSN_FIELD (IMM5, opcode);
|
|||
|
+ (*info->fprintf_func) (info->stream, "%d", (int) i);
|
|||
|
+ break;
|
|||
|
+ case 'l':
|
|||
|
+ /* 8-bit unsigned immediate */
|
|||
|
+ /* FIXME - not yet implemented */
|
|||
|
+ i = GET_INSN_FIELD (CUSTOM_N, opcode);
|
|||
|
+ (*info->fprintf_func) (info->stream, "%u", (int) i);
|
|||
|
+ break;
|
|||
|
+ case 'm':
|
|||
|
+ /* 26-bit unsigned immediate */
|
|||
|
+ i = GET_INSN_FIELD (IMM26, opcode);
|
|||
|
+ /* this translates to an address because its only used in call instructions */
|
|||
|
+ address = (address & 0xf0000000) | (i << 2);
|
|||
|
+ (*info->print_address_func) (address, info);
|
|||
|
+ break;
|
|||
|
+ case 'c':
|
|||
|
+ i = GET_INSN_FIELD (IMM5, opcode); /* ctrl register index */
|
|||
|
+ (*info->fprintf_func) (info->stream, "%s",
|
|||
|
+ nios2_regs[CTLREGBASE + i].name);
|
|||
|
+ break;
|
|||
|
+ case 'b':
|
|||
|
+ i = GET_INSN_FIELD (IMM5, opcode);
|
|||
|
+ (*info->fprintf_func) (info->stream, "%d", (int) i);
|
|||
|
+ break;
|
|||
|
+ default:
|
|||
|
+ (*info->fprintf_func) (info->stream, "unknown");
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
diff --git a/opcodes/nios2-opc.c b/opcodes/nios2-opc.c
|
|||
|
new file mode 100644
|
|||
|
index 0000000..c860207
|
|||
|
--- /dev/null
|
|||
|
+++ b/opcodes/nios2-opc.c
|
|||
|
@@ -0,0 +1,320 @@
|
|||
|
+/* nios2-opc.c -- Altera New Jersey opcode list.
|
|||
|
+
|
|||
|
+ Copyright (C) 2003
|
|||
|
+ by Nigel Gray (ngray@altera.com).
|
|||
|
+
|
|||
|
+This file is part of GDB, GAS, and the GNU binutils.
|
|||
|
+
|
|||
|
+GDB, GAS, and the GNU binutils are free software; you can redistribute
|
|||
|
+them and/or modify them under the terms of the GNU General Public
|
|||
|
+License as published by the Free Software Foundation; either version
|
|||
|
+1, or (at your option) any later version.
|
|||
|
+
|
|||
|
+GDB, GAS, and the GNU binutils are distributed in the hope that they
|
|||
|
+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 a copy of the GNU General Public License
|
|||
|
+along with this file; see the file COPYING. If not, write to the Free
|
|||
|
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
+
|
|||
|
+#include <stdio.h>
|
|||
|
+#include "opcode/nios2.h"
|
|||
|
+
|
|||
|
+/* Register string table */
|
|||
|
+
|
|||
|
+const struct nios2_reg nios2_builtin_regs[] = {
|
|||
|
+ {"zero", 0},
|
|||
|
+ {"at", 1}, // assembler temporary
|
|||
|
+ {"r2", 2},
|
|||
|
+ {"r3", 3},
|
|||
|
+ {"r4", 4},
|
|||
|
+ {"r5", 5},
|
|||
|
+ {"r6", 6},
|
|||
|
+ {"r7", 7},
|
|||
|
+ {"r8", 8},
|
|||
|
+ {"r9", 9},
|
|||
|
+ {"r10", 10},
|
|||
|
+ {"r11", 11},
|
|||
|
+ {"r12", 12},
|
|||
|
+ {"r13", 13},
|
|||
|
+ {"r14", 14},
|
|||
|
+ {"r15", 15},
|
|||
|
+ {"r16", 16},
|
|||
|
+ {"r17", 17},
|
|||
|
+ {"r18", 18},
|
|||
|
+ {"r19", 19},
|
|||
|
+ {"r20", 20},
|
|||
|
+ {"r21", 21},
|
|||
|
+ {"r22", 22},
|
|||
|
+ {"r23", 23},
|
|||
|
+ {"et", 24},
|
|||
|
+ {"bt", 25},
|
|||
|
+ {"gp", 26}, /* global pointer */
|
|||
|
+ {"sp", 27}, /* stack pointer */
|
|||
|
+ {"fp", 28}, /* frame pointer */
|
|||
|
+ {"ea", 29}, /* exception return address */
|
|||
|
+ {"ba", 30}, /* breakpoint return address */
|
|||
|
+ {"ra", 31}, /* return address */
|
|||
|
+
|
|||
|
+ /* alternative names for special registers */
|
|||
|
+ {"r0", 0},
|
|||
|
+ {"r1", 1},
|
|||
|
+ {"r24", 24},
|
|||
|
+ {"r25", 25},
|
|||
|
+ {"r26", 26},
|
|||
|
+ {"r27", 27},
|
|||
|
+ {"r28", 28},
|
|||
|
+ {"r29", 29},
|
|||
|
+ {"r30", 30},
|
|||
|
+ {"r31", 31},
|
|||
|
+
|
|||
|
+ /* control register names */
|
|||
|
+ {"status", 0},
|
|||
|
+ {"estatus", 1},
|
|||
|
+ {"bstatus", 2},
|
|||
|
+ {"ienable", 3},
|
|||
|
+ {"ipending", 4},
|
|||
|
+ {"cpuid", 5},
|
|||
|
+ {"ctl6", 6},
|
|||
|
+ {"ctl7", 7},
|
|||
|
+ {"pteaddr", 8},
|
|||
|
+ {"tlbacc", 9},
|
|||
|
+ {"tlbmisc", 10},
|
|||
|
+ {"fstatus", 11},
|
|||
|
+ {"ctl12", 12},
|
|||
|
+ {"ctl13", 13},
|
|||
|
+ {"ctl14", 14},
|
|||
|
+ {"ctl15", 15},
|
|||
|
+ {"ctl16", 16},
|
|||
|
+ {"ctl17", 17},
|
|||
|
+ {"ctl18", 18},
|
|||
|
+ {"ctl19", 19},
|
|||
|
+ {"ctl20", 20},
|
|||
|
+ {"ctl21", 21},
|
|||
|
+ {"ctl22", 22},
|
|||
|
+ {"ctl23", 23},
|
|||
|
+ {"ctl24", 24},
|
|||
|
+ {"ctl25", 25},
|
|||
|
+ {"ctl26", 26},
|
|||
|
+ {"ctl27", 27},
|
|||
|
+ {"ctl28", 28},
|
|||
|
+ {"ctl29", 29},
|
|||
|
+ {"ctl30", 30},
|
|||
|
+ {"ctl31", 31},
|
|||
|
+
|
|||
|
+ /* alternative names for special control registers */
|
|||
|
+ {"ctl0", 0},
|
|||
|
+ {"ctl1", 1},
|
|||
|
+ {"ctl2", 2},
|
|||
|
+ {"ctl3", 3},
|
|||
|
+ {"ctl4", 4},
|
|||
|
+ {"ctl5", 5},
|
|||
|
+ {"ctl8", 8},
|
|||
|
+ {"ctl9", 9},
|
|||
|
+ {"ctl10", 10},
|
|||
|
+ {"ctl11", 11},
|
|||
|
+
|
|||
|
+ /* coprocessor register names */
|
|||
|
+ {"c0", 0},
|
|||
|
+ {"c1", 1},
|
|||
|
+ {"c2", 2},
|
|||
|
+ {"c3", 3},
|
|||
|
+ {"c4", 4},
|
|||
|
+ {"c5", 5},
|
|||
|
+ {"c6", 6},
|
|||
|
+ {"c7", 7},
|
|||
|
+ {"c8", 8},
|
|||
|
+ {"c9", 9},
|
|||
|
+ {"c10", 10},
|
|||
|
+ {"c11", 11},
|
|||
|
+ {"c12", 12},
|
|||
|
+ {"c13", 13},
|
|||
|
+ {"c14", 14},
|
|||
|
+ {"c15", 15},
|
|||
|
+ {"c16", 16},
|
|||
|
+ {"c17", 17},
|
|||
|
+ {"c18", 18},
|
|||
|
+ {"c19", 19},
|
|||
|
+ {"c20", 20},
|
|||
|
+ {"c21", 21},
|
|||
|
+ {"c22", 22},
|
|||
|
+ {"c23", 23},
|
|||
|
+ {"c24", 24},
|
|||
|
+ {"c25", 25},
|
|||
|
+ {"c26", 26},
|
|||
|
+ {"c27", 27},
|
|||
|
+ {"c28", 28},
|
|||
|
+ {"c29", 29},
|
|||
|
+ {"c30", 30},
|
|||
|
+ {"c31", 31},
|
|||
|
+};
|
|||
|
+
|
|||
|
+#define NIOS2_NUM_REGS \
|
|||
|
+ ((sizeof nios2_builtin_regs) / (sizeof (nios2_builtin_regs[0])))
|
|||
|
+const int nios2_num_builtin_regs = NIOS2_NUM_REGS;
|
|||
|
+
|
|||
|
+/* const removed from the following to allow for dynamic extensions to the
|
|||
|
+ * built-in instruction set. */
|
|||
|
+struct nios2_reg *nios2_regs = (struct nios2_reg *) nios2_builtin_regs;
|
|||
|
+int nios2_num_regs = NIOS2_NUM_REGS;
|
|||
|
+#undef NIOS2_NUM_REGS
|
|||
|
+
|
|||
|
+/* overflow message string templates */
|
|||
|
+
|
|||
|
+char *overflow_msgs[] = {
|
|||
|
+ "call target address 0x%08x out of range 0x%08x to 0x%08x",
|
|||
|
+ "branch offset %d out of range %d to %d",
|
|||
|
+ "%s offset %d out of range %d to %d",
|
|||
|
+ "immediate value %d out of range %d to %d",
|
|||
|
+ "immediate value %u out of range %u to %u",
|
|||
|
+ "immediate value %u out of range %u to %u",
|
|||
|
+ "custom instruction opcode %u out of range %u to %u",
|
|||
|
+};
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+/*--------------------------------------------------------------------------------
|
|||
|
+ This is the opcode table used by the New Jersey GNU as, disassembler and GDB
|
|||
|
+ --------------------------------------------------------------------------------*/
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ The following letters can appear in the args field of the nios2_opcode
|
|||
|
+ structure:
|
|||
|
+
|
|||
|
+ c - a 5-bit control register index or break opcode
|
|||
|
+ d - a 5-bit destination register index
|
|||
|
+ s - a 5-bit left source register index
|
|||
|
+ t - a 5-bit right source register index
|
|||
|
+ i - a 16-bit signed immediate
|
|||
|
+ u - a 16-bit unsigned immediate
|
|||
|
+
|
|||
|
+ j - a 5-bit unsigned immediate
|
|||
|
+ k - a 6-bit unsigned immediate
|
|||
|
+ l - an 8-bit unsigned immediate
|
|||
|
+ m - a 26-bit unsigned immediate
|
|||
|
+*/
|
|||
|
+
|
|||
|
+/* *INDENT-OFF* */
|
|||
|
+/* FIXME: Re-format for GNU standards */
|
|||
|
+const struct nios2_opcode nios2_builtin_opcodes[] =
|
|||
|
+{
|
|||
|
+ /* name, args, args_test num_args, match, mask, pinfo */
|
|||
|
+ {"add", "d,s,t", "d,s,t,E", 3, OP_MATCH_ADD, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"addi", "t,s,i", "t,s,i,E", 3, OP_MATCH_ADDI, OP_MASK_IOP, NIOS2_INSN_ADDI, signed_immed16_overflow },
|
|||
|
+ {"subi", "t,s,i", "t,s,i,E", 3, OP_MATCH_ADDI, OP_MASK_IOP, NIOS2_INSN_MACRO, signed_immed16_overflow },
|
|||
|
+ {"and", "d,s,t", "d,s,t,E", 3, OP_MATCH_AND, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"andhi", "t,s,u", "t,s,u,E", 3, OP_MATCH_ANDHI, OP_MASK_IOP, 0, unsigned_immed16_overflow },
|
|||
|
+ {"andi", "t,s,u", "t,s,u,E", 3, OP_MATCH_ANDI, OP_MASK_IOP, NIOS2_INSN_ANDI, unsigned_immed16_overflow },
|
|||
|
+ {"beq", "s,t,o", "s,t,o,E", 3, OP_MATCH_BEQ, OP_MASK_IOP, NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"bge", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGE, OP_MASK_IOP, NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"bgeu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGEU, OP_MASK_IOP, NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"bgt", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLT, OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"bgtu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLTU, OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"ble", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGE, OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"bleu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BGEU, OP_MASK_IOP, NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"blt", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLT, OP_MASK_IOP, NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"bltu", "s,t,o", "s,t,o,E", 3, OP_MATCH_BLTU, OP_MASK_IOP, NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"bne", "s,t,o", "s,t,o,E", 3, OP_MATCH_BNE, OP_MASK_IOP, NIOS2_INSN_CBRANCH, branch_target_overflow },
|
|||
|
+ {"br", "o", "o,E", 1, OP_MATCH_BR, OP_MASK_IOP, NIOS2_INSN_UBRANCH, branch_target_overflow },
|
|||
|
+ {"break", "b", "b,E", 1, OP_MATCH_BREAK, OP_MASK_BREAK, 0, no_overflow },
|
|||
|
+ {"bret", "", "E", 0, OP_MATCH_BRET, OP_MASK, 0, no_overflow },
|
|||
|
+ {"flushd", "i(s)", "i(s)E", 2, OP_MATCH_FLUSHD, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"flushda", "i(s)", "i(s)E", 2, OP_MATCH_FLUSHDA, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"flushi", "s", "s,E", 1, OP_MATCH_FLUSHI, OP_MASK_FLUSHI, 0, no_overflow },
|
|||
|
+ {"flushp", "", "E", 0, OP_MATCH_FLUSHP, OP_MASK, 0, no_overflow },
|
|||
|
+ {"initd", "i(s)", "i(s)E", 2, OP_MATCH_INITD, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"initi", "s", "s,E", 1, OP_MATCH_INITI, OP_MASK_INITI, 0, no_overflow },
|
|||
|
+ {"call", "m", "m,E", 1, OP_MATCH_CALL, OP_MASK_IOP, NIOS2_INSN_CALL, call_target_overflow },
|
|||
|
+ {"callr", "s", "s,E", 1, OP_MATCH_CALLR, OP_MASK_CALLR, 0, no_overflow },
|
|||
|
+ {"cmpeq", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPEQ, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"cmpeqi", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPEQI, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"cmpge", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGE, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"cmpgei", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPGEI, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"cmpgeu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGEU, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"cmpgeui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPGEUI, OP_MASK_IOP, 0, unsigned_immed16_overflow },
|
|||
|
+ {"cmpgt", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLT, OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO, no_overflow },
|
|||
|
+ {"cmpgti", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPGEI, OP_MASK_IOP, NIOS2_INSN_MACRO, signed_immed16_overflow },
|
|||
|
+ {"cmpgtu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLTU, OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO, no_overflow },
|
|||
|
+ {"cmpgtui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPGEUI, OP_MASK_IOP, NIOS2_INSN_MACRO, unsigned_immed16_overflow },
|
|||
|
+ {"cmple", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGE, OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO, no_overflow },
|
|||
|
+ {"cmplei", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPLTI, OP_MASK_IOP, NIOS2_INSN_MACRO, signed_immed16_overflow },
|
|||
|
+ {"cmpleu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPGEU, OP_MASK_ROPX | OP_MASK_ROP, NIOS2_INSN_MACRO, no_overflow },
|
|||
|
+ {"cmpleui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPLTUI, OP_MASK_IOP, NIOS2_INSN_MACRO, unsigned_immed16_overflow },
|
|||
|
+ {"cmplt", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLT, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"cmplti", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPLTI, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"cmpltu", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPLTU, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"cmpltui", "t,s,u", "t,s,u,E", 3, OP_MATCH_CMPLTUI, OP_MASK_IOP, 0, unsigned_immed16_overflow },
|
|||
|
+ {"cmpne", "d,s,t", "d,s,t,E", 3, OP_MATCH_CMPNE, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"cmpnei", "t,s,i", "t,s,i,E", 3, OP_MATCH_CMPNEI, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"div", "d,s,t", "d,s,t,E", 3, OP_MATCH_DIV, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"divu", "d,s,t", "d,s,t,E", 3, OP_MATCH_DIVU, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"jmp", "s", "s,E", 1, OP_MATCH_JMP, OP_MASK_JMP, 0, no_overflow },
|
|||
|
+ {"jmpi", "m", "m,E", 1, OP_MATCH_JMPI, OP_MASK_IOP, 0, no_overflow },
|
|||
|
+ {"ldb", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDB, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldbio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDBIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldbu", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDBU, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldbuio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDBUIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldh", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDH, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldhio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDHIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldhu", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDHU, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldhuio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDHUIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldw", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDW, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"ldwio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_LDWIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"mov", "d,s", "d,s,E", 2, OP_MATCH_ADD, OP_MASK_RRT|OP_MASK_ROPX|OP_MASK_ROP, NIOS2_INSN_MACRO_MOV, no_overflow },
|
|||
|
+ {"movhi", "t,u", "t,u,E", 2, OP_MATCH_ORHI, OP_MASK_IRS|OP_MASK_IOP, NIOS2_INSN_MACRO_MOVI, unsigned_immed16_overflow },
|
|||
|
+ {"movui", "t,u", "t,u,E", 2, OP_MATCH_ORI, OP_MASK_IRS|OP_MASK_IOP, NIOS2_INSN_MACRO_MOVI, unsigned_immed16_overflow },
|
|||
|
+ {"movi", "t,i", "t,i,E", 2, OP_MATCH_ADDI, OP_MASK_IRS|OP_MASK_IOP, NIOS2_INSN_MACRO_MOVI, signed_immed16_overflow },
|
|||
|
+ /* movia expands to two instructions so there is no mask or match */
|
|||
|
+ {"movia", "t,o", "t,o,E", 2, OP_MATCH_ORHI, OP_MASK_IOP, NIOS2_INSN_MACRO_MOVIA, no_overflow },
|
|||
|
+ {"mul", "d,s,t", "d,s,t,E", 3, OP_MATCH_MUL, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"muli", "t,s,i", "t,s,i,E", 3, OP_MATCH_MULI, OP_MASK_IOP, 0, signed_immed16_overflow },
|
|||
|
+ {"mulxss", "d,s,t", "d,s,t,E", 3, OP_MATCH_MULXSS, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"mulxsu", "d,s,t", "d,s,t,E", 3, OP_MATCH_MULXSU, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"mulxuu", "d,s,t", "d,s,t,E", 3, OP_MATCH_MULXUU, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"nextpc", "d", "d,E", 1, OP_MATCH_NEXTPC, OP_MASK_NEXTPC, 0, no_overflow },
|
|||
|
+ {"nop", "", "E", 0, OP_MATCH_ADD, OP_MASK, NIOS2_INSN_MACRO_MOV, no_overflow },
|
|||
|
+ {"nor", "d,s,t", "d,s,t,E", 3, OP_MATCH_NOR, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"or", "d,s,t", "d,s,t,E", 3, OP_MATCH_OR, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"orhi", "t,s,u", "t,s,u,E", 3, OP_MATCH_ORHI, OP_MASK_IOP, 0, unsigned_immed16_overflow },
|
|||
|
+ {"ori", "t,s,u", "t,s,u,E", 3, OP_MATCH_ORI, OP_MASK_IOP, NIOS2_INSN_ORI, unsigned_immed16_overflow },
|
|||
|
+ {"rdctl", "d,c", "d,c,E", 2, OP_MATCH_RDCTL, OP_MASK_RDCTL, 0, no_overflow },
|
|||
|
+ {"ret", "", "E", 0, OP_MATCH_RET, OP_MASK, 0, no_overflow },
|
|||
|
+ {"rol", "d,s,t", "d,s,t,E", 3, OP_MATCH_ROL, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"roli", "d,s,j", "d,s,j,E", 3, OP_MATCH_ROLI, OP_MASK_ROLI, 0, unsigned_immed5_overflow },
|
|||
|
+ {"ror", "d,s,t", "d,s,t,E", 3, OP_MATCH_ROR, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"sll", "d,s,t", "d,s,t,E", 3, OP_MATCH_SLL, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"slli", "d,s,j", "d,s,j,E", 3, OP_MATCH_SLLI, OP_MASK_SLLI, 0, unsigned_immed5_overflow },
|
|||
|
+ {"sra", "d,s,t", "d,s,t,E", 3, OP_MATCH_SRA, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"srai", "d,s,j", "d,s,j,E", 3, OP_MATCH_SRAI, OP_MASK_SRAI, 0, unsigned_immed5_overflow },
|
|||
|
+ {"srl", "d,s,t", "d,s,t,E", 3, OP_MATCH_SRL, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"srli", "d,s,j", "d,s,j,E", 3, OP_MATCH_SRLI, OP_MASK_SRLI, 0, unsigned_immed5_overflow },
|
|||
|
+ {"stb", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STB, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"stbio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STBIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"sth", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STH, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"sthio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STHIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"stw", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STW, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"stwio", "t,i(s)", "t,i(s)E", 3, OP_MATCH_STWIO, OP_MASK_IOP, 0, address_offset_overflow },
|
|||
|
+ {"sub", "d,s,t", "d,s,t,E", 3, OP_MATCH_SUB, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"sync", "", "E", 0, OP_MATCH_SYNC, OP_MASK_SYNC, 0, no_overflow },
|
|||
|
+ {"trap", "", "E", 0, OP_MATCH_TRAP, OP_MASK_TRAP, 0, no_overflow },
|
|||
|
+ {"eret", "", "E", 0, OP_MATCH_ERET, OP_MASK, 0, no_overflow },
|
|||
|
+ {"custom", "l,d,s,t", "l,d,s,t,E", 4, OP_MATCH_CUSTOM, OP_MASK_ROP, 0, custom_opcode_overflow },
|
|||
|
+ {"wrctl", "c,s", "c,s,E", 2, OP_MATCH_WRCTL, OP_MASK_WRCTL, 0, no_overflow },
|
|||
|
+ {"xor", "d,s,t", "d,s,t,E", 3, OP_MATCH_XOR, OP_MASK_ROPX | OP_MASK_ROP, 0, no_overflow },
|
|||
|
+ {"xorhi", "t,s,u", "t,s,u,E", 3, OP_MATCH_XORHI, OP_MASK_IOP, 0, unsigned_immed16_overflow },
|
|||
|
+ {"xori", "t,s,u", "t,s,u,E", 3, OP_MATCH_XORI, OP_MASK_IOP, NIOS2_INSN_XORI, unsigned_immed16_overflow }
|
|||
|
+};
|
|||
|
+/* *INDENT-ON* */
|
|||
|
+
|
|||
|
+#define NIOS2_NUM_OPCODES \
|
|||
|
+ ((sizeof nios2_builtin_opcodes) / (sizeof (nios2_builtin_opcodes[0])))
|
|||
|
+const int bfd_nios2_num_builtin_opcodes = NIOS2_NUM_OPCODES;
|
|||
|
+
|
|||
|
+/* const removed from the following to allow for dynamic extensions to the
|
|||
|
+ * built-in instruction set. */
|
|||
|
+struct nios2_opcode *nios2_opcodes =
|
|||
|
+ (struct nios2_opcode *) nios2_builtin_opcodes;
|
|||
|
+int bfd_nios2_num_opcodes = NIOS2_NUM_OPCODES;
|
|||
|
+#undef NIOS2_NUM_OPCODES
|