summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaydeep Patil <jaydeep.patil@imgtec.com>2016-05-23 19:00:26 +0200
committerNikola Veljkovic <Nikola.Veljkovic@imgtec.com>2016-07-01 21:22:26 +0000
commitb66267cc5491513a9ad0369761a1c1b52bf15fed (patch)
tree413a9168d9d9c97f7bfffde4d1084b7a6ea71075
parent3bf3cd4d142637442a412ee7ead383fc65742ed1 (diff)
downloadgdb-b66267cc5491513a9ad0369761a1c1b52bf15fed.tar.gz
[mips] Add support for mips r6, microMIPS r6 and MSAndk-r13-beta2ndk-r13ndk-r13-release
Verified for all mips archs (mips32, mips32r6. mips64r6). Patch is a rebased version of: https://android-review.googlesource.com/153821 Change-Id: I60f576cc44571afd0000ddec4716e1fb0d02d660
-rw-r--r--gdb-7.11/bfd/archures.c1
-rw-r--r--gdb-7.11/bfd/bfd-in2.h1
-rw-r--r--gdb-7.11/bfd/cpu-mips.c3
-rw-r--r--gdb-7.11/gdb/common/signals.c10
-rw-r--r--gdb-7.11/gdb/features/Makefile11
-rw-r--r--gdb-7.11/gdb/features/mips-cp0.xml1
-rw-r--r--gdb-7.11/gdb/features/mips-dsp-linux.c85
-rw-r--r--gdb-7.11/gdb/features/mips-dsp.xml14
-rw-r--r--gdb-7.11/gdb/features/mips-fpu.xml2
-rw-r--r--gdb-7.11/gdb/features/mips-fpu128.xml47
-rw-r--r--gdb-7.11/gdb/features/mips-fpu64-dsp-linux.c111
-rw-r--r--gdb-7.11/gdb/features/mips-fpu64-dsp-linux.xml20
-rw-r--r--gdb-7.11/gdb/features/mips-fpu64-linux.c102
-rw-r--r--gdb-7.11/gdb/features/mips-fpu64-linux.xml19
-rw-r--r--gdb-7.11/gdb/features/mips-fpu64.xml45
-rw-r--r--gdb-7.11/gdb/features/mips-linux.c71
-rw-r--r--gdb-7.11/gdb/features/mips-msa-linux.c110
-rw-r--r--gdb-7.11/gdb/features/mips-msa-linux.xml26
-rw-r--r--gdb-7.11/gdb/features/mips-msa.xml12
-rw-r--r--gdb-7.11/gdb/features/mips64-cp0.xml1
-rw-r--r--gdb-7.11/gdb/features/mips64-dsp-linux.c85
-rw-r--r--gdb-7.11/gdb/features/mips64-dsp.xml14
-rw-r--r--gdb-7.11/gdb/features/mips64-fpu.xml2
-rw-r--r--gdb-7.11/gdb/features/mips64-fpu128.xml47
-rw-r--r--gdb-7.11/gdb/features/mips64-linux.c71
-rw-r--r--gdb-7.11/gdb/features/mips64-msa-linux.c108
-rw-r--r--gdb-7.11/gdb/features/mips64-msa-linux.xml24
-rw-r--r--gdb-7.11/gdb/features/mips64-msa.xml12
-rw-r--r--gdb-7.11/gdb/gdbarch.c32
-rw-r--r--gdb-7.11/gdb/gdbarch.h13
-rwxr-xr-xgdb-7.11/gdb/gdbarch.sh5
-rw-r--r--gdb-7.11/gdb/gdbserver/Makefile.in13
-rw-r--r--gdb-7.11/gdb/gdbserver/configure.srv13
-rw-r--r--gdb-7.11/gdb/gdbserver/linux-mips-low.c215
-rw-r--r--gdb-7.11/gdb/mips-linux-nat.c477
-rw-r--r--gdb-7.11/gdb/mips-linux-tdep.c272
-rw-r--r--gdb-7.11/gdb/mips-linux-tdep.h10
-rw-r--r--gdb-7.11/gdb/mips-tdep.c2886
-rw-r--r--gdb-7.11/gdb/mips-tdep.h47
-rw-r--r--gdb-7.11/gdb/regcache.c28
-rw-r--r--gdb-7.11/gdb/regformats/mips-dsp-linux.dat1
-rw-r--r--gdb-7.11/gdb/regformats/mips-fpu64-dsp-linux.dat85
-rw-r--r--gdb-7.11/gdb/regformats/mips-fpu64-linux.dat78
-rw-r--r--gdb-7.11/gdb/regformats/mips-linux.dat1
-rw-r--r--gdb-7.11/gdb/regformats/mips-msa-linux.dat80
-rw-r--r--gdb-7.11/gdb/regformats/mips64-dsp-linux.dat1
-rw-r--r--gdb-7.11/gdb/regformats/mips64-linux.dat1
-rw-r--r--gdb-7.11/gdb/regformats/mips64-msa-linux.dat80
-rw-r--r--gdb-7.11/include/elf/common.h1
-rw-r--r--gdb-7.11/include/gdb/signals.def5
-rw-r--r--gdb-7.11/include/opcode/mips.h13
-rw-r--r--gdb-7.11/opcodes/micromips-opc.c5
-rw-r--r--gdb-7.11/opcodes/mips-dis.c53
-rw-r--r--gdb-7.11/opcodes/mips-opc.c14
54 files changed, 4927 insertions, 557 deletions
diff --git a/gdb-7.11/bfd/archures.c b/gdb-7.11/bfd/archures.c
index 12e3342f3..3054237fe 100644
--- a/gdb-7.11/bfd/archures.c
+++ b/gdb-7.11/bfd/archures.c
@@ -192,6 +192,7 @@ DESCRIPTION
.#define bfd_mach_mipsisa64r5 68
.#define bfd_mach_mipsisa64r6 69
.#define bfd_mach_mips_micromips 96
+.#define bfd_mach_mips_micromipsr6 97
. bfd_arch_i386, {* Intel 386 *}
.#define bfd_mach_i386_intel_syntax (1 << 0)
.#define bfd_mach_i386_i8086 (1 << 1)
diff --git a/gdb-7.11/bfd/bfd-in2.h b/gdb-7.11/bfd/bfd-in2.h
index fb4858c5b..d52e74e65 100644
--- a/gdb-7.11/bfd/bfd-in2.h
+++ b/gdb-7.11/bfd/bfd-in2.h
@@ -2007,6 +2007,7 @@ enum bfd_architecture
#define bfd_mach_mipsisa64r5 68
#define bfd_mach_mipsisa64r6 69
#define bfd_mach_mips_micromips 96
+#define bfd_mach_mips_micromipsr6 97
bfd_arch_i386, /* Intel 386 */
#define bfd_mach_i386_intel_syntax (1 << 0)
#define bfd_mach_i386_i8086 (1 << 1)
diff --git a/gdb-7.11/bfd/cpu-mips.c b/gdb-7.11/bfd/cpu-mips.c
index d209fb6a5..fd5ad3598 100644
--- a/gdb-7.11/bfd/cpu-mips.c
+++ b/gdb-7.11/bfd/cpu-mips.c
@@ -155,7 +155,8 @@ static const bfd_arch_info_type arch_info_struct[] =
N (64, 64, bfd_mach_mips_octeon2,"mips:octeon2", FALSE, NN(I_mipsocteon2)),
N (64, 64, bfd_mach_mips_octeon3, "mips:octeon3", FALSE, NN(I_mipsocteon3)),
N (64, 64, bfd_mach_mips_xlr, "mips:xlr", FALSE, NN(I_xlr)),
- N (64, 64, bfd_mach_mips_micromips,"mips:micromips",FALSE,0)
+ N (64, 64, bfd_mach_mips_micromips,"mips:micromips",FALSE,0),
+ N (64, 64, bfd_mach_mips_micromipsr6,"mips:micromipsr6",FALSE,0)
};
/* The default architecture is mips:3000, but with a machine number of
diff --git a/gdb-7.11/gdb/common/signals.c b/gdb-7.11/gdb/common/signals.c
index 45c0c7341..860fedf64 100644
--- a/gdb-7.11/gdb/common/signals.c
+++ b/gdb-7.11/gdb/common/signals.c
@@ -344,6 +344,10 @@ gdb_signal_from_host (int hostsig)
else if (64 <= hostsig && hostsig <= 127)
return (enum gdb_signal)
(hostsig - 64 + (int) GDB_SIGNAL_REALTIME_64);
+ else if (hostsig == 128)
+ /* Some platforms, such as Linux MIPS, have NSIG == 128, in which case
+ signal 128 is the highest realtime signal. */
+ return GDB_SIGNAL_REALTIME_128;
else
error (_("GDB bug: target.c (gdb_signal_from_host): "
"unrecognized real-time signal"));
@@ -609,6 +613,12 @@ do_gdb_signal_to_host (enum gdb_signal oursig,
GDB_SIGNAL_REALTIME_64 is 64 by definition. */
retsig = (int) oursig - (int) GDB_SIGNAL_REALTIME_64 + 64;
}
+ else if (oursig == GDB_SIGNAL_REALTIME_128)
+ {
+ /* GDB_SIGNAL_REALTIME_128 isn't contiguous with
+ GDB_SIGNAL_REALTIME_127. It is 128 by definition. */
+ retsig = 128;
+ }
if (retsig >= REALTIME_LO && retsig < REALTIME_HI)
return retsig;
diff --git a/gdb-7.11/gdb/features/Makefile b/gdb-7.11/gdb/features/Makefile
index 10173cf2d..d0d1d4cb2 100644
--- a/gdb-7.11/gdb/features/Makefile
+++ b/gdb-7.11/gdb/features/Makefile
@@ -57,9 +57,10 @@ WHICH = aarch64 \
i386/x32 i386/x32-linux \
i386/x32-avx i386/x32-avx-linux \
i386/x32-avx512 i386/x32-avx512-linux \
- mips-linux mips-dsp-linux \
microblaze-with-stack-protect \
- mips64-linux mips64-dsp-linux \
+ mips-linux mips-dsp-linux mips-fpu64-linux mips-fpu64-dsp-linux \
+ mips-msa-linux \
+ mips64-linux mips64-dsp-linux mips64-msa-linux \
nios2-linux \
rs6000/powerpc-32 \
rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \
@@ -100,11 +101,15 @@ i386/x32-avx-expedite = rbp,rsp,rip
i386/x32-avx-linux-expedite = rbp,rsp,rip
i386/x32-avx512-expedite = rbp,rsp,rip
i386/x32-avx512-linux-expedite = rbp,rsp,rip
+microblaze-expedite = r1,rpc
mips-expedite = r29,pc
mips-dsp-expedite = r29,pc
+mips-fpu64-expedite = r29,pc
+mips-fpu64-dsp-expedite = r29,pc
+mips-msa-expedite = r29,pc
mips64-expedite = r29,pc
mips64-dsp-expedite = r29,pc
-microblaze-expedite = r1,rpc
+mips64-msa-expedite = r29,pc
nios2-linux-expedite = sp,pc
powerpc-expedite = r1,pc
rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
diff --git a/gdb-7.11/gdb/features/mips-cp0.xml b/gdb-7.11/gdb/features/mips-cp0.xml
index 773fd88b7..349672e97 100644
--- a/gdb-7.11/gdb/features/mips-cp0.xml
+++ b/gdb-7.11/gdb/features/mips-cp0.xml
@@ -10,4 +10,5 @@
<reg name="status" bitsize="32" regnum="32"/>
<reg name="badvaddr" bitsize="32" regnum="35"/>
<reg name="cause" bitsize="32" regnum="36"/>
+ <reg name="config5" bitsize="32" regnum="38"/>
</feature>
diff --git a/gdb-7.11/gdb/features/mips-dsp-linux.c b/gdb-7.11/gdb/features/mips-dsp-linux.c
index 80ceb223a..b6e56fcdd 100644
--- a/gdb-7.11/gdb/features/mips-dsp-linux.c
+++ b/gdb-7.11/gdb/features/mips-dsp-linux.c
@@ -57,54 +57,55 @@ initialize_tdesc_mips_dsp_linux (void)
tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
- tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
- tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
- tdesc_create_reg (feature, "hi1", 72, 1, NULL, 32, "int");
- tdesc_create_reg (feature, "lo1", 73, 1, NULL, 32, "int");
- tdesc_create_reg (feature, "hi2", 74, 1, NULL, 32, "int");
- tdesc_create_reg (feature, "lo2", 75, 1, NULL, 32, "int");
- tdesc_create_reg (feature, "hi3", 76, 1, NULL, 32, "int");
- tdesc_create_reg (feature, "lo3", 77, 1, NULL, 32, "int");
- tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi1", 73, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo1", 74, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi2", 75, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo2", 76, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi3", 77, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo3", 78, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
- tdesc_create_reg (feature, "restart", 79, 1, "system", 32, "int");
+ tdesc_create_reg (feature, "restart", 80, 1, "system", 32, "int");
tdesc_mips_dsp_linux = result;
}
diff --git a/gdb-7.11/gdb/features/mips-dsp.xml b/gdb-7.11/gdb/features/mips-dsp.xml
index f8b7e7435..fcc903d7a 100644
--- a/gdb-7.11/gdb/features/mips-dsp.xml
+++ b/gdb-7.11/gdb/features/mips-dsp.xml
@@ -7,12 +7,12 @@
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.mips.dsp">
- <reg name="hi1" bitsize="32" regnum="72"/>
- <reg name="lo1" bitsize="32" regnum="73"/>
- <reg name="hi2" bitsize="32" regnum="74"/>
- <reg name="lo2" bitsize="32" regnum="75"/>
- <reg name="hi3" bitsize="32" regnum="76"/>
- <reg name="lo3" bitsize="32" regnum="77"/>
+ <reg name="hi1" bitsize="32"/>
+ <reg name="lo1" bitsize="32"/>
+ <reg name="hi2" bitsize="32"/>
+ <reg name="lo2" bitsize="32"/>
+ <reg name="hi3" bitsize="32"/>
+ <reg name="lo3" bitsize="32"/>
- <reg name="dspctl" bitsize="32" regnum="78"/>
+ <reg name="dspctl" bitsize="32"/>
</feature>
diff --git a/gdb-7.11/gdb/features/mips-fpu.xml b/gdb-7.11/gdb/features/mips-fpu.xml
index 4d331a1c2..44c41505e 100644
--- a/gdb-7.11/gdb/features/mips-fpu.xml
+++ b/gdb-7.11/gdb/features/mips-fpu.xml
@@ -7,7 +7,7 @@
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.mips.fpu">
- <reg name="f0" bitsize="32" type="ieee_single" regnum="38"/>
+ <reg name="f0" bitsize="32" type="ieee_single"/>
<reg name="f1" bitsize="32" type="ieee_single"/>
<reg name="f2" bitsize="32" type="ieee_single"/>
<reg name="f3" bitsize="32" type="ieee_single"/>
diff --git a/gdb-7.11/gdb/features/mips-fpu128.xml b/gdb-7.11/gdb/features/mips-fpu128.xml
new file mode 100644
index 000000000..25bd8201e
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-fpu128.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu">
+ <vector id="msa128" type="ieee_double" count="2"/>
+
+ <reg name="f0" bitsize="128" type="msa128"/>
+ <reg name="f1" bitsize="128" type="msa128"/>
+ <reg name="f2" bitsize="128" type="msa128"/>
+ <reg name="f3" bitsize="128" type="msa128"/>
+ <reg name="f4" bitsize="128" type="msa128"/>
+ <reg name="f5" bitsize="128" type="msa128"/>
+ <reg name="f6" bitsize="128" type="msa128"/>
+ <reg name="f7" bitsize="128" type="msa128"/>
+ <reg name="f8" bitsize="128" type="msa128"/>
+ <reg name="f9" bitsize="128" type="msa128"/>
+ <reg name="f10" bitsize="128" type="msa128"/>
+ <reg name="f11" bitsize="128" type="msa128"/>
+ <reg name="f12" bitsize="128" type="msa128"/>
+ <reg name="f13" bitsize="128" type="msa128"/>
+ <reg name="f14" bitsize="128" type="msa128"/>
+ <reg name="f15" bitsize="128" type="msa128"/>
+ <reg name="f16" bitsize="128" type="msa128"/>
+ <reg name="f17" bitsize="128" type="msa128"/>
+ <reg name="f18" bitsize="128" type="msa128"/>
+ <reg name="f19" bitsize="128" type="msa128"/>
+ <reg name="f20" bitsize="128" type="msa128"/>
+ <reg name="f21" bitsize="128" type="msa128"/>
+ <reg name="f22" bitsize="128" type="msa128"/>
+ <reg name="f23" bitsize="128" type="msa128"/>
+ <reg name="f24" bitsize="128" type="msa128"/>
+ <reg name="f25" bitsize="128" type="msa128"/>
+ <reg name="f26" bitsize="128" type="msa128"/>
+ <reg name="f27" bitsize="128" type="msa128"/>
+ <reg name="f28" bitsize="128" type="msa128"/>
+ <reg name="f29" bitsize="128" type="msa128"/>
+ <reg name="f30" bitsize="128" type="msa128"/>
+ <reg name="f31" bitsize="128" type="msa128"/>
+
+ <reg name="fcsr" bitsize="32" group="float"/>
+ <reg name="fir" bitsize="32" group="float"/>
+</feature>
diff --git a/gdb-7.11/gdb/features/mips-fpu64-dsp-linux.c b/gdb-7.11/gdb/features/mips-fpu64-dsp-linux.c
new file mode 100644
index 000000000..c6dd7d018
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-fpu64-dsp-linux.c
@@ -0,0 +1,111 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: mips-fpu64-dsp-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_fpu64_dsp_linux;
+static void
+initialize_tdesc_mips_fpu64_dsp_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+ tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+ tdesc_create_reg (feature, "hi1", 73, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo1", 74, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi2", 75, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo2", 76, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi3", 77, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo3", 78, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+ tdesc_create_reg (feature, "restart", 80, 1, "system", 32, "int");
+
+ tdesc_mips_fpu64_dsp_linux = result;
+}
diff --git a/gdb-7.11/gdb/features/mips-fpu64-dsp-linux.xml b/gdb-7.11/gdb/features/mips-fpu64-dsp-linux.xml
new file mode 100644
index 000000000..f0de5cec5
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-fpu64-dsp-linux.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>mips</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="mips-cpu.xml"/>
+ <xi:include href="mips-cp0.xml"/>
+ <xi:include href="mips-fpu64.xml"/>
+ <xi:include href="mips-dsp.xml"/>
+
+ <feature name="org.gnu.gdb.mips.linux">
+ <reg name="restart" bitsize="32" group="system"/>
+ </feature>
+</target>
diff --git a/gdb-7.11/gdb/features/mips-fpu64-linux.c b/gdb-7.11/gdb/features/mips-fpu64-linux.c
new file mode 100644
index 000000000..3fe44977a
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-fpu64-linux.c
@@ -0,0 +1,102 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: mips-fpu64-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_fpu64_linux;
+static void
+initialize_tdesc_mips_fpu64_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+ tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+ tdesc_create_reg (feature, "restart", 73, 1, "system", 32, "int");
+
+ tdesc_mips_fpu64_linux = result;
+}
diff --git a/gdb-7.11/gdb/features/mips-fpu64-linux.xml b/gdb-7.11/gdb/features/mips-fpu64-linux.xml
new file mode 100644
index 000000000..bc021c0cc
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-fpu64-linux.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>mips</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="mips-cpu.xml"/>
+ <xi:include href="mips-cp0.xml"/>
+ <xi:include href="mips-fpu64.xml"/>
+
+ <feature name="org.gnu.gdb.mips.linux">
+ <reg name="restart" bitsize="32" group="system"/>
+ </feature>
+</target>
diff --git a/gdb-7.11/gdb/features/mips-fpu64.xml b/gdb-7.11/gdb/features/mips-fpu64.xml
new file mode 100644
index 000000000..88dc9d92d
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-fpu64.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu">
+ <reg name="f0" bitsize="64" type="ieee_double"/>
+ <reg name="f1" bitsize="64" type="ieee_double"/>
+ <reg name="f2" bitsize="64" type="ieee_double"/>
+ <reg name="f3" bitsize="64" type="ieee_double"/>
+ <reg name="f4" bitsize="64" type="ieee_double"/>
+ <reg name="f5" bitsize="64" type="ieee_double"/>
+ <reg name="f6" bitsize="64" type="ieee_double"/>
+ <reg name="f7" bitsize="64" type="ieee_double"/>
+ <reg name="f8" bitsize="64" type="ieee_double"/>
+ <reg name="f9" bitsize="64" type="ieee_double"/>
+ <reg name="f10" bitsize="64" type="ieee_double"/>
+ <reg name="f11" bitsize="64" type="ieee_double"/>
+ <reg name="f12" bitsize="64" type="ieee_double"/>
+ <reg name="f13" bitsize="64" type="ieee_double"/>
+ <reg name="f14" bitsize="64" type="ieee_double"/>
+ <reg name="f15" bitsize="64" type="ieee_double"/>
+ <reg name="f16" bitsize="64" type="ieee_double"/>
+ <reg name="f17" bitsize="64" type="ieee_double"/>
+ <reg name="f18" bitsize="64" type="ieee_double"/>
+ <reg name="f19" bitsize="64" type="ieee_double"/>
+ <reg name="f20" bitsize="64" type="ieee_double"/>
+ <reg name="f21" bitsize="64" type="ieee_double"/>
+ <reg name="f22" bitsize="64" type="ieee_double"/>
+ <reg name="f23" bitsize="64" type="ieee_double"/>
+ <reg name="f24" bitsize="64" type="ieee_double"/>
+ <reg name="f25" bitsize="64" type="ieee_double"/>
+ <reg name="f26" bitsize="64" type="ieee_double"/>
+ <reg name="f27" bitsize="64" type="ieee_double"/>
+ <reg name="f28" bitsize="64" type="ieee_double"/>
+ <reg name="f29" bitsize="64" type="ieee_double"/>
+ <reg name="f30" bitsize="64" type="ieee_double"/>
+ <reg name="f31" bitsize="64" type="ieee_double"/>
+
+ <reg name="fcsr" bitsize="32" group="float"/>
+ <reg name="fir" bitsize="32" group="float"/>
+</feature>
diff --git a/gdb-7.11/gdb/features/mips-linux.c b/gdb-7.11/gdb/features/mips-linux.c
index c99011902..f31683549 100644
--- a/gdb-7.11/gdb/features/mips-linux.c
+++ b/gdb-7.11/gdb/features/mips-linux.c
@@ -57,45 +57,46 @@ initialize_tdesc_mips_linux (void)
tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
- tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
- tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
- tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 32, "ieee_single");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
- tdesc_create_reg (feature, "restart", 72, 1, "system", 32, "int");
+ tdesc_create_reg (feature, "restart", 73, 1, "system", 32, "int");
tdesc_mips_linux = result;
}
diff --git a/gdb-7.11/gdb/features/mips-msa-linux.c b/gdb-7.11/gdb/features/mips-msa-linux.c
new file mode 100644
index 000000000..ccaad092b
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-msa-linux.c
@@ -0,0 +1,110 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: mips-msa-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_msa_linux;
+static void
+initialize_tdesc_mips_msa_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+ struct tdesc_type *field_type;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+ tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+ field_type = tdesc_named_type (feature, "ieee_double");
+ tdesc_create_vector (feature, "msa128", field_type, 2);
+
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.msa");
+ tdesc_create_reg (feature, "msacsr", 73, 1, "vector", 32, "int");
+ tdesc_create_reg (feature, "msair", 74, 1, "vector", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+ tdesc_create_reg (feature, "restart", 75, 1, "system", 32, "int");
+
+ tdesc_mips_msa_linux = result;
+}
diff --git a/gdb-7.11/gdb/features/mips-msa-linux.xml b/gdb-7.11/gdb/features/mips-msa-linux.xml
new file mode 100644
index 000000000..45cbc3a00
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-msa-linux.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>mips</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="mips-cpu.xml"/>
+ <feature name="org.gnu.gdb.mips.cp0">
+ <reg name="status" bitsize="32" regnum="32"/>
+ <reg name="badvaddr" bitsize="32" regnum="35"/>
+ <reg name="cause" bitsize="32" regnum="36"/>
+ <reg name="config5" bitsize="32" regnum="38"/>
+ </feature>
+ <xi:include href="mips-fpu128.xml"/>
+ <xi:include href="mips-msa.xml"/>
+
+ <feature name="org.gnu.gdb.mips.linux">
+ <reg name="restart" bitsize="32" group="system"/>
+ </feature>
+
+</target>
diff --git a/gdb-7.11/gdb/features/mips-msa.xml b/gdb-7.11/gdb/features/mips-msa.xml
new file mode 100644
index 000000000..c36c24fb4
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips-msa.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.msa">
+ <reg name="msacsr" bitsize="32" group="vector"/>
+ <reg name="msair" bitsize="32" group="vector"/>
+</feature>
diff --git a/gdb-7.11/gdb/features/mips64-cp0.xml b/gdb-7.11/gdb/features/mips64-cp0.xml
index 7d20cf911..d1249f4e5 100644
--- a/gdb-7.11/gdb/features/mips64-cp0.xml
+++ b/gdb-7.11/gdb/features/mips64-cp0.xml
@@ -10,4 +10,5 @@
<reg name="status" bitsize="64" regnum="32"/>
<reg name="badvaddr" bitsize="64" regnum="35"/>
<reg name="cause" bitsize="64" regnum="36"/>
+ <reg name="config5" bitsize="64" regnum="38"/>
</feature>
diff --git a/gdb-7.11/gdb/features/mips64-dsp-linux.c b/gdb-7.11/gdb/features/mips64-dsp-linux.c
index bc0907844..f75cbd7ab 100644
--- a/gdb-7.11/gdb/features/mips64-dsp-linux.c
+++ b/gdb-7.11/gdb/features/mips64-dsp-linux.c
@@ -55,54 +55,55 @@ initialize_tdesc_mips64_dsp_linux (void)
tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 64, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
- tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
- tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 64, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 64, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
- tdesc_create_reg (feature, "hi1", 72, 1, NULL, 64, "int");
- tdesc_create_reg (feature, "lo1", 73, 1, NULL, 64, "int");
- tdesc_create_reg (feature, "hi2", 74, 1, NULL, 64, "int");
- tdesc_create_reg (feature, "lo2", 75, 1, NULL, 64, "int");
- tdesc_create_reg (feature, "hi3", 76, 1, NULL, 64, "int");
- tdesc_create_reg (feature, "lo3", 77, 1, NULL, 64, "int");
- tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "hi1", 73, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "lo1", 74, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "hi2", 75, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "lo2", 76, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "hi3", 77, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "lo3", 78, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
- tdesc_create_reg (feature, "restart", 79, 1, "system", 64, "int");
+ tdesc_create_reg (feature, "restart", 80, 1, "system", 64, "int");
tdesc_mips64_dsp_linux = result;
}
diff --git a/gdb-7.11/gdb/features/mips64-dsp.xml b/gdb-7.11/gdb/features/mips64-dsp.xml
index 0a2694e7c..a6272768a 100644
--- a/gdb-7.11/gdb/features/mips64-dsp.xml
+++ b/gdb-7.11/gdb/features/mips64-dsp.xml
@@ -7,12 +7,12 @@
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.mips.dsp">
- <reg name="hi1" bitsize="64" regnum="72"/>
- <reg name="lo1" bitsize="64" regnum="73"/>
- <reg name="hi2" bitsize="64" regnum="74"/>
- <reg name="lo2" bitsize="64" regnum="75"/>
- <reg name="hi3" bitsize="64" regnum="76"/>
- <reg name="lo3" bitsize="64" regnum="77"/>
+ <reg name="hi1" bitsize="64"/>
+ <reg name="lo1" bitsize="64"/>
+ <reg name="hi2" bitsize="64"/>
+ <reg name="lo2" bitsize="64"/>
+ <reg name="hi3" bitsize="64"/>
+ <reg name="lo3" bitsize="64"/>
- <reg name="dspctl" bitsize="32" regnum="78"/>
+ <reg name="dspctl" bitsize="32"/>
</feature>
diff --git a/gdb-7.11/gdb/features/mips64-fpu.xml b/gdb-7.11/gdb/features/mips64-fpu.xml
index 7596fecf7..60b194aed 100644
--- a/gdb-7.11/gdb/features/mips64-fpu.xml
+++ b/gdb-7.11/gdb/features/mips64-fpu.xml
@@ -7,7 +7,7 @@
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.mips.fpu">
- <reg name="f0" bitsize="64" type="ieee_double" regnum="38"/>
+ <reg name="f0" bitsize="64" type="ieee_double"/>
<reg name="f1" bitsize="64" type="ieee_double"/>
<reg name="f2" bitsize="64" type="ieee_double"/>
<reg name="f3" bitsize="64" type="ieee_double"/>
diff --git a/gdb-7.11/gdb/features/mips64-fpu128.xml b/gdb-7.11/gdb/features/mips64-fpu128.xml
new file mode 100644
index 000000000..d176ae904
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips64-fpu128.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu">
+ <vector id="msa128" type="ieee_double" count="2"/>
+
+ <reg name="f0" bitsize="128" type="msa128"/>
+ <reg name="f1" bitsize="128" type="msa128"/>
+ <reg name="f2" bitsize="128" type="msa128"/>
+ <reg name="f3" bitsize="128" type="msa128"/>
+ <reg name="f4" bitsize="128" type="msa128"/>
+ <reg name="f5" bitsize="128" type="msa128"/>
+ <reg name="f6" bitsize="128" type="msa128"/>
+ <reg name="f7" bitsize="128" type="msa128"/>
+ <reg name="f8" bitsize="128" type="msa128"/>
+ <reg name="f9" bitsize="128" type="msa128"/>
+ <reg name="f10" bitsize="128" type="msa128"/>
+ <reg name="f11" bitsize="128" type="msa128"/>
+ <reg name="f12" bitsize="128" type="msa128"/>
+ <reg name="f13" bitsize="128" type="msa128"/>
+ <reg name="f14" bitsize="128" type="msa128"/>
+ <reg name="f15" bitsize="128" type="msa128"/>
+ <reg name="f16" bitsize="128" type="msa128"/>
+ <reg name="f17" bitsize="128" type="msa128"/>
+ <reg name="f18" bitsize="128" type="msa128"/>
+ <reg name="f19" bitsize="128" type="msa128"/>
+ <reg name="f20" bitsize="128" type="msa128"/>
+ <reg name="f21" bitsize="128" type="msa128"/>
+ <reg name="f22" bitsize="128" type="msa128"/>
+ <reg name="f23" bitsize="128" type="msa128"/>
+ <reg name="f24" bitsize="128" type="msa128"/>
+ <reg name="f25" bitsize="128" type="msa128"/>
+ <reg name="f26" bitsize="128" type="msa128"/>
+ <reg name="f27" bitsize="128" type="msa128"/>
+ <reg name="f28" bitsize="128" type="msa128"/>
+ <reg name="f29" bitsize="128" type="msa128"/>
+ <reg name="f30" bitsize="128" type="msa128"/>
+ <reg name="f31" bitsize="128" type="msa128"/>
+
+ <reg name="fcsr" bitsize="64" group="float"/>
+ <reg name="fir" bitsize="64" group="float"/>
+</feature>
diff --git a/gdb-7.11/gdb/features/mips64-linux.c b/gdb-7.11/gdb/features/mips64-linux.c
index 2ecda9ba3..0c9331b7f 100644
--- a/gdb-7.11/gdb/features/mips64-linux.c
+++ b/gdb-7.11/gdb/features/mips64-linux.c
@@ -55,45 +55,46 @@ initialize_tdesc_mips64_linux (void)
tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 64, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
- tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
- tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
- tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 64, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 64, "int");
feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
- tdesc_create_reg (feature, "restart", 72, 1, "system", 64, "int");
+ tdesc_create_reg (feature, "restart", 73, 1, "system", 64, "int");
tdesc_mips64_linux = result;
}
diff --git a/gdb-7.11/gdb/features/mips64-msa-linux.c b/gdb-7.11/gdb/features/mips64-msa-linux.c
new file mode 100644
index 000000000..31dd697f1
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips64-msa-linux.c
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: mips64-msa-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips64_msa_linux;
+static void
+initialize_tdesc_mips64_msa_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+ struct tdesc_type *field_type;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "lo", 33, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "hi", 34, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "pc", 37, 1, NULL, 64, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+ tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+ tdesc_create_reg (feature, "config5", 38, 1, NULL, 64, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+ field_type = tdesc_named_type (feature, "ieee_double");
+ tdesc_create_vector (feature, "msa128", field_type, 2);
+
+ tdesc_create_reg (feature, "f0", 39, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f1", 40, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f2", 41, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f3", 42, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f4", 43, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f5", 44, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f6", 45, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f7", 46, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f8", 47, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f9", 48, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f10", 49, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f11", 50, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f12", 51, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f13", 52, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f14", 53, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f15", 54, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f16", 55, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f17", 56, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f18", 57, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f19", 58, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f20", 59, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f21", 60, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f22", 61, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f23", 62, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f24", 63, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f25", 64, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f26", 65, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f27", 66, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f28", 67, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f29", 68, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f30", 69, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "f31", 70, 1, NULL, 128, "msa128");
+ tdesc_create_reg (feature, "fcsr", 71, 1, "float", 64, "int");
+ tdesc_create_reg (feature, "fir", 72, 1, "float", 64, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.msa");
+ tdesc_create_reg (feature, "msacsr", 73, 1, "vector", 64, "int");
+ tdesc_create_reg (feature, "msair", 74, 1, "vector", 64, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+ tdesc_create_reg (feature, "restart", 75, 1, "system", 64, "int");
+
+ tdesc_mips64_msa_linux = result;
+}
diff --git a/gdb-7.11/gdb/features/mips64-msa-linux.xml b/gdb-7.11/gdb/features/mips64-msa-linux.xml
new file mode 100644
index 000000000..709ad5030
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips64-msa-linux.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>mips</architecture>
+ <xi:include href="mips64-cpu.xml"/>
+ <feature name="org.gnu.gdb.mips.cp0">
+ <reg name="status" bitsize="64" regnum="32"/>
+ <reg name="badvaddr" bitsize="64" regnum="35"/>
+ <reg name="cause" bitsize="64" regnum="36"/>
+ <reg name="config5" bitsize="64" regnum="38"/>
+ </feature>
+ <xi:include href="mips64-fpu128.xml"/>
+ <xi:include href="mips64-msa.xml"/>
+
+ <feature name="org.gnu.gdb.mips.linux">
+ <reg name="restart" bitsize="64" group="system"/>
+ </feature>
+</target>
diff --git a/gdb-7.11/gdb/features/mips64-msa.xml b/gdb-7.11/gdb/features/mips64-msa.xml
new file mode 100644
index 000000000..832f722d3
--- /dev/null
+++ b/gdb-7.11/gdb/features/mips64-msa.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.msa">
+ <reg name="msacsr" bitsize="64" group="vector"/>
+ <reg name="msair" bitsize="64" group="vector"/>
+</feature>
diff --git a/gdb-7.11/gdb/gdbarch.c b/gdb-7.11/gdb/gdbarch.c
index 41437447a..0673fc1a0 100644
--- a/gdb-7.11/gdb/gdbarch.c
+++ b/gdb-7.11/gdb/gdbarch.c
@@ -199,6 +199,7 @@ struct gdbarch
gdbarch_dwarf2_reg_to_regnum_ftype *dwarf2_reg_to_regnum;
gdbarch_register_name_ftype *register_name;
gdbarch_register_type_ftype *register_type;
+ gdbarch_regcache_changed_ftype *regcache_changed;
gdbarch_dummy_id_ftype *dummy_id;
int deprecated_fp_regnum;
gdbarch_push_dummy_call_ftype *push_dummy_call;
@@ -543,6 +544,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
if (gdbarch->register_name == 0)
fprintf_unfiltered (log, "\n\tregister_name");
/* Skip verify of register_type, has predicate. */
+ /* Skip verify of regcache_changed, has predicate. */
/* Skip verify of dummy_id, has predicate. */
/* Skip verify of deprecated_fp_regnum, invalid_p == 0 */
/* Skip verify of push_dummy_call, has predicate. */
@@ -1225,6 +1227,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: record_special_symbol = <%s>\n",
host_address_to_string (gdbarch->record_special_symbol));
fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_regcache_changed_p() = %d\n",
+ gdbarch_regcache_changed_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: regcache_changed = <%s>\n",
+ host_address_to_string (gdbarch->regcache_changed));
+ fprintf_unfiltered (file,
"gdbarch_dump: register_name = <%s>\n",
host_address_to_string (gdbarch->register_name));
fprintf_unfiltered (file,
@@ -2171,6 +2179,30 @@ set_gdbarch_register_type (struct gdbarch *gdbarch,
}
int
+gdbarch_regcache_changed_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->regcache_changed != NULL;
+}
+
+int
+gdbarch_regcache_changed (struct gdbarch *gdbarch, struct regcache *regcache)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->regcache_changed != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_regcache_changed called\n");
+ return gdbarch->regcache_changed (gdbarch, regcache);
+}
+
+void
+set_gdbarch_regcache_changed (struct gdbarch *gdbarch,
+ gdbarch_regcache_changed_ftype regcache_changed)
+{
+ gdbarch->regcache_changed = regcache_changed;
+}
+
+int
gdbarch_dummy_id_p (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
diff --git a/gdb-7.11/gdb/gdbarch.h b/gdb-7.11/gdb/gdbarch.h
index 3fadcd14b..0be2877ca 100644
--- a/gdb-7.11/gdb/gdbarch.h
+++ b/gdb-7.11/gdb/gdbarch.h
@@ -356,6 +356,17 @@ typedef struct type * (gdbarch_register_type_ftype) (struct gdbarch *gdbarch, in
extern struct type * gdbarch_register_type (struct gdbarch *gdbarch, int reg_nr);
extern void set_gdbarch_register_type (struct gdbarch *gdbarch, gdbarch_register_type_ftype *register_type);
+/* Notify the architecture that the registers have changed and we now have
+ a new regcache to examine. Return one if a new architecture has been
+ selected that changed the layout of the regcache and it has to be
+ discarded and a new one initialised, zero otherwise. */
+
+extern int gdbarch_regcache_changed_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_regcache_changed_ftype) (struct gdbarch *gdbarch, struct regcache *regcache);
+extern int gdbarch_regcache_changed (struct gdbarch *gdbarch, struct regcache *regcache);
+extern void set_gdbarch_regcache_changed (struct gdbarch *gdbarch, gdbarch_regcache_changed_ftype *regcache_changed);
+
extern int gdbarch_dummy_id_p (struct gdbarch *gdbarch);
typedef struct frame_id (gdbarch_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *this_frame);
@@ -1570,7 +1581,7 @@ struct gdbarch_info
bfd *abfd;
/* Use default: NULL (ZERO). */
- void *tdep_info;
+ struct gdbarch_tdep_info *tdep_info;
/* Use default: GDB_OSABI_UNINITIALIZED (-1). */
enum gdb_osabi osabi;
diff --git a/gdb-7.11/gdb/gdbarch.sh b/gdb-7.11/gdb/gdbarch.sh
index 4ac6b90fd..2c0937145 100755
--- a/gdb-7.11/gdb/gdbarch.sh
+++ b/gdb-7.11/gdb/gdbarch.sh
@@ -469,6 +469,11 @@ m:const char *:register_name:int regnr:regnr::0
# the register cache should call this function directly; others should
# use "register_type".
M:struct type *:register_type:int reg_nr:reg_nr
+# Notify the architecture that the registers have changed and we now have
+# a new regcache to examine. Return one if a new architecture has been
+# selected that changed the layout of the regcache and it has to be
+# discarded and a new one initialised, zero otherwise.
+M:int:regcache_changed:struct regcache *regcache:regcache
M:struct frame_id:dummy_id:struct frame_info *this_frame:this_frame
# Implement DUMMY_ID and PUSH_DUMMY_CALL, then delete
diff --git a/gdb-7.11/gdb/gdbserver/Makefile.in b/gdb-7.11/gdb/gdbserver/Makefile.in
index 1e874e39e..4d97705c7 100644
--- a/gdb-7.11/gdb/gdbserver/Makefile.in
+++ b/gdb-7.11/gdb/gdbserver/Makefile.in
@@ -357,8 +357,9 @@ clean:
rm -f reg-tilegx.c reg-tilegx32.c
rm -f arm-with-iwmmxt.c
rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c
- rm -f mips-linux.c mips-dsp-linux.c
- rm -f mips64-linux.c mips64-dsp-linux.c
+ rm -f mips-linux.c mips-dsp-linux.c mips-fpu64-linux.c
+ rm -f mips-fpu64-dsp-linux.c mips-msa-linux.c
+ rm -f mips64-linux.c mips64-dsp-linux.c mips64-msa-linux.c
rm -f nios2-linux.c
rm -f powerpc-32.c powerpc-32l.c powerpc-64l.c powerpc-e500l.c
rm -f powerpc-altivec32l.c powerpc-cell32l.c powerpc-vsx32l.c
@@ -710,10 +711,18 @@ mips-linux.c : $(srcdir)/../regformats/mips-linux.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-linux.dat mips-linux.c
mips-dsp-linux.c : $(srcdir)/../regformats/mips-dsp-linux.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-dsp-linux.dat mips-dsp-linux.c
+mips-fpu64-linux.c : $(srcdir)/../regformats/mips-fpu64-linux.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-fpu64-linux.dat mips-fpu64-linux.c
+mips-fpu64-dsp-linux.c : $(srcdir)/../regformats/mips-fpu64-dsp-linux.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-fpu64-dsp-linux.dat mips-fpu64-dsp-linux.c
+mips-msa-linux.c : $(srcdir)/../regformats/mips-msa-linux.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-msa-linux.dat mips-msa-linux.c
mips64-linux.c : $(srcdir)/../regformats/mips64-linux.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-linux.dat mips64-linux.c
mips64-dsp-linux.c : $(srcdir)/../regformats/mips64-dsp-linux.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-dsp-linux.dat mips64-dsp-linux.c
+mips64-msa-linux.c : $(srcdir)/../regformats/mips64-msa-linux.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-msa-linux.dat mips64-msa-linux.c
nios2-linux.c : $(srcdir)/../regformats/nios2-linux.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nios2-linux.dat nios2-linux.c
powerpc-32.c : $(srcdir)/../regformats/rs6000/powerpc-32.dat $(regdat_sh)
diff --git a/gdb-7.11/gdb/gdbserver/configure.srv b/gdb-7.11/gdb/gdbserver/configure.srv
index a54b9e792..f0300c1aa 100644
--- a/gdb-7.11/gdb/gdbserver/configure.srv
+++ b/gdb-7.11/gdb/gdbserver/configure.srv
@@ -187,22 +187,35 @@ case "${target}" in
;;
mips*-*-linux*) srv_regobj="mips-linux.o"
srv_regobj="${srv_regobj} mips-dsp-linux.o"
+ srv_regobj="${srv_regobj} mips-fpu64-linux.o"
+ srv_regobj="${srv_regobj} mips-fpu64-dsp-linux.o"
+ srv_regobj="${srv_regobj} mips-msa-linux.o"
srv_regobj="${srv_regobj} mips64-linux.o"
srv_regobj="${srv_regobj} mips64-dsp-linux.o"
+ srv_regobj="${srv_regobj} mips64-msa-linux.o"
srv_tgtobj="$srv_linux_obj linux-mips-low.o"
srv_tgtobj="${srv_tgtobj} mips-linux-watch.o"
srv_xmlfiles="mips-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips-fpu64-linux.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips-fpu64-dsp-linux.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips-msa-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml"
srv_xmlfiles="${srv_xmlfiles} mips-cp0.xml"
srv_xmlfiles="${srv_xmlfiles} mips-fpu.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips-fpu64.xml"
srv_xmlfiles="${srv_xmlfiles} mips-dsp.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips-fpu128.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips-msa.xml"
srv_xmlfiles="${srv_xmlfiles} mips64-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips64-dsp-linux.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips64-msa-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips64-cpu.xml"
srv_xmlfiles="${srv_xmlfiles} mips64-cp0.xml"
srv_xmlfiles="${srv_xmlfiles} mips64-fpu.xml"
srv_xmlfiles="${srv_xmlfiles} mips64-dsp.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips64-fpu128.xml"
+ srv_xmlfiles="${srv_xmlfiles} mips64-msa.xml"
srv_linux_regsets=yes
srv_linux_usrregs=yes
srv_linux_thread_db=yes
diff --git a/gdb-7.11/gdb/gdbserver/linux-mips-low.c b/gdb-7.11/gdb/gdbserver/linux-mips-low.c
index 30a03d5f4..604abab82 100644
--- a/gdb-7.11/gdb/gdbserver/linux-mips-low.c
+++ b/gdb-7.11/gdb/gdbserver/linux-mips-low.c
@@ -18,9 +18,11 @@
#include "server.h"
#include "linux-low.h"
+#include "elf/common.h"
#include "nat/gdb_ptrace.h"
#include <endian.h>
+#include <sys/uio.h>
#include "nat/mips-linux-watch.h"
#include "gdb_proc_service.h"
@@ -33,6 +35,18 @@ extern const struct target_desc *tdesc_mips_linux;
void init_registers_mips_dsp_linux (void);
extern const struct target_desc *tdesc_mips_dsp_linux;
+/* Defined in auto-generated file mips-fpu64-linux.c. */
+void init_registers_mips_fpu64_linux (void);
+extern const struct target_desc *tdesc_mips_fpu64_linux;
+
+/* Defined in auto-generated file mips-fpu64-dsp-linux.c. */
+void init_registers_mips_fpu64_dsp_linux (void);
+extern const struct target_desc *tdesc_mips_fpu64_dsp_linux;
+
+/* Defined in auto-generated file mips-msa-linux.c. */
+void init_registers_mips_msa_linux (void);
+extern const struct target_desc *tdesc_mips_msa_linux;
+
/* Defined in auto-generated file mips64-linux.c. */
void init_registers_mips64_linux (void);
extern const struct target_desc *tdesc_mips64_linux;
@@ -41,21 +55,36 @@ extern const struct target_desc *tdesc_mips64_linux;
void init_registers_mips64_dsp_linux (void);
extern const struct target_desc *tdesc_mips64_dsp_linux;
+/* Defined in auto-generated file mips64-msa-linux.c. */
+void init_registers_mips64_msa_linux (void);
+extern const struct target_desc *tdesc_mips64_msa_linux;
+
#ifdef __mips64
#define tdesc_mips_linux tdesc_mips64_linux
#define tdesc_mips_dsp_linux tdesc_mips64_dsp_linux
+#define tdesc_mips_fpu64_linux tdesc_mips64_linux
+#define tdesc_mips_fpu64_dsp_linux tdesc_mips64_dsp_linux
+#define tdesc_mips_msa_linux tdesc_mips64_msa_linux
#endif
#ifndef PTRACE_GET_THREAD_AREA
#define PTRACE_GET_THREAD_AREA 25
#endif
+#ifndef PTRACE_GETREGSET
+#define PTRACE_GETREGSET 0x4204
+#endif
+
+#ifndef PTRACE_SETREGSET
+#define PTRACE_SETREGSET 0x4205
+#endif
+
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
-#define mips_num_regs 73
-#define mips_dsp_num_regs 80
+#define mips_num_regs 74
+#define mips_dsp_num_regs 81
#include <asm/ptrace.h>
@@ -64,6 +93,9 @@ extern const struct target_desc *tdesc_mips64_dsp_linux;
#define DSP_CONTROL 77
#endif
+#define ST0_FR (1 << 26)
+#define FIR_F64 (1 << 22)
+
union mips_register
{
unsigned char buf[8];
@@ -81,7 +113,7 @@ union mips_register
16, 17, 18, 19, 20, 21, 22, 23, \
24, 25, 26, 27, 28, 29, 30, 31, \
\
- -1, MMLO, MMHI, BADVADDR, CAUSE, PC, \
+ -1, MMLO, MMHI, BADVADDR, CAUSE, PC, -1, \
\
FPR_BASE, FPR_BASE + 1, FPR_BASE + 2, FPR_BASE + 3, \
FPR_BASE + 4, FPR_BASE + 5, FPR_BASE + 6, FPR_BASE + 7, \
@@ -117,17 +149,68 @@ static unsigned char mips_dsp_regset_bitmap[(mips_dsp_num_regs + 7) / 8] = {
};
static int have_dsp = -1;
+static int have_fpu64 = -1;
+static int have_msa = -1;
-/* Try peeking at an arbitrarily chosen DSP register and pick the available
- user register set accordingly. */
+/* Try peeking at registers and pick the available user register set
+ accordingly. */
static const struct target_desc *
mips_read_description (void)
{
+ const struct target_desc *tdescs[2][2] =
+ {
+ /* have_fpu64 = 0 have_fpu64 = 1 */
+ { tdesc_mips_linux, tdesc_mips_fpu64_linux }, /* have_dsp = 0 */
+ { tdesc_mips_dsp_linux, tdesc_mips_fpu64_dsp_linux }, /* have_dsp = 1 */
+ };
+
+ if (have_fpu64 < 0)
+ {
+ int pid = lwpid_of (current_thread);
+ long fir;
+
+ /* Try peeking at FIR.F64 bit */
+ errno = 0;
+ fir = ptrace (PTRACE_PEEKUSER, pid, FPC_EIR, 0);
+ switch (errno)
+ {
+ case 0:
+ have_fpu64 = !!(fir & FIR_F64);
+ break;
+ case EIO:
+ have_fpu64 = 0;
+ have_msa = 0;
+ break;
+ default:
+ perror_with_name ("ptrace");
+ break;
+ }
+ }
+
+ /* Check for MSA, which requires FR=1 */
+ if (have_msa < 0)
+ {
+ int pid = lwpid_of (current_thread);
+ int res;
+ uint32_t regs[32*4 + 8];
+ struct iovec iov;
+
+ /* this'd probably be better */
+ //have_msa = (getauxval(AT_HWCAP) & 0x2) != 0;
+
+ /* Test MSAIR */
+ iov.iov_base = regs;
+ iov.iov_len = sizeof(regs);
+ res = ptrace (PTRACE_GETREGSET, pid, NT_MIPS_MSA, &iov);
+ have_msa = (res >= 0) && regs[32*4 + 0];
+ }
+
if (have_dsp < 0)
{
int pid = lwpid_of (current_thread);
+ /* Try peeking at an arbitrarily chosen DSP register */
errno = 0;
ptrace (PTRACE_PEEKUSER, pid, DSP_CONTROL, 0);
switch (errno)
@@ -144,7 +227,8 @@ mips_read_description (void)
}
}
- return have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
+ return have_msa ? tdesc_mips_msa_linux
+ : tdescs[have_dsp][have_fpu64];
}
static void
@@ -743,6 +827,7 @@ mips_store_gregset (struct regcache *regcache, const void *buf)
{
const union mips_register *regset = (const union mips_register *) buf;
int i, use_64bit;
+ int config5 = find_regno (regcache->tdesc, "config5");
use_64bit = (register_size (regcache->tdesc, 0) == 8);
@@ -764,28 +849,37 @@ mips_store_gregset (struct regcache *regcache, const void *buf)
mips_supply_register (regcache, use_64bit,
find_regno (regcache->tdesc, "restart"), regset + 0);
+
+ if (config5 != -1)
+ {
+ union mips_register reg;
+ reg.reg64 = 0;
+ mips_supply_register (regcache, use_64bit, config5, &reg);
+ }
}
static void
mips_fill_fpregset (struct regcache *regcache, void *buf)
{
union mips_register *regset = (union mips_register *) buf;
- int i, use_64bit, first_fp, big_endian;
+ int i, use_64bit, fp_use_64bit, first_fp, big_endian;
use_64bit = (register_size (regcache->tdesc, 0) == 8);
first_fp = find_regno (regcache->tdesc, "f0");
+ fp_use_64bit = (register_size (regcache->tdesc, first_fp) >= 8);
big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
/* See GDB for a discussion of this peculiar layout. */
for (i = 0; i < 32; i++)
- if (use_64bit)
+ if (fp_use_64bit)
collect_register (regcache, first_fp + i, regset[i].buf);
else
collect_register (regcache, first_fp + i,
regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
mips_collect_register_32bit (regcache, use_64bit,
- find_regno (regcache->tdesc, "fcsr"), regset[32].buf);
+ find_regno (regcache->tdesc, "fcsr"),
+ regset[32].buf);
mips_collect_register_32bit (regcache, use_64bit,
find_regno (regcache->tdesc, "fir"),
regset[32].buf + 4);
@@ -795,15 +889,16 @@ static void
mips_store_fpregset (struct regcache *regcache, const void *buf)
{
const union mips_register *regset = (const union mips_register *) buf;
- int i, use_64bit, first_fp, big_endian;
+ int i, use_64bit, fp_use_64bit, first_fp, big_endian;
use_64bit = (register_size (regcache->tdesc, 0) == 8);
first_fp = find_regno (regcache->tdesc, "f0");
+ fp_use_64bit = (register_size (regcache->tdesc, first_fp) >= 8);
big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
/* See GDB for a discussion of this peculiar layout. */
for (i = 0; i < 32; i++)
- if (use_64bit)
+ if (fp_use_64bit)
supply_register (regcache, first_fp + i, regset[i].buf);
else
supply_register (regcache, first_fp + i,
@@ -818,12 +913,106 @@ mips_store_fpregset (struct regcache *regcache, const void *buf)
}
#endif /* HAVE_PTRACE_GETREGS */
+static void
+mips_fill_msa_regset (struct regcache *regcache, void *buf)
+{
+ unsigned char *bufp = buf;
+ int i, first_fp, fir, fcsr, msair, msacsr, config5;
+ unsigned char tmp[16];
+
+ if (!have_msa)
+ return;
+
+ first_fp = find_regno (regcache->tdesc, "f0");
+ fir = find_regno (regcache->tdesc, "fir");
+ fcsr = find_regno (regcache->tdesc, "fcsr");
+ msair = find_regno (regcache->tdesc, "msair");
+ msacsr = find_regno (regcache->tdesc, "msacsr");
+ config5 = find_regno (regcache->tdesc, "config5");
+
+ /* full vector including float */
+ if (__BYTE_ORDER == __BIG_ENDIAN)
+ for (i = 0; i < 32; i++)
+ {
+ collect_register (regcache, first_fp + i, tmp);
+ /* swap 64-bit halves, so it's a single word */
+ memcpy(bufp, tmp + 8, 8);
+ memcpy(bufp + 8, tmp, 8);
+ bufp += 16;
+ }
+ else
+ for (i = 0; i < 32; i++)
+ {
+ collect_register (regcache, first_fp + i, bufp);
+ bufp += 16;
+ }
+
+ /* FIXME gonna break with MIPS64 */
+ collect_register (regcache, fir, bufp);
+ bufp += 4;
+ collect_register (regcache, fcsr, bufp);
+ bufp += 4;
+ collect_register (regcache, msair, bufp);
+ bufp += 4;
+ collect_register (regcache, msacsr, bufp);
+ bufp += 4;
+ collect_register (regcache, config5, bufp);
+}
+
+static void
+mips_store_msa_regset (struct regcache *regcache, const void *buf)
+{
+ const unsigned char *bufp = buf;
+ int i, first_fp, fir, fcsr, msair, msacsr, config5;
+ unsigned char tmp[16];
+
+ if (!have_msa)
+ return;
+
+ first_fp = find_regno (regcache->tdesc, "f0");
+ fir = find_regno (regcache->tdesc, "fir");
+ fcsr = find_regno (regcache->tdesc, "fcsr");
+ msair = find_regno (regcache->tdesc, "msair");
+ msacsr = find_regno (regcache->tdesc, "msacsr");
+ config5 = find_regno (regcache->tdesc, "config5");
+
+ /* full vector including float */
+ if (__BYTE_ORDER == __BIG_ENDIAN)
+ for (i = 0; i < 32; i++)
+ {
+ /* swap 64-bit halves, as it's a single word */
+ memcpy(tmp, bufp + 8, 8);
+ memcpy(tmp + 8, bufp, 8);
+ supply_register (regcache, first_fp + i, tmp);
+ bufp += 16;
+ }
+ else
+ for (i = 0; i < 32; i++)
+ {
+ supply_register (regcache, first_fp + i, bufp);
+ bufp += 16;
+ }
+
+ /* FIXME gonna break with MIPS64 */
+ supply_register (regcache, fir, bufp);
+ bufp += 4;
+ supply_register (regcache, fcsr, bufp);
+ bufp += 4;
+ supply_register (regcache, msair, bufp);
+ bufp += 4;
+ supply_register (regcache, msacsr, bufp);
+ bufp += 4;
+ supply_register (regcache, config5, bufp);
+}
+
static struct regset_info mips_regsets[] = {
#ifdef HAVE_PTRACE_GETREGS
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
mips_fill_gregset, mips_store_gregset },
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS,
mips_fill_fpregset, mips_store_fpregset },
+ { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_MIPS_MSA, 34*16, EXTENDED_REGS,
+ mips_fill_msa_regset, mips_store_msa_regset },
#endif /* HAVE_PTRACE_GETREGS */
NULL_REGSET
};
@@ -903,8 +1092,12 @@ initialize_low_arch (void)
/* Initialize the Linux target descriptions. */
init_registers_mips_linux ();
init_registers_mips_dsp_linux ();
+ init_registers_mips_fpu64_linux ();
+ init_registers_mips_fpu64_dsp_linux ();
+ init_registers_mips_msa_linux ();
init_registers_mips64_linux ();
init_registers_mips64_dsp_linux ();
+ init_registers_mips64_msa_linux ();
initialize_regsets_info (&mips_regsets_info);
}
diff --git a/gdb-7.11/gdb/mips-linux-nat.c b/gdb-7.11/gdb/mips-linux-nat.c
index bfe9fcbe6..ba8e1e426 100644
--- a/gdb-7.11/gdb/mips-linux-nat.c
+++ b/gdb-7.11/gdb/mips-linux-nat.c
@@ -27,6 +27,7 @@
#include "linux-nat.h"
#include "mips-linux-tdep.h"
#include "target-descriptions.h"
+#include "elf/common.h"
#include "gdb_proc_service.h"
#include "gregset.h"
@@ -39,17 +40,36 @@
#include "features/mips-linux.c"
#include "features/mips-dsp-linux.c"
+#include "features/mips-fpu64-linux.c"
+#include "features/mips-fpu64-dsp-linux.c"
+#include "features/mips-msa-linux.c"
#include "features/mips64-linux.c"
#include "features/mips64-dsp-linux.c"
+#include "features/mips64-msa-linux.c"
#ifndef PTRACE_GET_THREAD_AREA
#define PTRACE_GET_THREAD_AREA 25
#endif
+#ifndef PTRACE_GETREGSET
+#define PTRACE_GETREGSET 0x4204
+#endif
+
+#ifndef PTRACE_SETREGSET
+#define PTRACE_SETREGSET 0x4205
+#endif
+
+#define FIR_F64 (1 << 22)
+
/* Assume that we have PTRACE_GETREGS et al. support. If we do not,
we'll clear this and use PTRACE_PEEKUSER instead. */
static int have_ptrace_regsets = 1;
+/* Does the current host support PTRACE_GETREGSET? */
+static int have_ptrace_getregset = 1;
+static int have_ptrace_getregset_fp = 1;
+static int have_ptrace_getregset_msa = 1;
+
/* Saved function pointers to fetch and store a single register using
PTRACE_PEEKUSER and PTRACE_POKEUSER. */
@@ -100,7 +120,7 @@ mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
else if (regno == mips_regnum (gdbarch)->dspctl)
regaddr = DSP_CONTROL;
- else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
+ else if (regno == mips_regnum (gdbarch)->linux_restart)
regaddr = 0;
else
regaddr = (CORE_ADDR) -1;
@@ -141,7 +161,7 @@ mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
else if (regno == mips_regnum (gdbarch)->dspctl)
regaddr = DSP_CONTROL;
- else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
+ else if (regno == mips_regnum (gdbarch)->linux_restart)
regaddr = 0;
else
regaddr = (CORE_ADDR) -1;
@@ -190,25 +210,18 @@ fill_gregset (const struct regcache *regcache,
void
supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
{
- if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
- mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *) fpregsetp);
- else
- mips64_supply_fpregset (regcache,
- (const mips64_elf_fpregset_t *) fpregsetp);
+ mips64_supply_fpregset (regcache,
+ (const mips64_elf_fpregset_t *) fpregsetp);
}
void
fill_fpregset (const struct regcache *regcache,
gdb_fpregset_t *fpregsetp, int regno)
{
- if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
- mips_fill_fpregset (regcache, (mips_elf_fpregset_t *) fpregsetp, regno);
- else
- mips64_fill_fpregset (regcache,
- (mips64_elf_fpregset_t *) fpregsetp, regno);
+ mips64_fill_fpregset (regcache,
+ (mips64_elf_fpregset_t *) fpregsetp, regno);
}
-
/* Fetch REGNO (or all registers if REGNO == -1) from the target
using PTRACE_GETREGS et al. */
@@ -217,21 +230,36 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int is_fp, is_dsp;
+ int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+ int is_fp, is_dsp, is_vec;
int have_dsp;
int regi;
int tid;
- if (regno >= mips_regnum (gdbarch)->fp0
- && regno <= mips_regnum (gdbarch)->fp0 + 32)
+ /* FP registers can be obtained in several ways.
+ is_fp will be cleared once the registers have been obtained. */
+ if (regno == -1)
+ is_fp = 1;
+ else if (regno >= mips_regnum (gdbarch)->fp0
+ && regno <= mips_regnum (gdbarch)->fp0 + 32)
is_fp = 1;
else if (regno == mips_regnum (gdbarch)->fp_control_status)
is_fp = 1;
else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
is_fp = 1;
+ else if (regno == mips_regnum (gdbarch)->config5)
+ is_fp = 1;
else
is_fp = 0;
+ /* Vector registers are optional but overlap fp registers */
+ if (regno == mips_regnum (gdbarch)->msa_csr)
+ is_vec = 1;
+ else if (regno == mips_regnum (gdbarch)->msa_ir)
+ is_vec = 1;
+ else
+ is_vec = 0;
+
/* DSP registers are optional and not a part of any set. */
have_dsp = mips_regnum (gdbarch)->dspctl != -1;
if (!have_dsp)
@@ -248,7 +276,7 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
if (tid == 0)
tid = ptid_get_pid (inferior_ptid);
- if (regno == -1 || (!is_fp && !is_dsp))
+ if (regno == -1 || (!is_fp && !is_dsp && !is_vec))
{
mips64_elf_gregset_t regs;
@@ -266,23 +294,160 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
(const mips64_elf_gregset_t *) &regs);
}
- if (regno == -1 || is_fp)
+ /* Set the default value of the Config5 register. */
+ if (mips_regnum (gdbarch)->config5 >= 0)
+ {
+ unsigned int config5_default = 0;
+ regcache_raw_supply (regcache, mips_regnum (gdbarch)->config5,
+ &config5_default);
+ }
+
+ if (is_fp || is_vec)
{
- mips64_elf_fpregset_t fp_regs;
+ const struct mips_regnum *rn = mips_regnum (gdbarch);
+ int float_regnum = rn->fp0;
- if (ptrace (PTRACE_GETFPREGS, tid, 0L,
- (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+ /* Try the MSA regset first if vector registers are desired */
+ if (rn->msa_csr != -1
+ && have_ptrace_getregset && have_ptrace_getregset_msa)
{
- if (errno == EIO)
+ unsigned char w_regs[34][16];
+ unsigned char buf[16];
+ struct iovec iovec;
+ int ret;
+
+ iovec.iov_base = &w_regs;
+ iovec.iov_len = sizeof (w_regs);
+
+ ret = ptrace (PTRACE_GETREGSET, tid, NT_MIPS_MSA, &iovec);
+ if (ret < 0)
{
- have_ptrace_regsets = 0;
- return;
+ if (errno == EIO)
+ have_ptrace_getregset = 0;
+ else if (errno == EINVAL)
+ have_ptrace_getregset_msa = 0;
+ else
+ perror_with_name (_("Unable to fetch FP/MSA registers."));
+ }
+ else
+ {
+ /* full vector including float */
+ if (big_endian)
+ for (regi = 0; regi < 32; regi++)
+ {
+ /* swap 64-bit halves, so it's a single word */
+ memcpy(buf, w_regs[regi] + 8, 8);
+ memcpy(buf + 8, w_regs[regi], 8);
+ regcache_raw_supply (regcache, float_regnum + regi, buf);
+ }
+ else
+ for (regi = 0; regi < 32; regi++)
+ regcache_raw_supply (regcache, float_regnum + regi,
+ (char *) w_regs[regi]);
+
+ if (iovec.iov_len >= 32*16 + 4)
+ regcache_raw_supply (regcache, rn->fp_implementation_revision,
+ (char *) (w_regs + 32) + 0);
+ if (iovec.iov_len >= 32*16 + 8)
+ regcache_raw_supply (regcache, rn->fp_control_status,
+ (char *) (w_regs + 32) + 4);
+ if (iovec.iov_len >= 32*16 + 12)
+ regcache_raw_supply (regcache, rn->msa_ir,
+ (char *) (w_regs + 32) + 8);
+ if (iovec.iov_len >= 32*16 + 16)
+ regcache_raw_supply (regcache, rn->msa_csr,
+ (char *) (w_regs + 32) + 12);
+ if (iovec.iov_len >= 33*16 + 4)
+ regcache_raw_supply (regcache, rn->config5,
+ (char *) (w_regs + 33) + 0);
+
+ /* we've got fp registers now */
+ is_fp = 0;
+ }
+ }
+
+ /* Try the FP regset next as it may contain Config5 */
+ if (is_fp && have_ptrace_getregset && have_ptrace_getregset_fp)
+ {
+ unsigned char fp_regs[34][8];
+ struct iovec iovec;
+ int ret;
+
+ iovec.iov_base = &fp_regs;
+ iovec.iov_len = sizeof (fp_regs);
+
+ ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec);
+ if (ret < 0)
+ {
+ if (errno == EIO)
+ have_ptrace_getregset = 0;
+ else if (errno == EINVAL)
+ have_ptrace_getregset_fp = 0;
+ else
+ perror_with_name (_("Unable to fetch FP registers."));
+ }
+ else
+ {
+ for (regi = 0; regi < 32; regi++)
+ {
+ if (register_size (gdbarch, float_regnum + regi) == 8)
+ {
+ /* FR = 1
+ copy entire double */
+ regcache_raw_supply (regcache, float_regnum + regi,
+ (char *) fp_regs[regi]);
+ }
+ else if (regi & 1)
+ {
+ /* FR = 0
+ odd single from top of even double */
+ regcache_raw_supply (regcache, float_regnum + regi,
+ (char *) fp_regs[regi - 1] +
+ 4 - 4*big_endian);
+ }
+ else
+ {
+ /* FR = 0
+ even single from bottom of even double */
+ regcache_raw_supply (regcache, float_regnum + regi,
+ (char *) fp_regs[regi] + 4 * big_endian);
+ }
+ }
+
+ if (iovec.iov_len >= 32*8 + 4)
+ regcache_raw_supply (regcache, rn->fp_control_status,
+ (char *) (fp_regs + 32) + 0);
+ if (iovec.iov_len >= 32*8 + 8)
+ regcache_raw_supply (regcache, rn->fp_implementation_revision,
+ (char *) (fp_regs + 32) + 4);
+ if (iovec.iov_len >= 33*8 + 4 && rn->config5 >= 0)
+ regcache_raw_supply (regcache, rn->config5,
+ (char *) (fp_regs + 33) + 0);
+
+ /* we've got fp registers now */
+ is_fp = 0;
}
- perror_with_name (_("Couldn't get FP registers"));
}
- mips64_supply_fpregset (regcache,
- (const mips64_elf_fpregset_t *) &fp_regs);
+ /* Fall back to GETFPREGS. */
+ if (is_fp)
+ {
+ mips64_elf_fpregset_t fp_regs;
+
+ if (ptrace (PTRACE_GETFPREGS, tid, 0L,
+ (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+ {
+ if (errno == EIO)
+ {
+ have_ptrace_regsets = 0;
+ return;
+ }
+ perror_with_name (_("Couldn't get FP registers"));
+ }
+
+ mips64_supply_fpregset (regcache,
+ (const mips64_elf_fpregset_t *) &fp_regs);
+ }
}
if (is_dsp)
@@ -305,11 +470,16 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int is_fp, is_dsp;
+ int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+ int is_fp, is_dsp, is_vec;
int have_dsp;
int regi;
int tid;
+ /* FP registers can be written in several ways.
+ is_fp will be cleared once the registers have been written. */
+ if (regno == -1)
+ is_fp = 1;
if (regno >= mips_regnum (gdbarch)->fp0
&& regno <= mips_regnum (gdbarch)->fp0 + 32)
is_fp = 1;
@@ -317,9 +487,22 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
is_fp = 1;
else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
is_fp = 1;
+ else if (regno == mips_regnum (gdbarch)->config5)
+ is_fp = 1;
else
is_fp = 0;
+ /* Vector registers are optional but overlap fp registers */
+ if (regno >= mips_regnum (gdbarch)->w0
+ && regno <= mips_regnum (gdbarch)->w0 + 32)
+ is_vec = 1;
+ else if (regno == mips_regnum (gdbarch)->msa_csr)
+ is_vec = 1;
+ else if (regno == mips_regnum (gdbarch)->msa_ir)
+ is_vec = 1;
+ else
+ is_vec = 0;
+
/* DSP registers are optional and not a part of any set. */
have_dsp = mips_regnum (gdbarch)->dspctl != -1;
if (!have_dsp)
@@ -336,7 +519,7 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
if (tid == 0)
tid = ptid_get_pid (inferior_ptid);
- if (regno == -1 || (!is_fp && !is_dsp))
+ if (regno == -1 || (!is_fp && !is_dsp && !is_vec))
{
mips64_elf_gregset_t regs;
@@ -349,19 +532,169 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
perror_with_name (_("Couldn't set registers"));
}
- if (regno == -1 || is_fp)
+ if (is_fp || is_vec)
{
- mips64_elf_fpregset_t fp_regs;
+ const struct mips_regnum *rn = mips_regnum (gdbarch);
+ int float_regnum = rn->fp0;
+
+ /* Try the MSA regset first if vector registers are desired */
+ if (rn->msa_csr != -1
+ && have_ptrace_getregset && have_ptrace_getregset_msa)
+ {
+ unsigned char w_regs[34][16];
+ unsigned char buf[16];
+ struct iovec iovec;
+ int ret;
+
+ iovec.iov_base = &w_regs;
+ iovec.iov_len = sizeof (w_regs);
- if (ptrace (PTRACE_GETFPREGS, tid, 0L,
- (PTRACE_TYPE_ARG3) &fp_regs) == -1)
- perror_with_name (_("Couldn't get FP registers"));
+ ret = ptrace (PTRACE_GETREGSET, tid, NT_MIPS_MSA, &iovec);
+ if (ret < 0)
+ {
+ if (errno == EIO)
+ have_ptrace_getregset = 0;
+ else if (errno == EINVAL)
+ have_ptrace_getregset_msa = 0;
+ else
+ perror_with_name (_("Unable to fetch FP/MSA registers."));
+ }
+ else
+ {
+ /* full vector including float */
+ if (big_endian)
+ for (regi = 0; regi < 32; regi++)
+ {
+ regcache_raw_collect (regcache, float_regnum + regi, buf);
+ /* swap 64-bit halves, as it's a single word */
+ memcpy(w_regs[regi], buf + 8, 8);
+ memcpy(w_regs[regi] + 8, buf, 8);
+ }
+ else
+ for (regi = 0; regi < 32; regi++)
+ regcache_raw_collect (regcache, float_regnum + regi,
+ (char *) w_regs[regi]);
+
+ regcache_raw_collect (regcache, rn->fp_implementation_revision,
+ (char *) (w_regs + 32) + 0);
+ regcache_raw_collect (regcache, rn->fp_control_status,
+ (char *) (w_regs + 32) + 4);
+ regcache_raw_collect (regcache, rn->msa_ir,
+ (char *) (w_regs + 32) + 8);
+ regcache_raw_collect (regcache, rn->msa_csr,
+ (char *) (w_regs + 32) + 12);
+ regcache_raw_collect (regcache, rn->config5,
+ (char *) (w_regs + 33) + 0);
+
+ /* don't modify iovec length from amount of data returned */
+ ret = ptrace (PTRACE_SETREGSET, tid, NT_MIPS_MSA, &iovec);
+ if (ret < 0)
+ {
+ if (errno == EIO)
+ have_ptrace_getregset = 0;
+ if (errno == EINVAL)
+ have_ptrace_getregset_msa = 0;
+ else
+ perror_with_name (_("Unable to store FP/MSA registers."));
+ }
+ else
+ {
+ /* we've written fp registers now */
+ is_fp = 0;
+ }
+ }
+ }
+
+ /* Try the FP regset next as it may contain Config5 */
+ if (is_fp && have_ptrace_getregset && have_ptrace_getregset_fp)
+ {
+ unsigned char fp_regs[34][8];
+ struct iovec iovec;
+ int ret;
- mips64_fill_fpregset (regcache, &fp_regs, regno);
+ iovec.iov_base = &fp_regs;
+ iovec.iov_len = sizeof (fp_regs);
+
+ ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec);
+ if (ret < 0)
+ {
+ if (errno == EIO)
+ have_ptrace_getregset = 0;
+ else if (errno == EINVAL)
+ have_ptrace_getregset_fp = 0;
+ else
+ perror_with_name (_("Unable to fetch FP registers."));
+ }
+ else
+ {
+ for (regi = 0; regi < 32; regi++)
+ {
+ if (register_size (gdbarch, float_regnum + regi) == 8)
+ {
+ /* FR = 1
+ copy entire double */
+ regcache_raw_collect (regcache, float_regnum + regi,
+ (char *) fp_regs[regi]);
+ }
+ else if (regi & 1)
+ {
+ /* FR = 0
+ odd single from top of even double */
+ regcache_raw_collect (regcache, float_regnum + regi,
+ (char *) fp_regs[regi - 1] +
+ 4 - 4*big_endian);
+ }
+ else
+ {
+ /* FR = 0
+ even single from bottom of even double */
+ regcache_raw_collect (regcache, float_regnum + regi,
+ (char *) fp_regs[regi] + 4 * big_endian);
+ }
+ }
+
+ regcache_raw_collect (regcache, rn->fp_control_status,
+ (char *) (fp_regs + 32) + 0);
+ regcache_raw_collect (regcache, rn->fp_implementation_revision,
+ (char *) (fp_regs + 32) + 4);
+ if (rn->config5 >= 0)
+ regcache_raw_collect (regcache, rn->config5,
+ (char *) (fp_regs + 33) + 0);
+
+ /* don't modify iovec length from amount of data returned */
+ ret = ptrace (PTRACE_SETREGSET, tid, NT_FPREGSET, &iovec);
+ if (ret < 0)
+ {
+ if (errno == EIO)
+ have_ptrace_getregset = 0;
+ else if (errno == EINVAL)
+ have_ptrace_getregset_fp = 0;
+ else
+ perror_with_name (_("Unable to store FP/MSA registers."));
+ }
+ else
+ {
+ /* we've got fp registers now */
+ is_fp = 0;
+ }
+ }
+ }
- if (ptrace (PTRACE_SETFPREGS, tid, 0L,
- (PTRACE_TYPE_ARG3) &fp_regs) == -1)
- perror_with_name (_("Couldn't set FP registers"));
+ /* Fall back to SETFPREGS. */
+ if (is_fp)
+ {
+ mips64_elf_fpregset_t fp_regs;
+
+ if (ptrace (PTRACE_GETFPREGS, tid, 0L,
+ (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+ perror_with_name (_("Couldn't get FP registers"));
+
+ mips64_fill_fpregset (regcache, &fp_regs, regno);
+
+ if (ptrace (PTRACE_SETFPREGS, tid, 0L,
+ (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+ perror_with_name (_("Couldn't set FP registers"));
+ }
}
if (is_dsp)
@@ -425,7 +758,65 @@ mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
static const struct target_desc *
mips_linux_read_description (struct target_ops *ops)
{
+ const struct target_desc *tdescs[2][2] =
+ {
+ /* have_fpu64 = 0 have_fpu64 = 1 */
+ { tdesc_mips_linux, tdesc_mips_fpu64_linux }, /* have_dsp = 0 */
+ { tdesc_mips_dsp_linux, tdesc_mips_fpu64_dsp_linux }, /* have_dsp = 1 */
+ };
+
static int have_dsp = -1;
+ static int have_fpu64 = -1;
+ static int have_msa = -1;
+
+ if (have_fpu64 < 0)
+ {
+ int tid;
+ long fir;
+
+ tid = ptid_get_lwp (inferior_ptid);
+ if (tid == 0)
+ tid = ptid_get_pid (inferior_ptid);
+
+ /* Try peeking at FIR.F64 bit */
+ errno = 0;
+ fir = ptrace (PTRACE_PEEKUSER, tid, FPC_EIR, 0);
+ switch (errno)
+ {
+ case 0:
+ have_fpu64 = !!(fir & FIR_F64);
+ break;
+ case EIO:
+ have_fpu64 = 0;
+ have_msa = 0;
+ break;
+ default:
+ perror_with_name ("ptrace");
+ break;
+ }
+ }
+
+ /* Check for MSA, which requires FR=1 */
+ if (have_msa < 0)
+ {
+ int tid;
+ int res;
+ uint32_t regs[32*4 + 8];
+ struct iovec iov;
+
+ tid = ptid_get_lwp (inferior_ptid);
+ if (tid == 0)
+ tid = ptid_get_pid (inferior_ptid);
+
+ /* this'd probably be better */
+ //have_msa = (getauxval(AT_HWCAP) & 0x2) != 0;
+
+ /* Test MSAIR */
+ iov.iov_base = regs;
+ iov.iov_len = sizeof(regs);
+ res = ptrace (PTRACE_GETREGSET, tid, NT_MIPS_MSA, &iov);
+ have_msa = (res >= 0) && regs[32*4 + 0];
+ }
if (have_dsp < 0)
{
@@ -454,9 +845,11 @@ mips_linux_read_description (struct target_ops *ops)
/* Report that target registers are a size we know for sure
that we can get from ptrace. */
if (_MIPS_SIM == _ABIO32)
- return have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
+ return have_msa ? tdesc_mips_msa_linux
+ : tdescs[have_dsp][have_fpu64];
else
- return have_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
+ return have_msa ? tdesc_mips64_msa_linux :
+ have_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
}
/* -1 if the kernel and/or CPU do not support watch registers.
@@ -811,6 +1204,10 @@ triggers a breakpoint or watchpoint."),
/* Initialize the standard target descriptions. */
initialize_tdesc_mips_linux ();
initialize_tdesc_mips_dsp_linux ();
+ initialize_tdesc_mips_fpu64_linux ();
+ initialize_tdesc_mips_fpu64_dsp_linux ();
+ initialize_tdesc_mips_msa_linux ();
initialize_tdesc_mips64_linux ();
initialize_tdesc_mips64_dsp_linux ();
+ initialize_tdesc_mips64_msa_linux ();
}
diff --git a/gdb-7.11/gdb/mips-linux-tdep.c b/gdb-7.11/gdb/mips-linux-tdep.c
index 8dc0566db..3912d9cfd 100644
--- a/gdb-7.11/gdb/mips-linux-tdep.c
+++ b/gdb-7.11/gdb/mips-linux-tdep.c
@@ -75,7 +75,7 @@ enum
MIPS_LINUX_SIGRTMIN = 32,
MIPS_LINUX_SIGRT64 = 64,
- MIPS_LINUX_SIGRTMAX = 127,
+ MIPS_LINUX_SIGRTMAX = 128,
};
/* Figure out where the longjmp will land.
@@ -141,8 +141,9 @@ mips_supply_gregset (struct regcache *regcache,
for (regi = EF_REG0 + 1; regi <= EF_REG31; regi++)
supply_32bit_reg (regcache, regi - EF_REG0, regp + regi);
- if (mips_linux_restart_reg_p (gdbarch))
- supply_32bit_reg (regcache, MIPS_RESTART_REGNUM, regp + EF_REG0);
+ if (mips_regnum (gdbarch)->linux_restart >= 0)
+ supply_32bit_reg (regcache, mips_regnum (gdbarch)->linux_restart,
+ regp + EF_REG0);
supply_32bit_reg (regcache, mips_regnum (gdbarch)->lo, regp + EF_LO);
supply_32bit_reg (regcache, mips_regnum (gdbarch)->hi, regp + EF_HI);
@@ -191,7 +192,9 @@ mips_fill_gregset (const struct regcache *regcache,
mips_fill_gregset (regcache, gregsetp, mips_regnum (gdbarch)->badvaddr);
mips_fill_gregset (regcache, gregsetp, MIPS_PS_REGNUM);
mips_fill_gregset (regcache, gregsetp, mips_regnum (gdbarch)->cause);
- mips_fill_gregset (regcache, gregsetp, MIPS_RESTART_REGNUM);
+ if (mips_regnum (gdbarch)->linux_restart >= 0)
+ mips_fill_gregset (regcache, gregsetp,
+ mips_regnum (gdbarch)->linux_restart);
return;
}
@@ -214,8 +217,7 @@ mips_fill_gregset (const struct regcache *regcache,
regaddr = EF_CP0_STATUS;
else if (regno == mips_regnum (gdbarch)->cause)
regaddr = EF_CP0_CAUSE;
- else if (mips_linux_restart_reg_p (gdbarch)
- && regno == MIPS_RESTART_REGNUM)
+ else if (regno == mips_regnum (gdbarch)->linux_restart)
regaddr = EF_REG0;
else
regaddr = -1;
@@ -388,8 +390,8 @@ mips64_supply_gregset (struct regcache *regcache,
supply_64bit_reg (regcache, regi - MIPS64_EF_REG0,
(const gdb_byte *) (regp + regi));
- if (mips_linux_restart_reg_p (gdbarch))
- supply_64bit_reg (regcache, MIPS_RESTART_REGNUM,
+ if (mips_regnum (gdbarch)->linux_restart >= 0)
+ supply_64bit_reg (regcache, mips_regnum (gdbarch)->linux_restart,
(const gdb_byte *) (regp + MIPS64_EF_REG0));
supply_64bit_reg (regcache, mips_regnum (gdbarch)->lo,
@@ -444,7 +446,8 @@ mips64_fill_gregset (const struct regcache *regcache,
mips_regnum (gdbarch)->badvaddr);
mips64_fill_gregset (regcache, gregsetp, MIPS_PS_REGNUM);
mips64_fill_gregset (regcache, gregsetp, mips_regnum (gdbarch)->cause);
- mips64_fill_gregset (regcache, gregsetp, MIPS_RESTART_REGNUM);
+ mips64_fill_gregset (regcache, gregsetp,
+ mips_regnum (gdbarch)->linux_restart);
return;
}
@@ -462,8 +465,7 @@ mips64_fill_gregset (const struct regcache *regcache,
regaddr = MIPS64_EF_CP0_STATUS;
else if (regno == mips_regnum (gdbarch)->cause)
regaddr = MIPS64_EF_CP0_CAUSE;
- else if (mips_linux_restart_reg_p (gdbarch)
- && regno == MIPS_RESTART_REGNUM)
+ else if (regno == mips_regnum (gdbarch)->linux_restart)
regaddr = MIPS64_EF_REG0;
else
regaddr = -1;
@@ -962,6 +964,111 @@ static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
};
/* *INDENT-OFF* */
+/* The unwinder for extended context in signal frames. Extended context looks
+ like this, at the beginning of a larger struct:
+
+ struct extcontext {
+ unsigned int magic;
+ unsigned int size;
+ };
+
+ struct msa_extcontext {
+ struct extcontext ext;
+ unsigned long long wr[32];
+ unsigned int csr;
+ }; */
+/* *INDENT-ON* */
+
+#define EXTCONTEXT_MAGIC_OFFSET (0 * 4)
+#define EXTCONTEXT_SIZE_OFFSET (1 * 4)
+#define EXTCONTEXT_SIZE (2 * 4)
+
+#define END_EXTCONTEXT_MAGIC 0x78454e44 /* xEND */
+#define MSA_EXTCONTEXT_MAGIC 0x784d5341 /* xMSA */
+
+#define MSA_EXTCONTEXT_WR_OFFSET EXTCONTEXT_SIZE
+#define MSA_EXTCONTEXT_WREG_SIZE 8
+#define MSA_EXTCONTEXT_CSR_OFFSET (EXTCONTEXT_SIZE \
+ + 32 * MSA_EXTCONTEXT_WREG_SIZE)
+
+static void
+mips_linux_msa_extcontext_init (struct frame_info *this_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR extcontext_base)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ const struct mips_regnum *regs = mips_regnum (gdbarch);
+ unsigned int i;
+
+ if (regs->w0 != -1)
+ for (i = 0; i < 32; ++i)
+ trad_frame_set_reg_addr (this_cache, regs->w0 + i
+ + gdbarch_num_regs (gdbarch),
+ extcontext_base + MSA_EXTCONTEXT_WR_OFFSET
+ + i * MSA_EXTCONTEXT_WREG_SIZE);
+ if (regs->msa_csr != -1)
+ trad_frame_set_reg_addr (this_cache, regs->msa_csr,
+ extcontext_base + MSA_EXTCONTEXT_CSR_OFFSET);
+}
+
+static void
+mips_linux_extcontext_init (struct frame_info *this_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR extcontext_base)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[4];
+ uint32_t magic, size;
+ unsigned int i;
+
+ /* Limit the extended context blocks read */
+ for (i = 0; i < 10; ++i)
+ {
+ /* Read magic. */
+ if (!safe_frame_unwind_memory (this_frame,
+ extcontext_base + EXTCONTEXT_MAGIC_OFFSET,
+ buf, 4))
+ break;
+ magic = extract_unsigned_integer (buf, 4, byte_order);
+ /* Stop at the END magic. */
+ if (magic == END_EXTCONTEXT_MAGIC)
+ break;
+ /* Read size of extended context. */
+ if (!safe_frame_unwind_memory (this_frame,
+ extcontext_base + EXTCONTEXT_SIZE_OFFSET,
+ buf, 4))
+ break;
+ size = extract_unsigned_integer (buf, 4, byte_order);
+ /* We don't want to loop forever or fly off into the distance
+ * if something went terribly wrong. */
+ if (!size || size > 4096)
+ {
+ warning (_("%s: bad extended context size 0x%x"),
+ __func__, size);
+ break;
+ }
+ /* The rest depends on what type of context it is. */
+ switch (magic)
+ {
+ case MSA_EXTCONTEXT_MAGIC:
+ mips_linux_msa_extcontext_init (this_frame, this_cache,
+ extcontext_base);
+ break;
+
+ default:
+ if (gdbarch_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "%s: unrecognised extcontext magic = 0x%08x\n",
+ __func__, magic);
+ break;
+ }
+ /* And skip to the next block of extended context. */
+ extcontext_base += size;
+ }
+}
+
+/* *INDENT-OFF* */
/* The unwinder for o32 signal frames. The legacy structures look
like this:
@@ -970,6 +1077,7 @@ static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
u32 sf_code[2]; [signal trampoline or fill]
struct sigcontext sf_sc;
sigset_t sf_mask;
+ struct extcontext sf_extcontext[0];
};
Pre-2.6.12 sigcontext:
@@ -1035,22 +1143,36 @@ static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
[Alignment hole of four bytes]
struct sigcontext uc_mcontext;
sigset_t uc_sigmask;
+ struct extcontext uc_extcontext[0];
}; */
/* *INDENT-ON* */
+#define SIGCONTEXT_SIZE (74 * 8)
+#define SIGSET_T_SIZE (2 * 8)
+
#define SIGFRAME_SIGCONTEXT_OFFSET (6 * 4)
+#define SIGFRAME_EXTCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \
+ + SIGCONTEXT_SIZE \
+ + SIGSET_T_SIZE)
#define RTSIGFRAME_SIGINFO_SIZE 128
#define STACK_T_SIZE (3 * 4)
#define UCONTEXT_SIGCONTEXT_OFFSET (2 * 4 + STACK_T_SIZE + 4)
+#define UCONTEXT_EXTCONTEXT_OFFSET (UCONTEXT_SIGCONTEXT_OFFSET \
+ + SIGCONTEXT_SIZE \
+ + SIGSET_T_SIZE)
#define RTSIGFRAME_SIGCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \
+ RTSIGFRAME_SIGINFO_SIZE \
+ UCONTEXT_SIGCONTEXT_OFFSET)
+#define RTSIGFRAME_EXTCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \
+ + RTSIGFRAME_SIGINFO_SIZE \
+ + UCONTEXT_EXTCONTEXT_OFFSET)
#define SIGCONTEXT_PC (1 * 8)
#define SIGCONTEXT_REGS (2 * 8)
#define SIGCONTEXT_FPREGS (34 * 8)
#define SIGCONTEXT_FPCSR (66 * 8 + 4)
+#define SIGCONTEXT_USEDMATH (67 * 8 + 4)
#define SIGCONTEXT_DSPCTL (68 * 8 + 0)
#define SIGCONTEXT_HI (69 * 8)
#define SIGCONTEXT_LO (70 * 8)
@@ -1065,6 +1187,19 @@ static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
#define SIGCONTEXT_REG_SIZE 8
+#ifndef USED_FP
+#define USED_FP (1 << 0)
+#endif
+#ifndef USED_FR1
+#define USED_FR1 (1 << 1)
+#endif
+#ifndef USED_HYBRID_FPRS
+#define USED_HYBRID_FPRS (1 << 2)
+#endif
+#ifndef USED_EXTCONTEXT
+#define USED_EXTCONTEXT (1 << 3)
+#endif
+
static void
mips_linux_o32_sigframe_init (const struct tramp_frame *self,
struct frame_info *this_frame,
@@ -1074,9 +1209,12 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
struct gdbarch *gdbarch = get_frame_arch (this_frame);
int ireg;
CORE_ADDR frame_sp = get_frame_sp (this_frame);
- CORE_ADDR sigcontext_base;
+ CORE_ADDR sigcontext_base, extcontext_base;
const struct mips_regnum *regs = mips_regnum (gdbarch);
CORE_ADDR regs_base;
+ gdb_byte buf[4];
+ uint32_t used_math;
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
if (self == &mips_linux_o32_sigframe
|| self == &micromips_linux_o32_sigframe)
@@ -1094,9 +1232,9 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
else
regs_base = sigcontext_base;
- if (mips_linux_restart_reg_p (gdbarch))
+ if (mips_regnum (gdbarch)->linux_restart >= 0)
trad_frame_set_reg_addr (this_cache,
- (MIPS_RESTART_REGNUM
+ (mips_regnum (gdbarch)->linux_restart
+ gdbarch_num_regs (gdbarch)),
regs_base + SIGCONTEXT_REGS);
@@ -1107,6 +1245,14 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
(regs_base + SIGCONTEXT_REGS
+ ireg * SIGCONTEXT_REG_SIZE));
+ /* Read the used_math field. */
+ if (safe_frame_unwind_memory (this_frame,
+ sigcontext_base + SIGCONTEXT_USEDMATH,
+ buf, 4))
+ used_math = extract_unsigned_integer (buf, 4, gdbarch_byte_order (gdbarch));
+ else
+ used_math = 0;
+
/* The way that floating point registers are saved, unfortunately,
depends on the architecture the kernel is built for. For the r3000 and
tx39, four bytes of each register are at the beginning of each of the
@@ -1115,8 +1261,27 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
and the high bits are the odd-numbered register. Assume the latter
layout, since we can't tell, and it's much more common. Which bits are
the "high" bits depends on endianness. */
+ /* FIXME if !used_math, should probably say unavailable or something */
for (ireg = 0; ireg < 32; ireg++)
- if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (ireg & 1))
+#if 0
+ trad_frame_set_reg_addr (this_cache, ireg + regs->fp0,
+ (sigcontext_base + SIGCONTEXT_FPREGS
+ + (ireg & ~1) * SIGCONTEXT_REG_SIZE));
+#else
+ /* FIXME probably should use SR for MIPS64 for more reliability with old
+ * kernels */
+ if (used_math & USED_FR1)
+ {
+ trad_frame_set_reg_addr (this_cache,
+ ireg + regs->fp0,
+ (sigcontext_base + SIGCONTEXT_FPREGS
+ + ireg * SIGCONTEXT_REG_SIZE));
+ trad_frame_set_reg_addr (this_cache,
+ ireg + regs->fp0 + gdbarch_num_regs (gdbarch),
+ (sigcontext_base + SIGCONTEXT_FPREGS
+ + ireg * SIGCONTEXT_REG_SIZE));
+ }
+ else if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (ireg & 1))
trad_frame_set_reg_addr (this_cache,
ireg + regs->fp0 + gdbarch_num_regs (gdbarch),
(sigcontext_base + SIGCONTEXT_FPREGS + 4
@@ -1126,6 +1291,7 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
ireg + regs->fp0 + gdbarch_num_regs (gdbarch),
(sigcontext_base + SIGCONTEXT_FPREGS
+ (ireg & ~1) * SIGCONTEXT_REG_SIZE));
+#endif
trad_frame_set_reg_addr (this_cache,
regs->pc + gdbarch_num_regs (gdbarch),
@@ -1136,6 +1302,20 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
+ gdbarch_num_regs (gdbarch)),
sigcontext_base + SIGCONTEXT_FPCSR);
+ if (used_math & USED_EXTCONTEXT)
+ {
+ /* Extended context is present,
+ find base of extended context list. */
+ if (self == &mips_linux_o32_sigframe)
+ extcontext_base = frame_sp + SIGFRAME_EXTCONTEXT_OFFSET;
+ else
+ extcontext_base = frame_sp + RTSIGFRAME_EXTCONTEXT_OFFSET;
+
+ /* And read the blocks of extended context. */
+ mips_linux_extcontext_init (this_frame, this_cache,
+ extcontext_base);
+ }
+
if (regs->dspctl != -1)
trad_frame_set_reg_addr (this_cache,
regs->dspctl + gdbarch_num_regs (gdbarch),
@@ -1286,9 +1466,9 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self,
else
sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET;
- if (mips_linux_restart_reg_p (gdbarch))
+ if (mips_regnum (gdbarch)->linux_restart >= 0)
trad_frame_set_reg_addr (this_cache,
- (MIPS_RESTART_REGNUM
+ (mips_regnum (gdbarch)->linux_restart
+ gdbarch_num_regs (gdbarch)),
sigcontext_base + N64_SIGCONTEXT_REGS);
@@ -1387,23 +1567,9 @@ mips_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
mips_write_pc (regcache, pc);
/* Clear the syscall restart flag. */
- if (mips_linux_restart_reg_p (gdbarch))
- regcache_cooked_write_unsigned (regcache, MIPS_RESTART_REGNUM, 0);
-}
-
-/* Return 1 if MIPS_RESTART_REGNUM is usable. */
-
-int
-mips_linux_restart_reg_p (struct gdbarch *gdbarch)
-{
- /* If we do not have a target description with registers, then
- MIPS_RESTART_REGNUM will not be included in the register set. */
- if (!tdesc_has_registers (gdbarch_target_desc (gdbarch)))
- return 0;
-
- /* If we do, then MIPS_RESTART_REGNUM is safe to check; it will
- either be GPR-sized or missing. */
- return register_size (gdbarch, MIPS_RESTART_REGNUM) > 0;
+ if (mips_regnum (gdbarch)->linux_restart >= 0)
+ regcache_cooked_write_unsigned (regcache,
+ mips_regnum (gdbarch)->linux_restart, 0);
}
/* When FRAME is at a syscall instruction, return the PC of the next
@@ -1630,9 +1796,11 @@ mips_gdb_signal_from_target (struct gdbarch *gdbarch, int signal)
else if (offset < 32)
return (enum gdb_signal) (offset - 1
+ (int) GDB_SIGNAL_REALTIME_33);
- else
+ else if (offset < 128)
return (enum gdb_signal) (offset - 32
+ (int) GDB_SIGNAL_REALTIME_64);
+ else
+ return GDB_SIGNAL_REALTIME_128;
}
return linux_gdb_signal_from_target (gdbarch, signal);
@@ -1646,8 +1814,6 @@ mips_linux_init_abi (struct gdbarch_info info,
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum mips_abi abi = mips_abi (gdbarch);
- struct tdesc_arch_data *tdesc_data
- = (struct tdesc_arch_data *) info.tdep_info;
linux_init_abi (info, gdbarch);
@@ -1738,23 +1904,31 @@ mips_linux_init_abi (struct gdbarch_info info,
tdep->syscall_next_pc = mips_linux_syscall_next_pc;
- if (tdesc_data)
+ if (info.tdep_info->tdesc_data)
{
const struct tdesc_feature *feature;
- /* If we have target-described registers, then we can safely
- reserve a number for MIPS_RESTART_REGNUM (whether it is
- described or not). */
- gdb_assert (gdbarch_num_regs (gdbarch) <= MIPS_RESTART_REGNUM);
- set_gdbarch_num_regs (gdbarch, MIPS_RESTART_REGNUM + 1);
- set_gdbarch_num_pseudo_regs (gdbarch, MIPS_RESTART_REGNUM + 1);
-
- /* If it's present, then assign it to the reserved number. */
+ /* If "restart" is present in the target register description,
+ then assign it to a new register number. */
feature = tdesc_find_feature (info.target_desc,
"org.gnu.gdb.mips.linux");
- if (feature != NULL)
- tdesc_numbered_register (feature, tdesc_data, MIPS_RESTART_REGNUM,
- "restart");
+ if (feature != NULL
+ && tdesc_unnumbered_register (feature, "restart"))
+ {
+ int restart_regnum;
+ /* We cast away const'ness in order to set linux_restart.
+ */
+ struct mips_regnum *regnum =
+ (struct mips_regnum *)mips_regnum (gdbarch);
+
+ restart_regnum = gdbarch_num_regs (gdbarch);
+ regnum->linux_restart = restart_regnum;
+ set_gdbarch_num_regs (gdbarch, restart_regnum + 1);
+ set_gdbarch_num_pseudo_regs (gdbarch, restart_regnum + 1);
+
+ tdesc_numbered_register (feature, info.tdep_info->tdesc_data,
+ restart_regnum, "restart");
+ }
}
}
diff --git a/gdb-7.11/gdb/mips-linux-tdep.h b/gdb-7.11/gdb/mips-linux-tdep.h
index e8a69fb76..4537fcd65 100644
--- a/gdb-7.11/gdb/mips-linux-tdep.h
+++ b/gdb-7.11/gdb/mips-linux-tdep.h
@@ -95,13 +95,3 @@ void mips64_supply_fpregset (struct regcache *,
const mips64_elf_fpregset_t *);
void mips64_fill_fpregset (const struct regcache *,
mips64_elf_fpregset_t *, int);
-
-enum {
- /* The Linux kernel stores an error code from any interrupted
- syscall in a "register" (in $0's save slot). */
- MIPS_RESTART_REGNUM = 79
-};
-
-/* Return 1 if MIPS_RESTART_REGNUM is usable. */
-
-int mips_linux_restart_reg_p (struct gdbarch *gdbarch);
diff --git a/gdb-7.11/gdb/mips-tdep.c b/gdb-7.11/gdb/mips-tdep.c
index 63c1560f5..dd9c586bd 100644
--- a/gdb-7.11/gdb/mips-tdep.c
+++ b/gdb-7.11/gdb/mips-tdep.c
@@ -76,10 +76,16 @@ static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
static void mips_print_float_info (struct gdbarch *, struct ui_file *,
struct frame_info *, const char *);
+static int mips_read_fp_register_single (struct frame_info *, int,
+ gdb_byte *);
/* A useful bit in the CP0 status register (MIPS_PS_REGNUM). */
/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */
#define ST0_FR (1 << 26)
+/* A useful bit in the CP0 Config5 register.
+ This bit is set in hybrid 64-bit FPR mode. */
+#define CONF5_FRE (1 << 8)
+
/* The sizes of floating point registers. */
enum
@@ -219,6 +225,16 @@ mips_float_register_p (struct gdbarch *gdbarch, int regnum)
&& rawnum < mips_regnum (gdbarch)->fp0 + 32);
}
+static int
+mips_vector_register_p (struct gdbarch *gdbarch, int regnum)
+{
+ int rawnum = regnum % gdbarch_num_regs (gdbarch);
+
+ return (mips_regnum (gdbarch)->w0 >= 0
+ && rawnum >= mips_regnum (gdbarch)->w0
+ && rawnum < mips_regnum (gdbarch)->w0 + 32);
+}
+
#define MIPS_EABI(gdbarch) (gdbarch_tdep (gdbarch)->mips_abi \
== MIPS_ABI_EABI32 \
|| gdbarch_tdep (gdbarch)->mips_abi == MIPS_ABI_EABI64)
@@ -274,6 +290,108 @@ mips_abi_regsize (struct gdbarch *gdbarch)
}
}
+/* Determine the current floating-point register size and update our
+ architecture data accordingly. Return one if the size has changed
+ and a new architecture has been selected, zero otherwise.
+
+ For MIPS1, MIPS2 and MIPS32 rev. 1 processors the size is hardwired
+ to 32 bits. For MIPS3 and other 64-bit processors up to the MIPS64
+ rev. 1 ISA the size is determined by the CP0 Status register's bit
+ FR. If this bit is 1, then the size is 64 bits. If it is 0, then
+ the FPU operates in the compatibility mode and the size is 32 bits.
+
+ From MIPS32 and MIPS64 rev. 2 ISAs up the size is implementation
+ specific and reported by the CP1 FIR register's bit F64. If this
+ bit is 0, then the size is hardwired to 32 bits. If this bit is 1,
+ then the size is determined by the CP0 Status register's bit FR as
+ described above. Unfortunately we may not have access to the CP0
+ registers needed to determine whether the ISA implemented is MIPS32
+ or MIPS64 rev. 2 or higher.
+
+ We currently cannot handle the 64-bit floating-point register size
+ on MIPS32 rev. 2 and higher ISA processors though as no target
+ provides access to upper halves of such registers. Therefore we
+ hardcode the size to 32 bits for any 32-bit processors.
+
+ As the CP0 Status register's bit FR cannot be modified on processors
+ that do not implement an FPU, backends for operating systems that
+ can emulate the FPU in software should set the size according to the
+ ABI in use and then set fp_register_mode_fixed_p to 1 to prevent
+ further updates. */
+
+static int
+mips_set_float_regsize (struct gdbarch *gdbarch, struct regcache *regcache)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct gdbarch_tdep_info tdep_info = { NULL };
+ struct gdbarch_info info;
+ enum mips_fpu_mode fp_mode;
+ enum register_status status;
+ ULONGEST sr, config5;
+
+ if (tdep->fp_register_mode_fixed_p)
+ return 0;
+
+ status = regcache_raw_read_unsigned (regcache, MIPS_PS_REGNUM, &sr);
+ if (status == REG_VALID)
+ fp_mode = (sr & ST0_FR) ? MIPS_FPU_64 : MIPS_FPU_32;
+ else
+ fp_mode = mips_isa_regsize (gdbarch) == 8 ? MIPS_FPU_64 : MIPS_FPU_32;
+
+ if (fp_mode == MIPS_FPU_64 && mips_regnum (gdbarch)->config5 >= 0)
+ {
+ /* Find out if FRE is set */
+ status = regcache_raw_read_unsigned (regcache,
+ mips_regnum (gdbarch)->config5,
+ &config5);
+ if (status == REG_VALID && config5 & CONF5_FRE)
+ fp_mode = MIPS_FPU_HYBRID;
+ }
+
+ if (fp_mode == tdep->fp_mode)
+ return 0;
+
+ /* Need a new gdbarch, go get one.
+ Be careful to preserve target description. */
+ gdbarch_info_init (&info);
+#if 0
+ target_clear_description ();
+ target_find_description ();
+#endif
+ info.target_desc = target_current_description ();
+ info.tdep_info = &tdep_info;
+ info.tdep_info->fp_mode = fp_mode;
+ gdbarch_update_p (info);
+
+ return 1;
+}
+
+/* Return the currently configured floating-point register size. */
+
+static int
+mips_float_regsize (struct gdbarch *gdbarch)
+{
+ switch (gdbarch_tdep (gdbarch)->fp_mode)
+ {
+ case MIPS_FPU_32:
+ return 4;
+ case MIPS_FPU_64:
+ case MIPS_FPU_HYBRID:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+/* Return whether the FPU is currently in hybrid 64-bit mode (where odd singles
+ are found in the top half of the 64-bit even FP registers. */
+
+static int
+mips_float_hybrid (struct gdbarch *gdbarch)
+{
+ return gdbarch_tdep (gdbarch)->fp_mode == MIPS_FPU_HYBRID;
+}
+
/* MIPS16/microMIPS function addresses are odd (bit 0 is set). Here
are some functions to handle addresses associated with compressed
code including but not limited to testing, setting, or clearing
@@ -504,32 +622,6 @@ mips_xfer_register (struct gdbarch *gdbarch, struct regcache *regcache,
fprintf_unfiltered (gdb_stdlog, "\n");
}
-/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU
- compatiblity mode. A return value of 1 means that we have
- physical 64-bit registers, but should treat them as 32-bit registers. */
-
-static int
-mips2_fp_compat (struct frame_info *frame)
-{
- struct gdbarch *gdbarch = get_frame_arch (frame);
- /* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
- meaningful. */
- if (register_size (gdbarch, mips_regnum (gdbarch)->fp0) == 4)
- return 0;
-
-#if 0
- /* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
- in all the places we deal with FP registers. PR gdb/413. */
- /* Otherwise check the FR bit in the status register - it controls
- the FP compatiblity mode. If it is clear we are in compatibility
- mode. */
- if ((get_frame_register_unsigned (frame, MIPS_PS_REGNUM) & ST0_FR) == 0)
- return 1;
-#endif
-
- return 0;
-}
-
#define VM_MIN_ADDRESS (CORE_ADDR)0x400000
static CORE_ADDR heuristic_proc_start (struct gdbarch *, CORE_ADDR);
@@ -610,6 +702,8 @@ static const char *
mips_register_name (struct gdbarch *gdbarch, int regno)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ const struct mips_regnum *regnum = mips_regnum (gdbarch);
+
/* GPR names for all ABIs other than n32/n64. */
static char *mips_gpr_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
@@ -626,6 +720,14 @@ mips_register_name (struct gdbarch *gdbarch, int regno)
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
+ /* MSA vector register names. */
+ static const char *const mips_msa_names[] = {
+ "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
+ "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
+ "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
+ "w24", "w25", "w26", "w27", "w28", "w29", "w30", "w31",
+ };
+
enum mips_abi abi = mips_abi (gdbarch);
/* Map [gdbarch_num_regs .. 2*gdbarch_num_regs) onto the raw registers,
@@ -653,6 +755,8 @@ mips_register_name (struct gdbarch *gdbarch, int regno)
else
return mips_gpr_names[rawnum];
}
+ else if (regnum->w0 >= 0 && rawnum >= regnum->w0 && rawnum < regnum->w0 + 32)
+ return mips_msa_names[rawnum - regnum->w0];
else if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
return tdesc_register_name (gdbarch, rawnum);
else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
@@ -680,8 +784,12 @@ mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
int pseudo = regnum / gdbarch_num_regs (gdbarch);
if (reggroup == all_reggroup)
return pseudo;
- vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
- float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
+ vector_p = (TYPE_VECTOR (register_type (gdbarch, regnum)) ||
+ rawnum == mips_regnum (gdbarch)->msa_csr ||
+ rawnum == mips_regnum (gdbarch)->msa_ir);
+ float_p = (mips_float_register_p (gdbarch, rawnum) ||
+ rawnum == mips_regnum (gdbarch)->fp_control_status ||
+ rawnum == mips_regnum (gdbarch)->fp_implementation_revision);
/* FIXME: cagney/2003-04-13: Can't yet use gdbarch_num_regs
(gdbarch), as not all architectures are multi-arch. */
raw_p = rawnum < gdbarch_num_regs (gdbarch);
@@ -734,6 +842,190 @@ mips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
return mips_register_reggroup_p (gdbarch, regnum, reggroup);
}
+/* Describes a part of a raw register, used for constructing cooked registers.
+ */
+
+struct mips_reg_part
+{
+ unsigned int regnum;
+ unsigned char offset;
+ unsigned char size;
+};
+
+/* Get the raw register containing a single precision float.
+ Returns the number of parts (maximum 1) written through loc. */
+
+static unsigned int
+mips_get_fp_single_location (struct gdbarch *gdbarch,
+ unsigned int idx,
+ struct mips_reg_part *loc)
+{
+ int raw_num = mips_regnum (gdbarch)->fp0;
+ int raw_len = register_size (gdbarch, raw_num);
+ enum mips_fpu_mode fp_mode = gdbarch_tdep (gdbarch)->fp_mode;
+ int big_endian, offs;
+
+ /* Only even doubles provided, in pairs of 32-bit registers. */
+ if (raw_len == 4)
+ {
+ /* In 64-bit FP mode, odd singles don't alias even doubles. */
+ if (fp_mode == MIPS_FPU_64 && idx & 1)
+ return 0;
+
+ loc->regnum = raw_num + idx;
+ loc->offset = 0;
+ loc->size = 4;
+ return 1;
+ }
+
+ if (raw_len < 8)
+ return 0;
+
+ /* All doubles provided, potentially at least significant end of vector
+ register. */
+ big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+ offs = big_endian ? (raw_len - 8) : 0;
+
+ loc->size = 4;
+ switch (fp_mode)
+ {
+ case MIPS_FPU_32:
+ case MIPS_FPU_HYBRID:
+ loc->regnum = raw_num + (idx & ~1);
+ loc->offset = offs + 4 * (big_endian ^ (idx & 1));
+ return 1;
+ case MIPS_FPU_64:
+ loc->regnum = raw_num + idx;
+ loc->offset = offs + 4 * big_endian;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Get the raw register part(s) containing a double precision float.
+ Returns the number of parts (maximum 2) written through loc. */
+
+static unsigned int
+mips_get_fp_double_location (struct gdbarch *gdbarch,
+ unsigned int idx,
+ struct mips_reg_part *loc)
+{
+ int raw_num = mips_regnum (gdbarch)->fp0;
+ int raw_len = register_size (gdbarch, raw_num);
+ enum mips_fpu_mode fp_mode = gdbarch_tdep (gdbarch)->fp_mode;
+ int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+
+ /* Only even doubles provided, in pairs of 32-bit registers. */
+ if (raw_len == 4)
+ {
+ /* No odd doubles. */
+ if (idx & 1)
+ return 0;
+
+ /* Even register contains even single, least significant end of double */
+ loc[big_endian].regnum = raw_num + idx;
+ loc[big_endian].offset = 0;
+ loc[big_endian].size = 4;
+ loc[!big_endian].regnum = raw_num + idx + 1;
+ loc[!big_endian].offset = 0;
+ loc[!big_endian].size = 4;
+ return 2;
+ }
+
+ if (raw_len < 8)
+ return 0;
+
+ /* FPU32 doesn't have odd doubles */
+ if (fp_mode == MIPS_FPU_32 && idx & 1)
+ return 0;
+
+ /* All doubles provided, potentially at least significant end of vector
+ register. */
+ loc->regnum = raw_num + idx;
+ loc->offset = big_endian ? (raw_len - 8) : 0;
+ loc->size = 8;
+ return 1;
+}
+
+/* Get the raw register part(s) composing a cooked float register.
+ Returns the number of parts (maximum 3) written through loc. */
+
+static unsigned int
+mips_get_fp_multi_location (struct gdbarch *gdbarch,
+ unsigned int idx,
+ unsigned int cooked_len,
+ struct mips_reg_part *loc)
+{
+ unsigned int parts, total_parts = 0;
+
+ /* The cooked formats supported are:
+ fp32 (len=4): just a single.
+ fp64 (len=8): double (with aliased single).
+ fp96 (len=12): consecutive double and single. */
+ if (cooked_len > 12 || cooked_len < 4 || cooked_len & 0x3)
+ internal_error (__FILE__, __LINE__, _("bad cooked register size"));
+
+ /* Formats containing a distinct double. */
+ if (cooked_len & 8)
+ {
+ parts = mips_get_fp_double_location (gdbarch, idx, loc);
+ if (!parts)
+ return 0;
+ total_parts += parts;
+ loc += parts;
+ }
+
+ /* Formats containing a distinct single. */
+ if (cooked_len & 4)
+ {
+ parts = mips_get_fp_single_location (gdbarch, idx, loc);
+ if (!parts)
+ return 0;
+ total_parts += parts;
+ }
+
+ return total_parts;
+}
+
+/* Read multiple register parts from the register cache into a buffer. */
+
+static enum register_status
+mips_regcache_raw_read_parts (struct regcache *regcache,
+ struct mips_reg_part *loc,
+ unsigned int parts,
+ gdb_byte **buf)
+{
+ enum register_status ret = REG_UNAVAILABLE;
+
+ for (; parts; --parts, ++loc)
+ {
+ ret = regcache_raw_read_part (regcache, loc->regnum, loc->offset,
+ loc->size, *buf);
+ if (ret != REG_VALID)
+ return ret;
+ *buf += loc->size;
+ }
+
+ return ret;
+}
+
+/* Write multiple register parts of the register cache from a buffer. */
+
+static void
+mips_regcache_raw_write_parts (struct regcache *regcache,
+ struct mips_reg_part *loc,
+ unsigned int parts,
+ const gdb_byte **buf)
+{
+ for (; parts; --parts, ++loc)
+ {
+ regcache_raw_write_part (regcache, loc->regnum, loc->offset, loc->size,
+ *buf);
+ *buf += loc->size;
+ }
+}
+
/* Map the symbol table registers which live in the range [1 *
gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw
registers. Take care of alignment and size problems. */
@@ -742,13 +1034,46 @@ static enum register_status
mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int cookednum, gdb_byte *buf)
{
+ enum register_status ret;
+ int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
int rawnum = cookednum % gdbarch_num_regs (gdbarch);
+ int fpnum;
+ int raw_len, cooked_len;
+
gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
&& cookednum < 2 * gdbarch_num_regs (gdbarch));
- if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
+
+ raw_len = register_size (gdbarch, rawnum);
+ cooked_len = register_size (gdbarch, cookednum);
+
+ if (mips_float_register_p (gdbarch, rawnum))
+ {
+ struct mips_reg_part loc[3];
+ unsigned int parts;
+
+ fpnum = rawnum - mips_regnum (gdbarch)->fp0;
+ parts = mips_get_fp_multi_location (gdbarch, fpnum, cooked_len, loc);
+ return mips_regcache_raw_read_parts (regcache, loc, parts, &buf);
+ }
+ else if (mips_vector_register_p (gdbarch, rawnum))
+ {
+ int fp_rawnum, fp_raw_len;
+
+ fpnum = rawnum - mips_regnum (gdbarch)->w0;
+ fp_rawnum = mips_regnum (gdbarch)->fp0 + fpnum;
+ fp_raw_len = register_size (gdbarch, fp_rawnum);
+
+ if (fp_raw_len < cooked_len)
+ return REG_UNAVAILABLE;
+
+ /* fill from normal fp register */
+ return regcache_raw_read_part (regcache, fp_rawnum,
+ big_endian * (fp_raw_len - cooked_len),
+ cooked_len, buf);
+ }
+ else if (raw_len == cooked_len)
return regcache_raw_read (regcache, rawnum, buf);
- else if (register_size (gdbarch, rawnum) >
- register_size (gdbarch, cookednum))
+ else if (raw_len > cooked_len)
{
if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
return regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
@@ -773,13 +1098,46 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
struct regcache *regcache, int cookednum,
const gdb_byte *buf)
{
+ enum register_status ret;
+ int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
int rawnum = cookednum % gdbarch_num_regs (gdbarch);
+ int fpnum;
+ int raw_len, cooked_len;
+
gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
&& cookednum < 2 * gdbarch_num_regs (gdbarch));
- if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
+
+ raw_len = register_size (gdbarch, rawnum);
+ cooked_len = register_size (gdbarch, cookednum);
+
+ if (mips_float_register_p (gdbarch, rawnum))
+ {
+ struct mips_reg_part loc[3];
+ unsigned int parts;
+
+ fpnum = rawnum - mips_regnum (gdbarch)->fp0;
+ parts = mips_get_fp_multi_location (gdbarch, fpnum, cooked_len, loc);
+ mips_regcache_raw_write_parts (regcache, loc, parts, &buf);
+ }
+ else if (mips_vector_register_p (gdbarch, rawnum))
+ {
+ int fp_rawnum, fp_raw_len;
+
+ fpnum = rawnum - mips_regnum (gdbarch)->w0;
+ fp_rawnum = mips_regnum (gdbarch)->fp0 + fpnum;
+ fp_raw_len = register_size (gdbarch, fp_rawnum);
+
+ if (fp_raw_len < cooked_len)
+ return;
+
+ /* write to normal fp register */
+ regcache_raw_write_part (regcache, fp_rawnum,
+ big_endian * (fp_raw_len - cooked_len),
+ cooked_len, buf);
+ }
+ else if (raw_len == cooked_len)
regcache_raw_write (regcache, rawnum, buf);
- else if (register_size (gdbarch, rawnum) >
- register_size (gdbarch, cookednum))
+ else if (raw_len > cooked_len)
{
if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
regcache_raw_write_part (regcache, rawnum, 0, 4, buf);
@@ -872,18 +1230,31 @@ set_mips64_transfers_32bit_regs (char *args, int from_tty,
/* Convert to/from a register and the corresponding memory value. */
-/* This predicate tests for the case of an 8 byte floating point
- value that is being transferred to or from a pair of floating point
- registers each of which are (or are considered to be) only 4 bytes
- wide. */
+/* This predicate tests for the case of a 4 byte floating point
+ value that is being transferred to or from a floating point
+ register which is 8 bytes wide. */
+
static int
mips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
struct type *type)
{
- return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
- && register_size (gdbarch, regnum) == 4
+ return (register_size (gdbarch, regnum) == 8
+ && mips_float_register_p (gdbarch, regnum)
+ && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 4);
+}
+
+/* This predicate tests for the case of a 4 or 8 byte floating point
+ value that is being transferred to or from a floating point
+ register which is 12 bytes wide (containing both single and double). */
+
+static int
+mips_convert_register_float_fre_case_p (struct gdbarch *gdbarch,
+ int regnum, struct type *type)
+{
+ return (register_size (gdbarch, regnum) == 12
&& mips_float_register_p (gdbarch, regnum)
- && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
+ && TYPE_CODE (type) == TYPE_CODE_FLT
+ && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
}
/* This predicate tests for the case of a value of less than 8
@@ -905,6 +1276,7 @@ mips_convert_register_p (struct gdbarch *gdbarch,
int regnum, struct type *type)
{
return (mips_convert_register_float_case_p (gdbarch, regnum, type)
+ || mips_convert_register_float_fre_case_p (gdbarch, regnum, type)
|| mips_convert_register_gpreg_case_p (gdbarch, regnum, type));
}
@@ -917,16 +1289,39 @@ mips_register_to_value (struct frame_info *frame, int regnum,
if (mips_convert_register_float_case_p (gdbarch, regnum, type))
{
- get_frame_register (frame, regnum + 0, to + 4);
- get_frame_register (frame, regnum + 1, to + 0);
-
- if (!get_frame_register_bytes (frame, regnum + 0, 0, 4, to + 4,
- optimizedp, unavailablep))
- return 0;
-
- if (!get_frame_register_bytes (frame, regnum + 1, 0, 4, to + 0,
- optimizedp, unavailablep))
- return 0;
+ /* single comes from low half of 64-bit register */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ if (!get_frame_register_bytes (frame, regnum, 4, 4, to,
+ optimizedp, unavailablep))
+ return 0;
+ }
+ else
+ {
+ if (!get_frame_register_bytes (frame, regnum, 0, 4, to,
+ optimizedp, unavailablep))
+ return 0;
+ }
+ *optimizedp = *unavailablep = 0;
+ return 1;
+ }
+ else if (mips_convert_register_float_fre_case_p (gdbarch, regnum, type))
+ {
+ int len = TYPE_LENGTH (type);
+ if (len == 8)
+ {
+ /* double comes first */
+ if (!get_frame_register_bytes (frame, regnum, 0, 8, to,
+ optimizedp, unavailablep))
+ return 0;
+ }
+ else
+ {
+ /* followed by single */
+ if (!get_frame_register_bytes (frame, regnum, 8, 4, to,
+ optimizedp, unavailablep))
+ return 0;
+ }
*optimizedp = *unavailablep = 0;
return 1;
}
@@ -958,8 +1353,21 @@ mips_value_to_register (struct frame_info *frame, int regnum,
if (mips_convert_register_float_case_p (gdbarch, regnum, type))
{
- put_frame_register (frame, regnum + 0, from + 4);
- put_frame_register (frame, regnum + 1, from + 0);
+ /* single goes in low half of 64-bit register */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ put_frame_register_bytes (frame, regnum, 4, 4, from);
+ else
+ put_frame_register_bytes (frame, regnum, 0, 4, from);
+ }
+ else if (mips_convert_register_float_fre_case_p (gdbarch, regnum, type))
+ {
+ int len = TYPE_LENGTH (type);
+ if (len == 8)
+ /* double goes first */
+ put_frame_register_bytes (frame, regnum, 0, 8, from);
+ else
+ /* followed by single */
+ put_frame_register_bytes (frame, regnum, 8, 4, from);
}
else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
{
@@ -998,6 +1406,499 @@ mips_value_to_register (struct frame_info *frame, int regnum,
}
}
+/* Get floating point rounding mode enumeration type */
+
+static struct type *
+mips_frm_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_rm_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t;
+ struct field *f;
+
+ t = arch_type (gdbarch, TYPE_CODE_ENUM, 1, "__gdb_builtin_type_fp_rm");
+ TYPE_UNSIGNED (t) = 1;
+ f = append_composite_type_field_raw (t, "NEAREST", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 0);
+ f = append_composite_type_field_raw (t, "ZERO", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 1);
+ f = append_composite_type_field_raw (t, "INF", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 2);
+ f = append_composite_type_field_raw (t, "NINF", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 3);
+
+ tdep->fp_rm_type = t;
+ }
+ return tdep->fp_rm_type;
+}
+
+/* Get floating point condition flags type */
+
+static struct type *
+mips_fcflags_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_cflags_type == NULL)
+ {
+ struct type *t;
+
+ /* Flags, Enables, Cause have common set of condition flags */
+ t = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_cflags", 1);
+ append_flags_type_flag (t, 0, "I");
+ append_flags_type_flag (t, 1, "U");
+ append_flags_type_flag (t, 2, "O");
+ append_flags_type_flag (t, 3, "Z");
+ append_flags_type_flag (t, 4, "V");
+ append_flags_type_flag (t, 5, "E"); /* Cause field only */
+
+ tdep->fp_cflags_type = t;
+ }
+ return tdep->fp_cflags_type;
+}
+
+static struct type *
+mips_fcsr_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_csr_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t, *cflags, *flags;
+ struct field *f;
+
+ /* Flags, Enables, Cause have common set of condition flags */
+ cflags = mips_fcflags_type (gdbarch);
+
+ /* Various bits at top end */
+ flags = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_csr_flags", 2);
+ append_flags_type_flag (flags, 0, "NAN2008");
+ append_flags_type_flag (flags, 1, "ABS2008");
+ append_flags_type_flag (flags, 2, "MAC2008");
+ append_flags_type_flag (flags, 3, "IMPL0");
+ append_flags_type_flag (flags, 4, "IMPL1");
+ append_flags_type_flag (flags, 5, "FCC0");
+ append_flags_type_flag (flags, 6, "FS");
+ append_flags_type_flag (flags, 7, "FCC1");
+ append_flags_type_flag (flags, 8, "FCC2");
+ append_flags_type_flag (flags, 9, "FCC3");
+ append_flags_type_flag (flags, 10, "FCC4");
+ append_flags_type_flag (flags, 11, "FCC5");
+ append_flags_type_flag (flags, 12, "FCC6");
+ append_flags_type_flag (flags, 13, "FCC7");
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_fp_csr",
+ TYPE_CODE_STRUCT);
+
+ /* rounding mode */
+ f = append_composite_type_field_raw (t, "rm", mips_frm_type (gdbarch));
+ SET_FIELD_BITPOS (*f, 0);
+ FIELD_BITSIZE (*f) = 2;
+
+ f = append_composite_type_field_raw (t, "flags", cflags);
+ SET_FIELD_BITPOS (*f, 2);
+ FIELD_BITSIZE (*f) = 5;
+
+ f = append_composite_type_field_raw (t, "enables", cflags);
+ SET_FIELD_BITPOS (*f, 7);
+ FIELD_BITSIZE (*f) = 5;
+
+ f = append_composite_type_field_raw (t, "cause", cflags);
+ SET_FIELD_BITPOS (*f, 12);
+ FIELD_BITSIZE (*f) = 6;
+
+ f = append_composite_type_field_raw (t, "", flags);
+ SET_FIELD_BITPOS (*f, 18);
+ FIELD_BITSIZE (*f) = 14;
+
+ TYPE_LENGTH (t) = 4;
+ TYPE_NAME (t) = "fp_csr";
+ tdep->fp_csr_type = t;
+ }
+
+ return tdep->fp_csr_type;
+}
+
+static struct type *
+mips_fir_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_ir_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t, *flags;
+ /* top half has flags */
+ flags = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_ir_flags", 2);
+ append_flags_type_flag (flags, 0, "S");
+ append_flags_type_flag (flags, 1, "D");
+ append_flags_type_flag (flags, 2, "PS");
+ append_flags_type_flag (flags, 3, "3D");
+ append_flags_type_flag (flags, 4, "W");
+ append_flags_type_flag (flags, 5, "L");
+ append_flags_type_flag (flags, 6, "F64");
+ append_flags_type_flag (flags, 7, "HAS2008");
+ append_flags_type_flag (flags, 8, "IMPL0");
+ append_flags_type_flag (flags, 9, "IMPL1");
+ append_flags_type_flag (flags, 10, "IMPL2");
+ append_flags_type_flag (flags, 11, "IMPL3");
+ append_flags_type_flag (flags, 12, "UFRP");
+ append_flags_type_flag (flags, 13, "FREP");
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_fp_ir",
+ TYPE_CODE_STRUCT);
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+ {
+ /* bottom half has revision & processor id */
+ append_composite_type_field (t, "rev", bt->builtin_uint8);
+ append_composite_type_field (t, "prid", bt->builtin_uint8);
+
+ /* top half has flags */
+ append_composite_type_field (t, "", flags);
+ }
+ else
+ {
+ /* top half has flags */
+ append_composite_type_field (t, "", flags);
+
+ /* bottom half has revision & processor id */
+ append_composite_type_field (t, "prid", bt->builtin_uint8);
+ append_composite_type_field (t, "rev", bt->builtin_uint8);
+ }
+
+ TYPE_LENGTH (t) = 4;
+ TYPE_NAME (t) = "fp_ir";
+ tdep->fp_ir_type = t;
+ }
+
+ return tdep->fp_ir_type;
+}
+
+static struct type *
+mips_config5_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->config5_type == NULL)
+ {
+ struct type *t;
+ /* top half has flags */
+ t = arch_flags_type (gdbarch, "__gdb_builtin_type_config5", 4);
+ append_flags_type_flag (t, 8, "FRE");
+
+ TYPE_NAME (t) = "config5";
+ tdep->config5_type = t;
+ }
+
+ return tdep->config5_type;
+}
+
+static struct type *
+mips_msacsr_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->msa_csr_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t, *cflags, *flags;
+ struct field *f;
+
+ /* Flags, Enables, Cause have common set of condition flags */
+ cflags = mips_fcflags_type (gdbarch);
+
+ /* Various bits at top end */
+ flags = arch_flags_type (gdbarch, "__gdb_builtin_type_msa_csr_flags", 2);
+ append_flags_type_flag (flags, 0, "NX");
+ append_flags_type_flag (flags, 3, "IMPL0");
+ append_flags_type_flag (flags, 4, "IMPL1");
+ append_flags_type_flag (flags, 6, "FS");
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_msa_csr",
+ TYPE_CODE_STRUCT);
+
+ /* Rounding mode */
+ f = append_composite_type_field_raw (t, "rm", mips_frm_type (gdbarch));
+ SET_FIELD_BITPOS (*f, 0);
+ FIELD_BITSIZE (*f) = 2;
+
+ f = append_composite_type_field_raw (t, "flags", cflags);
+ SET_FIELD_BITPOS (*f, 2);
+ FIELD_BITSIZE (*f) = 5;
+
+ f = append_composite_type_field_raw (t, "enables", cflags);
+ SET_FIELD_BITPOS (*f, 7);
+ FIELD_BITSIZE (*f) = 5;
+
+ f = append_composite_type_field_raw (t, "cause", cflags);
+ SET_FIELD_BITPOS (*f, 12);
+ FIELD_BITSIZE (*f) = 6;
+
+ f = append_composite_type_field_raw (t, "", flags);
+ SET_FIELD_BITPOS (*f, 18);
+ FIELD_BITSIZE (*f) = 14;
+
+ TYPE_LENGTH (t) = 4;
+ TYPE_NAME (t) = "msa_csr";
+ tdep->msa_csr_type = t;
+ }
+
+ return tdep->msa_csr_type;
+}
+
+static struct type *
+mips_msair_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->msa_ir_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t, *flags;
+
+ /* top half has flags */
+ flags = arch_flags_type (gdbarch, "__gdb_builtin_type_msa_ir_flags", 2);
+ append_flags_type_flag (flags, 0, "WRP");
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_msa_ir",
+ TYPE_CODE_STRUCT);
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+ {
+ /* bottom half has revision & processor id */
+ append_composite_type_field (t, "rev", bt->builtin_uint8);
+ append_composite_type_field (t, "prid", bt->builtin_uint8);
+
+ /* top half has flags */
+ append_composite_type_field (t, "", flags);
+ }
+ else
+ {
+ /* top half has flags */
+ append_composite_type_field (t, "", flags);
+
+ /* bottom half has revision & processor id */
+ append_composite_type_field (t, "prid", bt->builtin_uint8);
+ append_composite_type_field (t, "rev", bt->builtin_uint8);
+ }
+
+ TYPE_LENGTH (t) = 4;
+ TYPE_NAME (t) = "msa_ir";
+ tdep->msa_ir_type = t;
+ }
+
+ return tdep->msa_ir_type;
+}
+
+/* Get 32-bit only floating point type, which can be interpreted as either a
+ single precision float or a 32-bit signed integer.
+ This is used for odd fp registers when FR=0. In this case there are no odd
+ doubles. */
+
+static struct type *
+mips_fp32_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp32_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t;
+
+ /* The type we're building is this: */
+#if 0
+ union __gdb_builtin_mips_fp32 {
+ float f32;
+ int32_t i32;
+ };
+#endif
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_mips_fp32",
+ TYPE_CODE_UNION);
+ append_composite_type_field (t, "f32", bt->builtin_float);
+ append_composite_type_field (t, "i32", bt->builtin_int32);
+
+ TYPE_NAME (t) = "fp32";
+ tdep->fp32_type = t;
+ }
+
+ return tdep->fp32_type;
+}
+
+/* Get general floating point type, which can be interpreted as either a
+ single or double precision float, or a 32-bit or 64-bit signed integer.
+ This is used for even fp registers when FR=0 (doubles are constructed from
+ even/odd pairs of fp registers so only even registers can be interpreted as
+ double precision flaots) and for all fp registers when FR=1. */
+
+static struct type *
+mips_fp64_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp64_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+ struct type *t;
+ struct field *f;
+
+ /* The type we're building is roughly this (little endian): */
+#if 0
+ union __gdb_builtin_mips_fp64 {
+ float f32;
+ double f64;
+ int32 i32;
+ int64 i64;
+ };
+#endif
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_mips_fp64",
+ TYPE_CODE_UNION);
+ f = append_composite_type_field_raw (t, "f32", bt->builtin_float);
+ SET_FIELD_BITPOS (*f, 32*big_endian);
+ f = append_composite_type_field_raw (t, "f64", bt->builtin_double);
+ SET_FIELD_BITPOS (*f, 0);
+ f = append_composite_type_field_raw (t, "i32", bt->builtin_int32);
+ SET_FIELD_BITPOS (*f, 32*big_endian);
+ f = append_composite_type_field_raw (t, "i64", bt->builtin_int64);
+ SET_FIELD_BITPOS (*f, 0);
+
+ TYPE_LENGTH (t) = 8;
+ TYPE_NAME (t) = "fp64";
+ tdep->fp64_type = t;
+ }
+
+ return tdep->fp64_type;
+}
+
+/* Get FRE odd floating point type, which can contains separate single and
+ double precision floats, or a separate 32-bit or 64-bit signed integer.
+ This is used for odd fp registers when FR=1 and FRE=1 (the odd single comes
+ from the upper half of the even double, so odd singles and odd doubles do not
+ overlap). */
+
+static struct type *
+mips_fp96_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp96_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t;
+ struct field *f;
+
+ /* The type we're building is roughly this: */
+#if 0
+ struct __gdb_builtin_mips_fp96 {
+ union {
+ double f64;
+ int64 i64;
+ };
+ union {
+ float f32;
+ int32 i32;
+ };
+ };
+#endif
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_mips_fp96",
+ TYPE_CODE_STRUCT);
+ f = append_composite_type_field_raw (t, "f32", bt->builtin_float);
+ SET_FIELD_BITPOS (*f, 64);
+ f = append_composite_type_field_raw (t, "f64", bt->builtin_double);
+ SET_FIELD_BITPOS (*f, 0);
+ f = append_composite_type_field_raw (t, "i32", bt->builtin_int32);
+ SET_FIELD_BITPOS (*f, 64);
+ f = append_composite_type_field_raw (t, "i64", bt->builtin_int64);
+ SET_FIELD_BITPOS (*f, 0);
+
+ TYPE_LENGTH (t) = 12;
+ TYPE_NAME (t) = "fp96";
+ tdep->fp96_type = t;
+ }
+
+ return tdep->fp96_type;
+}
+
+/* Get the floating point type for an arbitrary FP register. This returns the
+ appropriate type depending on the possible types and overlaps of the
+ register. */
+
+static struct type *
+mips_fp_type (struct gdbarch *gdbarch, int fpnum)
+{
+ if ((fpnum & 1) == 1 && mips_float_hybrid (gdbarch) )
+ /* 64-bit hybrid registers: odd singles and doubles don't overlap. */
+ return mips_fp96_type (gdbarch);
+ else if ((fpnum & 1) == 0 || mips_float_regsize (gdbarch) == 8)
+ /* Even singles and doubles always overlap, as do odd singles and
+ doubles when FR=1 (and FRE=0). */
+ return mips_fp64_type (gdbarch);
+ else
+ /* 32-bit odd singles (there are no odd doubles). */
+ return mips_fp32_type (gdbarch);
+}
+
+/* FIXME: The vector types are not correctly ordered on big-endian
+ targets. Just as s0 is the low bits of d0, d0[0] is also the low
+ bits of d0 - regardless of what unit size is being held in d0. So
+ the offset of the first uint8 in d0 is 7, but the offset of the
+ first float is 4. This code works as-is for little-endian
+ targets. */
+
+static struct type *
+mips_msa_128b_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->msa_128b_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t;
+
+ /* The type we're building is this: */
+#if 0
+ union __gdb_builtin_type_msa_128
+ {
+ float f32[4];
+ double f64[2];
+ uint8_t u8[16];
+ uint16_t u16[8];
+ uint32_t u32[4];
+ uint64_t u64[2];
+ };
+#endif
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_msa_128",
+ TYPE_CODE_UNION);
+ append_composite_type_field (t, "u8",
+ init_vector_type (bt->builtin_uint8, 16));
+ append_composite_type_field (t, "u16",
+ init_vector_type (bt->builtin_uint16, 8));
+ append_composite_type_field (t, "u32",
+ init_vector_type (bt->builtin_uint32, 4));
+ append_composite_type_field (t, "u64",
+ init_vector_type (bt->builtin_uint64, 2));
+ append_composite_type_field (t, "f32",
+ init_vector_type (bt->builtin_float, 4));
+ append_composite_type_field (t, "f64",
+ init_vector_type (bt->builtin_double, 2));
+
+ TYPE_VECTOR (t) = 1;
+ TYPE_NAME (t) = "msa_128";
+ tdep->msa_128b_type = t;
+ }
+
+ return tdep->msa_128b_type;
+}
+
/* Return the GDB type object for the "standard" data type of data in
register REG. */
@@ -1005,33 +1906,49 @@ static struct type *
mips_register_type (struct gdbarch *gdbarch, int regnum)
{
gdb_assert (regnum >= 0 && regnum < 2 * gdbarch_num_regs (gdbarch));
- if (mips_float_register_p (gdbarch, regnum))
- {
- /* The floating-point registers raw, or cooked, always match
- mips_isa_regsize(), and also map 1:1, byte for byte. */
- if (mips_isa_regsize (gdbarch) == 4)
- return builtin_type (gdbarch)->builtin_float;
- else
- return builtin_type (gdbarch)->builtin_double;
- }
- else if (regnum < gdbarch_num_regs (gdbarch))
+ if (regnum < gdbarch_num_regs (gdbarch))
{
/* The raw or ISA registers. These are all sized according to
- the ISA regsize. */
- if (mips_isa_regsize (gdbarch) == 4)
- return builtin_type (gdbarch)->builtin_int32;
+ the ISA regsize, except FP registers which may be double
+ even on MIPS32 since rev 2 of the architecture. */
+ int regsize = mips_isa_regsize (gdbarch);
+
+ if (mips_float_register_p (gdbarch, regnum))
+ return (mips_float_regsize (gdbarch) == 4
+ ? builtin_type (gdbarch)->builtin_float
+ : builtin_type (gdbarch)->builtin_double);
+ else if (mips_vector_register_p (gdbarch, regnum))
+ /* no raw representation, share fp registers */
+ return builtin_type (gdbarch)->builtin_int0;
else
- return builtin_type (gdbarch)->builtin_int64;
+ return (regsize == 4
+ ? builtin_type (gdbarch)->builtin_int32
+ : builtin_type (gdbarch)->builtin_int64);
}
else
{
- int rawnum = regnum - gdbarch_num_regs (gdbarch);
-
/* The cooked or ABI registers. These are sized according to
the ABI (with a few complications). */
- if (rawnum == mips_regnum (gdbarch)->fp_control_status
- || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
- return builtin_type (gdbarch)->builtin_int32;
+ int rawnum = regnum - gdbarch_num_regs (gdbarch);
+
+ /* Floating-point registers of most 64-bit and some 32-bit MIPS
+ processors can be reconfigured dynamically at the run time as
+ either 64-bit or 32-bit via the CP0 Status register's FR bit.
+ Use the current setting for cooked registers. */
+ if (mips_float_register_p (gdbarch, regnum))
+ return mips_fp_type (gdbarch, rawnum - mips_regnum (gdbarch)->fp0);
+ else if (rawnum == mips_regnum (gdbarch)->fp_control_status)
+ return mips_fcsr_type (gdbarch);
+ else if (rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+ return mips_fir_type (gdbarch);
+ else if (rawnum == mips_regnum (gdbarch)->config5)
+ return mips_config5_type (gdbarch);
+ else if (mips_vector_register_p (gdbarch, regnum))
+ return mips_msa_128b_type (gdbarch);
+ else if (rawnum == mips_regnum (gdbarch)->msa_csr)
+ return mips_msacsr_type (gdbarch);
+ else if (rawnum == mips_regnum (gdbarch)->msa_ir)
+ return mips_msair_type (gdbarch);
else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
&& gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
&& rawnum >= MIPS_FIRST_EMBED_REGNUM
@@ -1062,21 +1979,32 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
static struct type *
mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch ());
const int num_regs = gdbarch_num_regs (gdbarch);
int rawnum = regnum % num_regs;
- struct type *rawtype;
+ struct type *rawtype, *fp_rawtype;
gdb_assert (regnum >= num_regs && regnum < 2 * num_regs);
- /* Absent registers are still absent. */
rawtype = gdbarch_register_type (gdbarch, rawnum);
+
+ /* Vector registers extend FP registers */
+ if (mips_vector_register_p (gdbarch, rawnum))
+ return mips_msa_128b_type (gdbarch);
+
+ /* Absent registers are still absent. */
if (TYPE_LENGTH (rawtype) == 0)
return rawtype;
if (mips_float_register_p (gdbarch, rawnum))
- /* Present the floating point registers however the hardware did;
- do not try to convert between FPU layouts. */
- return rawtype;
+ /* FIXME this comment is now out of date */
+ /* Present the floating point registers however the hardware did; do
+ not try to convert between FPU layouts. A target description is
+ expected to have taken the CP0 Status register's FR bit into account
+ as necessary, this has been already verified in mips_gdbarch_init. */
+ return mips_fp_type (gdbarch, rawnum - mips_regnum (gdbarch)->fp0);
+
+ /* msacsr, msair */
/* Use pointer types for registers if we can. For n32 we can not,
since we do not have a 64-bit pointer type. */
@@ -1102,6 +2030,21 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
&& rawnum < mips_regnum (gdbarch)->dspacc + 6)))
return builtin_type (gdbarch)->builtin_int32;
+ if (rawnum == mips_regnum (gdbarch)->fp_control_status)
+ return mips_fcsr_type (gdbarch);
+
+ if (rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+ return mips_fir_type (gdbarch);
+
+ if (rawnum == mips_regnum (gdbarch)->config5)
+ return mips_config5_type (gdbarch);
+
+ if (rawnum == mips_regnum (gdbarch)->msa_csr)
+ return mips_msacsr_type (gdbarch);
+
+ if (rawnum == mips_regnum (gdbarch)->msa_ir)
+ return mips_msair_type (gdbarch);
+
if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
&& gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
&& rawnum >= MIPS_EMBED_FP0_REGNUM + 32
@@ -1462,6 +2405,17 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
return extract_unsigned_integer (buf, instlen, byte_order);
}
+/* Return one if the gdbarch is based on MIPS Release 6. */
+
+static int
+is_mipsr6_isa (struct gdbarch *gdbarch)
+{
+ const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
+
+ return (info->mach == bfd_mach_mipsisa32r6
+ || info->mach == bfd_mach_mipsisa64r6);
+}
+
/* These are the fields of 32 bit mips instructions. */
#define mips32_op(x) (x >> 26)
#define itype_op(x) (x >> 26)
@@ -1493,10 +2447,12 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
#define b1s9_imm(x) (((x) >> 1) & 0x1ff)
#define b2s3_cc(x) (((x) >> 2) & 0x7)
#define b4s2_regl(x) (((x) >> 4) & 0x3)
+#define b4s4_imm(x) (((x) >> 4) & 0xf)
#define b5s5_op(x) (((x) >> 5) & 0x1f)
#define b5s5_reg(x) (((x) >> 5) & 0x1f)
#define b6s4_op(x) (((x) >> 6) & 0xf)
#define b7s3_reg(x) (((x) >> 7) & 0x7)
+#define b8s2_regl(x) (((x) >> 8) & 0x3)
/* 32-bit instruction formats, B and S refer to the lowest bit and the size
respectively of the field extracted. */
@@ -1504,8 +2460,10 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
#define b0s11_op(x) ((x) & 0x7ff)
#define b0s12_imm(x) ((x) & 0xfff)
#define b0s16_imm(x) ((x) & 0xffff)
+#define b0s21_imm(x) ((x) & 0x1fffff)
#define b0s26_imm(x) ((x) & 0x3ffffff)
#define b6s10_ext(x) (((x) >> 6) & 0x3ff)
+#define b9s3_op(x) (((x) >> 9) & 0x7)
#define b11s5_reg(x) (((x) >> 11) & 0x1f)
#define b12s4_op(x) (((x) >> 12) & 0xf)
@@ -1513,13 +2471,15 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
instruction set. */
static int
-mips_insn_size (enum mips_isa isa, ULONGEST insn)
+mips_insn_size (struct gdbarch *gdbarch, enum mips_isa isa, ULONGEST insn)
{
switch (isa)
{
case ISA_MICROMIPS:
- if ((micromips_op (insn) & 0x4) == 0x4
- || (micromips_op (insn) & 0x7) == 0x0)
+ if (!is_mipsr6_isa (gdbarch) && micromips_op (insn) == 0x1f)
+ return 3 * MIPS_INSN16_SIZE;
+ if (((micromips_op (insn) & 0x4) == 0x4)
+ || ((micromips_op (insn) & 0x7) == 0x0))
return 2 * MIPS_INSN16_SIZE;
else
return MIPS_INSN16_SIZE;
@@ -1540,6 +2500,24 @@ mips32_relative_offset (ULONGEST inst)
return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
}
+/* Extract the 21-bit signed immediate offset from the MIPS instruction
+ INSN. */
+
+static LONGEST
+mips32_relative_offset21 (ULONGEST insn)
+{
+ return ((b0s21_imm (insn) ^ 0x100000) - 0x100000) << 2;
+}
+
+/* Extract the 26-bit signed immediate offset from the MIPS instruction
+ INSN. */
+
+static LONGEST
+mips32_relative_offset26 (ULONGEST insn)
+{
+ return ((b0s26_imm (insn) ^ 0x2000000) - 0x2000000) << 2;
+}
+
/* Determine the address of the next instruction executed after the INST
floating condition branch instruction at PC. COUNT specifies the
number of the floating condition bits tested by the branch. */
@@ -1570,6 +2548,152 @@ mips32_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
return pc;
}
+/* Determine the address of the next instruction execute after the INST
+ BLEZ family of branch instructions at PC */
+
+static CORE_ADDR
+mips32_blez_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+ ULONGEST inst, CORE_ADDR pc, int invert)
+{
+ int rs = itype_rs (inst);
+ int rt = itype_rt (inst);
+ LONGEST val_rs = get_frame_register_signed (frame, rs);
+ LONGEST val_rt = get_frame_register_signed (frame, rt);
+ ULONGEST uval_rs = get_frame_register_unsigned (frame, rs);
+ ULONGEST uval_rt = get_frame_register_unsigned (frame, rt);
+ int taken = 0;
+ int delay_slot_size = 4;
+
+ /* BLEZ, BLEZL, BGTZ, BGTZL */
+ if (rt == 0)
+ {
+ taken = (val_rs <= 0);
+ }
+ else if (is_mipsr6_isa (gdbarch))
+ {
+ /* BLEZALC, BGTZALC */
+ if (rs == 0 && rt != 0)
+ taken = (val_rt <= 0);
+ /* BGEZALC, BLTZALC */
+ else if (rs == rt && rt != 0)
+ taken = (val_rt >= 0);
+ /* BGEUC, BLTUC */
+ else if (rs != rt && rs != 0 && rt != 0)
+ taken = (uval_rs >= uval_rt);
+
+ /* Step through the forbidden slot to avoid repeated exceptions we do
+ not currently have access to the BD bit when hitting a breakpoint
+ and therefore cannot tell if the breakpoint hit on the branch or the
+ forbidden slot. */
+ /* delay_slot_size = 0; */
+ }
+
+ if (invert)
+ taken = !taken;
+
+ /* Calculate branch target */
+ if (taken)
+ pc += mips32_relative_offset (inst);
+ else
+ pc += delay_slot_size;
+
+ return pc;
+}
+
+/* Determine whether a vector branch will be taken.
+ Returns 1 if branch taken, 0 if branch not taken, -1 on error. */
+
+static int
+mips_bc1_w_taken (struct gdbarch *gdbarch, struct frame_info *frame,
+ unsigned int op, unsigned int wt)
+{
+ int wr = gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->w0;
+ int taken = -1;
+ int size, elem_size, tog;
+ gdb_byte *buf, *end, *elem_end;
+
+ if (wr == -1)
+ /* No way to handle; it'll most likely trap anyway. */
+ return -1;
+ wr += wt;
+
+ /* Read vector register. */
+ size = register_size (gdbarch, wr);
+ buf = alloca (size);
+ if (!deprecated_frame_register_read (frame, wr, buf))
+ return -1;
+
+ if ((op & 0x18) == 0x18)
+ {
+ elem_size = 1 << (op & 0x3);
+ /* Check whether this branch would be taken first:
+ BZ.df: 110xx (branch if at least one element is zero) */
+ taken = 0;
+ for (end = buf + size; buf < end;)
+ {
+ taken = 1;
+ for (elem_end = buf + elem_size; buf < elem_end; ++buf)
+ if (*buf)
+ {
+ /* this element is non-zero */
+ taken = 0;
+ break;
+ }
+ if (taken)
+ /* this element zero, branch taken */
+ break;
+ buf = elem_end;
+ }
+
+ if (op & 0x4)
+ /* BNZ.df: 111xx (branch if all elements are non-zero)
+ Branch taken is inverted compared to BZ.df */
+ taken = !taken;
+ }
+ else if ((op & 0x1b) == 0x0b)
+ {
+ /* Check whether this branch would be taken first:
+ BZ.V: 01011 (branch if all elements are zero) */
+ taken = 1;
+ for (end = buf + size; buf < end; ++buf)
+ if (*buf)
+ {
+ /* this element is non-zero, branch not taken */
+ taken = 0;
+ break;
+ }
+ if (op & 0x4)
+ /* BNZ.V: 01111 (branch if any elements are non-zero)
+ Branch taken is inverted compared to BZ.V */
+ taken = !taken;
+ }
+
+ return taken;
+}
+
+/* Determine the address of the next instruction executed after the INST
+ vector branch instruction at PC. */
+
+static CORE_ADDR
+mips32_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+ ULONGEST inst, CORE_ADDR pc)
+{
+ int op = itype_rs (inst);
+ int wt = itype_rt (inst);
+ int taken;
+
+ /* Will the branch be taken? */
+ taken = mips_bc1_w_taken (gdbarch, frame, op, wt);
+
+ /* Calculate branch target */
+ if (taken > 0)
+ pc += mips32_relative_offset (inst);
+ else if (taken == 0)
+ pc += 4;
+
+ return pc;
+}
+
/* Return nonzero if the gdbarch is an Octeon series. */
static int
@@ -1598,6 +2722,24 @@ is_octeon_bbit_op (int op, struct gdbarch *gdbarch)
return 0;
}
+/* Return 1 if A + B would overflow. */
+
+static int
+is_add32bit_overflow (int32_t a, int32_t b)
+{
+ int32_t r = (uint32_t) a + (uint32_t) b;
+ return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
+}
+
+static int
+is_add64bit_overflow (int64_t a, int64_t b)
+{
+ if (a != (int32_t)a)
+ return 1;
+ if (b != (int32_t)b)
+ return 1;
+ return is_add32bit_overflow ((int32_t)a, (int32_t)b);
+}
/* Determine where to set a single step breakpoint while considering
branch prediction. */
@@ -1608,12 +2750,18 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
struct gdbarch *gdbarch = get_frame_arch (frame);
unsigned long inst;
int op;
+ int mips64bitreg = 0;
+
+ if (mips_isa_regsize (gdbarch) == 8)
+ mips64bitreg = 1;
+
inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
op = itype_op (inst);
if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch
instruction. */
{
- if (op >> 2 == 5)
+ if (op >> 2 == 5 && ((op & 0x02) == 0
+ || itype_rt (inst) == 0))
/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
{
switch (op & 0x03)
@@ -1623,7 +2771,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
case 1: /* BNEL */
goto neq_branch;
case 2: /* BLEZL */
- goto less_branch;
+ goto lez_branch;
case 3: /* BGTZL */
goto greater_branch;
default:
@@ -1633,15 +2781,25 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
else if (op == 17 && itype_rs (inst) == 8)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 1);
- else if (op == 17 && itype_rs (inst) == 9
+ else if (!is_mipsr6_isa (gdbarch)
+ && op == 17 && itype_rs (inst) == 9
&& (itype_rt (inst) & 2) == 0)
/* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 2);
- else if (op == 17 && itype_rs (inst) == 10
+ else if (!is_mipsr6_isa (gdbarch)
+ && op == 17 && itype_rs (inst) == 10
&& (itype_rt (inst) & 2) == 0)
/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4);
- else if (op == 29)
+ else if (op == 17 && (itype_rs (inst) & 0x18) == 0x18)
+ /* BZ.df: 010001 110xx */
+ /* BNZ.df: 010001 111xx */
+ pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4);
+ else if (op == 17 && (itype_rs (inst) & 0x1b) == 0x0b)
+ /* BZ.V: 010001 01011 */
+ /* BNZ.V: 010001 01111 */
+ pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4);
+ else if (!is_mipsr6_isa (gdbarch) && op == 29)
/* JALX: 011101 */
/* The new PC will be alternate mode. */
{
@@ -1669,7 +2827,126 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
else
pc += 8; /* After the delay slot. */
}
+ else if (is_mipsr6_isa (gdbarch))
+ {
+ /* BOVC, BEQZALC, BEQC and BNVC, BNEZALC, BNEC */
+ if (op == 8 || op == 24)
+ {
+ int rs = rtype_rs (inst);
+ int rt = rtype_rt (inst);
+ LONGEST val_rs = get_frame_register_signed (frame, rs);
+ LONGEST val_rt = get_frame_register_signed (frame, rt);
+ int taken = 0;
+ /* BOVC (BNVC) */
+ if (rs >= rt)
+ {
+ if (mips64bitreg == 1)
+ taken = is_add64bit_overflow (val_rs, val_rt);
+ else
+ taken = is_add32bit_overflow (val_rs, val_rt);
+ }
+ /* BEQZALC (BNEZALC) */
+ else if (rs < rt && rs == 0)
+ taken = (val_rt == 0);
+ /* BEQC (BNEC) */
+ else
+ taken = (val_rs == val_rt);
+
+ /* BNVC, BNEZALC, BNEC */
+ if (op == 24)
+ taken = !taken;
+
+ if (taken)
+ pc += mips32_relative_offset (inst) + 4;
+ else
+ /* Step through the forbidden slot to avoid repeated exceptions
+ we do not currently have access to the BD bit when hitting a
+ breakpoint and therefore cannot tell if the breakpoint
+ hit on the branch or the forbidden slot. */
+ pc += 8;
+ }
+ /* BC1EQZ, BC1NEZ */
+ else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13))
+ {
+ gdb_byte status;
+ gdb_byte true_val = 0;
+ gdb_byte *raw_buffer = alloca (sizeof (gdb_byte) * 8);
+ mips_read_fp_register_single (frame, itype_rt (inst) +
+ gdbarch_num_regs (gdbarch) +
+ mips_regnum (gdbarch)->fp0,
+ raw_buffer);
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ status = *(raw_buffer + 3);
+ else
+ status = *(raw_buffer);
+ if (itype_rs (inst) == 13)
+ true_val = 1;
+
+ if ((status & 0x1) == true_val)
+ pc += mips32_relative_offset (inst) + 4;
+ else
+ pc += 8;
+ }
+ else if (op == 22 || op == 23)
+ /* BLEZC, BGEZC, BGEC, BGTZC, BLTZC, BLTC */
+ {
+ int rs = rtype_rs (inst);
+ int rt = rtype_rt (inst);
+ LONGEST val_rs = get_frame_register_signed (frame, rs);
+ LONGEST val_rt = get_frame_register_signed (frame, rt);
+ int taken = 0;
+ /* The R5 rt == 0 case is handled above so we treat it as
+ an unknown instruction here for future ISA usage. */
+ if (rs == 0 && rt != 0)
+ taken = (val_rt <= 0);
+ else if (rs == rt && rt != 0)
+ taken = (val_rt >= 0);
+ else if (rs != rt && rs != 0 && rt != 0)
+ taken = (val_rs >= val_rt);
+
+ if (op == 23)
+ taken = !taken;
+
+ if (taken)
+ pc += mips32_relative_offset (inst) + 4;
+ else
+ /* Step through the forbidden slot to avoid repeated exceptions
+ we do not currently have access to the BD bit when hitting a
+ breakpoint and therefore cannot tell if the breakpoint
+ hit on the branch or the forbidden slot. */
+ pc += 8;
+ }
+ else if (op == 50 || op == 58)
+ /* BC, BALC */
+ pc += mips32_relative_offset26 (inst) + 4;
+ else if ((op == 54 || op == 62)
+ && rtype_rs (inst) == 0)
+ /* JIC, JIALC */
+ {
+ pc = get_frame_register_signed (frame, itype_rt (inst));
+ pc += (itype_immediate (inst) ^ 0x8000) - 0x8000;
+ }
+ else if (op == 54 || op == 62)
+ /* BEQZC, BNEZC */
+ {
+ int rs = itype_rs (inst);
+ LONGEST rs_val = get_frame_register_signed (frame, rs);
+ int taken = (rs_val == 0);
+ if (op == 62)
+ taken = !taken;
+ if (taken)
+ pc += mips32_relative_offset21 (inst) + 4;
+ else
+ /* Step through the forbidden slot to avoid repeated exceptions
+ we do not currently have access to the BD bit when hitting a
+ breakpoint and therefore cannot tell if the breakpoint
+ hit on the branch or the forbidden slot. */
+ pc += 8;
+ }
+ else
+ pc += 4; /* Not a branch, next instruction is easy. */
+ }
else
pc += 4; /* Not a branch, next instruction is easy. */
}
@@ -1713,7 +2990,6 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
case 2: /* BLTZL */
case 16: /* BLTZAL */
case 18: /* BLTZALL */
- less_branch:
if (get_frame_register_signed (frame, itype_rs (inst)) < 0)
pc += mips32_relative_offset (inst) + 4;
else
@@ -1729,22 +3005,38 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
pc += 8; /* after the delay slot */
break;
case 0x1c: /* BPOSGE32 */
+ case 0x18: /* BPOSGE32C */
case 0x1e: /* BPOSGE64 */
pc += 4;
if (itype_rs (inst) == 0)
{
unsigned int pos = (op & 2) ? 64 : 32;
int dspctl = mips_regnum (gdbarch)->dspctl;
+ int delay_slot_size = 4;
if (dspctl == -1)
/* No way to handle; it'll most likely trap anyway. */
break;
+ /* BPOSGE32C */
+ if (op == 0x18)
+ {
+ if (!is_mipsr6_isa (gdbarch))
+ break;
+
+ /* Step through the forbidden slot to avoid repeated
+ exceptions we do not currently have access to the BD
+ bit when hitting a breakpoint and therefore cannot
+ tell if the breakpoint hit on the branch or the
+ forbidden slot. */
+ /* delay_slot_size = 0; */
+ }
+
if ((get_frame_register_unsigned (frame,
dspctl) & 0x7f) >= pos)
pc += mips32_relative_offset (inst);
else
- pc += 4;
+ pc += delay_slot_size;
}
break;
/* All of the other instructions in the REGIMM category */
@@ -1778,19 +3070,14 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
else
pc += 8;
break;
- case 6: /* BLEZ, BLEZL */
- if (get_frame_register_signed (frame, itype_rs (inst)) <= 0)
- pc += mips32_relative_offset (inst) + 4;
- else
- pc += 8;
+ case 6: /* BLEZ, BLEZL, BLEZALC, BGEZALC, BGEUC */
+ lez_branch:
+ pc = mips32_blez_pc (gdbarch, frame, inst, pc + 4, 0);
break;
case 7:
default:
- greater_branch: /* BGTZ, BGTZL */
- if (get_frame_register_signed (frame, itype_rs (inst)) > 0)
- pc += mips32_relative_offset (inst) + 4;
- else
- pc += 8;
+ greater_branch: /* BGTZ, BGTZL, BGTZALC, BLTZALC, BLTUC */
+ pc = mips32_blez_pc (gdbarch, frame, inst, pc + 4, 1);
break;
} /* switch */
} /* else */
@@ -1824,6 +3111,24 @@ micromips_relative_offset16 (ULONGEST insn)
return ((b0s16_imm (insn) ^ 0x8000) - 0x8000) << 1;
}
+/* Extract the 21-bit signed immediate offset from the microMIPS instruction
+ INSN. */
+
+static LONGEST
+micromips_relative_offset21 (ULONGEST insn)
+{
+ return ((b0s21_imm (insn) ^ 0x100000) - 0x100000) << 1;
+}
+
+/* Extract the 26-bit signed immediate offset from the microMIPS instruction
+ INSN. */
+
+static LONGEST
+micromips_relative_offset26 (ULONGEST insn)
+{
+ return ((b0s26_imm (insn) ^ 0x2000000) - 0x2000000) << 1;
+}
+
/* Return the size in bytes of the microMIPS instruction at the address PC. */
static int
@@ -1832,7 +3137,7 @@ micromips_pc_insn_size (struct gdbarch *gdbarch, CORE_ADDR pc)
ULONGEST insn;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
- return mips_insn_size (ISA_MICROMIPS, insn);
+ return mips_insn_size (gdbarch, ISA_MICROMIPS, insn);
}
/* Calculate the address of the next microMIPS instruction to execute
@@ -1866,6 +3171,284 @@ micromips_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
return pc;
}
+static CORE_ADDR
+get_micromipsr6_branch_target (struct frame_info *frame, CORE_ADDR pc)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ ULONGEST insn;
+ LONGEST reg_val1;
+ int mips64bitreg = 0;
+
+ if (mips_isa_regsize (gdbarch) == 8)
+ mips64bitreg = 1;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
+ pc += MIPS_INSN16_SIZE;
+ switch (mips_insn_size (gdbarch, ISA_MICROMIPS, insn))
+ {
+ /* 48-bit instructions. */
+ case 3 * MIPS_INSN16_SIZE: /* POOL48A: bits 011111 */
+ /* No branch or jump instructions in this category. */
+ pc += 2 * MIPS_INSN16_SIZE;
+ break;
+
+ /* 32-bit instructions. */
+ case 2 * MIPS_INSN16_SIZE:
+ insn <<= 16;
+ insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
+ pc += MIPS_INSN16_SIZE;
+ switch (micromips_op (insn >> 16))
+ {
+ case 0x00: /* POOL32A */
+ if (b0s6_op (insn) == 0x3c) /* POOL32Axf */
+ {
+ /* JALRC and JALRC.HB */
+ if (b6s10_ext (insn) == 0x3c || b6s10_ext (insn) == 0x7c)
+ pc = get_frame_register_signed (frame,
+ b0s5_reg (insn >> 16));
+ }
+ break;
+ case 0x10: /* POOL32I */
+ switch (b5s5_op (insn >> 16))
+ {
+ case 0x08: /* BC1EQZC */
+ case 0x09: /* BC1NEZC */
+ if (mips_regnum (gdbarch)->fp_control_status == -1)
+ break;
+ reg_val1 = get_frame_register_signed (frame,
+ b0s5_reg (insn >> 16));
+ if ((b5s5_op (insn >> 16) == 0x08 && (reg_val1 & 0x1) == 0)
+ || (b5s5_op (insn >> 16) == 0x09 && (reg_val1 & 0x1) != 0))
+ pc += micromips_relative_offset16 (insn);
+ break;
+ case 0x0a: /* BC2EQZC */
+ case 0x0b: /* BC2NEZC */
+ /* BC2*: don't know how to handle these. */
+ break;
+ case 0x19: /* BPOSGE32 */
+ {
+ int dspctl = mips_regnum (gdbarch)->dspctl;
+ if (dspctl == -1)
+ break;
+ if ((get_frame_register_unsigned (frame,
+ dspctl) & 0x7f) >= 32)
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+ }
+ break;
+ case 0x20: /* BEQZC/JIC */
+ if (b5s5_reg (insn >> 16) == 0) /* JIC */
+ {
+ reg_val1 = get_frame_register_signed (frame,
+ b0s5_reg (insn >> 16));
+ pc = reg_val1 + ((b0s16_imm (insn) ^ 0x8000) - 0x8000);
+ }
+ else
+ {
+ reg_val1 = get_frame_register_signed (frame,
+ b5s5_reg (insn >> 16));
+ if (reg_val1 == 0)
+ pc += micromips_relative_offset21 (insn);
+ }
+ break;
+ case 0x28: /* BNEZC/JIALC */
+ if (b5s5_reg (insn >> 16) == 0) /* JIALC */
+ {
+ reg_val1 = get_frame_register_signed (frame,
+ b0s5_reg (insn >> 16));
+ pc = reg_val1 + ((b0s16_imm (insn) ^ 0x8000) - 0x8000);
+ }
+ else
+ {
+ reg_val1 = get_frame_register_signed (frame,
+ b5s5_reg (insn >> 16));
+ if (reg_val1 != 0)
+ pc += micromips_relative_offset21 (insn);
+ }
+ break;
+ case 0x30: /* BLEZALC/BGEZALC/BGEUC */
+ {
+ int rt, rs;
+ rt = b5s5_reg (insn >> 16);
+ rs = b0s5_reg (insn >> 16);
+
+ if (((rt != 0 && rs == 0) /* BLEZALC */
+ && get_frame_register_signed (frame, rt) <= 0)
+ || ((rt == rs && rt != 0) /* BGEZALC */
+ && get_frame_register_signed (frame, rt) >= 0)
+ || ((rs != rt && rt != 0 && rs != 0) /* BGEUC */
+ && (get_frame_register_unsigned (frame, rs)
+ >= get_frame_register_unsigned (frame, rt))))
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+ case 0x38: /* BGTZALC/BLTZALC/BLTUC */
+ {
+ int rt, rs;
+ rt = b5s5_reg (insn >> 16);
+ rs = b0s5_reg (insn >> 16);
+
+ if (((rt != 0 && rs == 0) /* BGTZALC */
+ && get_frame_register_signed (frame, rt) > 0)
+ || ((rt == rs && rt != 0) /* BLTZALC */
+ && get_frame_register_signed (frame, rt) < 0)
+ || ((rs != rt && rt != 0 && rs != 0) /* BLTUC */
+ && (get_frame_register_unsigned (frame, rs)
+ < get_frame_register_unsigned (frame, rt))))
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+ case 0x1d: /* BOVC/BEQC/BEQZALC */
+ {
+ int rt = b5s5_reg (insn >> 16);
+ int rs = b0s5_reg (insn >> 16);
+ LONGEST val_rs = get_frame_register_signed (frame, rs);
+ LONGEST val_rt = get_frame_register_signed (frame, rt);
+ int ovf;
+
+ if (rs >= rt) /* BOVC */
+ {
+ if (mips64bitreg == 1)
+ ovf = is_add64bit_overflow (val_rs, val_rt);
+ else
+ ovf = is_add32bit_overflow (val_rs, val_rt);
+ if (ovf == 1)
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+
+ if ((rs < rt && val_rt == val_rs) /* BEQC */
+ || (rt != 0 && rs == 0 && val_rt == 0)) /* BEQZALC */
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+ case 0x25: /* BC */
+ case 0x2d: /* BALC */
+ pc += micromips_relative_offset26 (insn);
+ break;
+ case 0x35: /* BGTZC/BLTZC/BLTC */
+ {
+ int rt, rs;
+ rt = b5s5_reg (insn >> 16);
+ rs = b0s5_reg (insn >> 16);
+
+ if (((rt !=0 && rs == 0) /* BGTZC */
+ && get_frame_register_signed (frame, rt) > 0)
+ || ((rt == rs && rt != 0) /* BLTZC */
+ && get_frame_register_signed (frame, rt) < 0)
+ || ((rt != rs && rt != 0 && rs != 0) /* BLTC */
+ && get_frame_register_signed (frame, rs)
+ < get_frame_register_signed (frame, rt)))
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+ case 0x3d: /* BLEZC/BGEZC/BGEC */
+ {
+ int rt, rs;
+ rt = b5s5_reg (insn >> 16);
+ rs = b0s5_reg (insn >> 16);
+
+ if (((rt !=0 && rs == 0) /* BLEZC */
+ && get_frame_register_signed (frame, rt) <= 0)
+ || ((rt == rs && rt != 0) /* BGEZC */
+ && get_frame_register_signed (frame, rt) >= 0)
+ || ((rt != rs && rt != 0 && rs != 0) /* BGEC */
+ && get_frame_register_signed (frame, rs)
+ >= get_frame_register_signed (frame, rt)))
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+ case 0x1f: /* BNVC/BNEC/BNEZALC */
+ {
+ int rt = b5s5_reg (insn >> 16);
+ int rs = b0s5_reg (insn >> 16);
+ LONGEST val_rs = get_frame_register_signed (frame, rs);
+ LONGEST val_rt = get_frame_register_signed (frame, rt);
+ int ovf;
+
+ if (rs >= rt) /* BNVC */
+ {
+ if (mips64bitreg == 1)
+ ovf = is_add64bit_overflow (val_rs, val_rt);
+ else
+ ovf = is_add32bit_overflow (val_rs, val_rt);
+ if (ovf == 0)
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+
+ if ((rs < rt && val_rt != val_rs) /* BNEC */
+ || (rt != 0 && rs == 0 && val_rt != 0)) /* BNEZALC */
+ pc += micromips_relative_offset16 (insn);
+ break;
+ }
+ }
+ break;
+
+ /* 16-bit instructions. */
+ case MIPS_INSN16_SIZE:
+ switch (micromips_op (insn))
+ {
+ case 0x11: /* POOL16C */
+ switch (b0s5_imm (insn))
+ {
+ case 0x03: /* JRC16 */
+ case 0x0b: /* JALRC16 */
+ pc = get_frame_register_signed (frame, b5s5_reg (insn));
+ break;
+ case 0x13: /* JRCADDIUSP */
+ pc = get_frame_register_signed (frame, MIPS_RA_REGNUM);
+ break;
+ }
+ break;
+ case 0x23: /* BEQZC16 */
+ {
+ int rs = mips_reg3_to_reg[b7s3_reg (insn)];
+ if (get_frame_register_signed (frame, rs) == 0)
+ pc += micromips_relative_offset7 (insn);
+ break;
+ }
+ case 0x2b: /* BNEZC16 */
+ {
+ int rs = mips_reg3_to_reg[b7s3_reg (insn)];
+ if (get_frame_register_signed (frame, rs) != 0)
+ pc += micromips_relative_offset7 (insn);
+ break;
+ }
+ case 0x33: /* BC16 */
+ pc += micromips_relative_offset10 (insn);
+ break;
+ }
+ break;
+ }
+ return pc;
+}
+
+/* Calculate the address of the next microMIPS instruction to execute
+ after the INSN coprocessor 1 vector conditional branch instruction
+ at the address PC. */
+
+static CORE_ADDR
+micromips_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+ ULONGEST insn, CORE_ADDR pc)
+{
+ int op = b5s5_op (insn >> 16);
+ int wt = b0s5_reg (insn >> 16);
+ int taken;
+
+ /* Will the branch be taken? */
+ taken = mips_bc1_w_taken (gdbarch, frame, op, wt);
+
+ /* Calculate branch target */
+ if (taken > 0)
+ pc += micromips_relative_offset16 (insn);
+ else if (taken == 0)
+ pc += micromips_pc_insn_size (gdbarch, pc);
+
+ return pc;
+}
+
/* Calculate the address of the next microMIPS instruction to execute
after the instruction at the address PC. */
@@ -1875,9 +3458,12 @@ micromips_next_pc (struct frame_info *frame, CORE_ADDR pc)
struct gdbarch *gdbarch = get_frame_arch (frame);
ULONGEST insn;
+ if (is_mipsr6_isa (gdbarch))
+ return get_micromipsr6_branch_target (frame, pc);
+
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
pc += MIPS_INSN16_SIZE;
- switch (mips_insn_size (ISA_MICROMIPS, insn))
+ switch (mips_insn_size (gdbarch, ISA_MICROMIPS, insn))
{
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
@@ -1988,6 +3574,16 @@ micromips_next_pc (struct frame_info *frame, CORE_ADDR pc)
}
break;
+ case 0x20: /* POOL32D: bits 100000 */
+ if ((b5s5_op (insn) & 0x18) == 0x18
+ /* BZ.df: bits 100000 110xx */
+ /* BNZ.df: bits 100000 111xx */
+ || (b5s5_op (insn) & 0x1b) == 0x0b)
+ /* BZ.V: bits 100000 01011 */
+ /* BNZ.V: bits 100000 01111 */
+ pc = micromips_bc1_w_pc (gdbarch, frame, insn, pc);
+ break;
+
case 0x1d: /* JALS: bits 011101 */
case 0x35: /* J: bits 110101 */
case 0x3d: /* JAL: bits 111101 */
@@ -2377,21 +3973,162 @@ mips16_instruction_is_compact_branch (unsigned short insn)
or jump. */
static int
-micromips_instruction_is_compact_branch (unsigned short insn)
+micromips_instruction_is_compact_branch (struct frame_info *frame,
+ CORE_ADDR pc)
{
- switch (micromips_op (insn))
+ ULONGEST insn;
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
+ pc += MIPS_INSN16_SIZE;
+
+ if (! is_mipsr6_isa (gdbarch))
{
- case 0x11: /* POOL16C: bits 010001 */
- return (b5s5_op (insn) == 0x18
- /* JRADDIUSP: bits 010001 11000 */
- || b5s5_op (insn) == 0xd);
- /* JRC: bits 010011 01101 */
- case 0x10: /* POOL32I: bits 010000 */
- return (b5s5_op (insn) & 0x1d) == 0x5;
- /* BEQZC/BNEZC: bits 010000 001x1 */
- default:
- return 0;
+ switch (micromips_op (insn))
+ {
+ case 0x11: /* POOL16C: bits 010001 */
+ return (b5s5_op (insn) == 0x18
+ /* JRADDIUSP: bits 010001 11000 */
+ || b5s5_op (insn) == 0xd);
+ /* JRC: bits 010011 01101 */
+ case 0x10: /* POOL32I: bits 010000 */
+ return (b5s5_op (insn) & 0x1d) == 0x5;
+ /* BEQZC/BNEZC: bits 010000 001x1 */
+ default:
+ return 0;
+ }
+ }
+
+ switch (mips_insn_size (gdbarch, ISA_MICROMIPS, insn))
+ {
+ /* 32-bit instructions. */
+ case 2 * MIPS_INSN16_SIZE:
+ insn <<= 16;
+ insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
+ pc += MIPS_INSN16_SIZE;
+ switch (micromips_op (insn >> 16))
+ {
+ case 0x00: /* POOL32A */
+ if (b0s6_op (insn) == 0x3c) /* POOL32Axf */
+ {
+ /* JALRC and JALRC.HB */
+ if (b6s10_ext (insn) == 0x3c || b6s10_ext (insn) == 0x7c)
+ return 1;
+ }
+ break;
+ case 0x10: /* POOL32I */
+ switch (b5s5_op (insn >> 16))
+ {
+ case 0x08: /* BC1EQZC */
+ case 0x09: /* BC1NEZC */
+ case 0x0a: /* BC2EQZC */
+ case 0x0b: /* BC2NEZC */
+ return 1;
+ }
+ break;
+ case 0x20: /* BEQZC/JIC */
+ case 0x28: /* BNEZC/JIALC */
+ case 0x30: /* BLEZALC/BGEZALC/BGEUC */
+ case 0x38: /* BGTZALC/BLTZALC/BLTUC */
+ case 0x1d: /* BOVC/BEQC/BEQZALC */
+ case 0x25: /* BC */
+ case 0x2d: /* BALC */
+ case 0x35: /* BGTZC/BLTZC/BLTC */
+ case 0x3d: /* BLEZC/BGEZC/BGEC */
+ case 0x1f: /* BNVC/BNEC/BNEZALC */
+ return 1;
+ }
+ break;
+
+ /* 16-bit instructions. */
+ case MIPS_INSN16_SIZE:
+ switch (micromips_op (insn))
+ {
+ case 0x11: /* POOL16C */
+ switch (b0s5_imm (insn))
+ {
+ case 0x03: /* JRC16 */
+ case 0x0b: /* JALRC16 */
+ case 0x13: /* JRCADDIUSP */
+ return 1;
+ }
+ break;
+ case 0x23: /* BEQZC16 */
+ case 0x2b: /* BNEZC16 */
+ case 0x33: /* BC16 */
+ return 1;
+ }
+ break;
}
+ return 0;
+}
+
+/* Return non-zero if the MIPS instruction INSN is a compact branch
+ or jump. A value of 1 indicates an unconditional compact branch
+ and a value of 2 indicates a conditional compact branch. */
+
+static int
+mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn)
+{
+ switch (itype_op (insn))
+ {
+ /* BC */
+ case 50:
+ /* BALC */
+ case 58:
+ if (is_mipsr6_isa (gdbarch))
+ return 1;
+ break;
+ /* BOVC, BEQZALC, BEQC */
+ case 8:
+ /* BNVC, BNEZALC, BNEC */
+ case 24:
+ if (is_mipsr6_isa (gdbarch))
+ return 2;
+ break;
+ /* BEQZC, JIC */
+ case 54:
+ /* BNEZC, JIALC */
+ case 62:
+ if (is_mipsr6_isa (gdbarch))
+ /* JIC, JIALC are unconditional */
+ return (itype_rs (insn) == 0) ? 1 : 2;
+ break;
+ /* BLEZC, BGEZC, BGEC */
+ case 22:
+ /* BGTZC, BLTZC, BLTC */
+ case 23:
+ /* BLEZALC, BGEZALC, BGEUC */
+ case 6:
+ /* BGTZALC, BLTZALC, BLTUC */
+ case 7:
+ if (is_mipsr6_isa (gdbarch)
+ && itype_rt (insn) != 0)
+ return 2;
+ break;
+ /* BPOSGE32C */
+ case 1:
+ if (is_mipsr6_isa (gdbarch)
+ && itype_rt (insn) == 0x18 && itype_rs (insn) == 0)
+ return 2;
+ }
+ return 0;
+}
+
+/* Return non-zero if a standard MIPS instruction at ADDR has a branch
+ forbidden slot (i.e. it is a conditional compact branch instruction). */
+
+static int
+mips32_insn_at_pc_has_forbidden_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ ULONGEST insn;
+ int status;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
+ if (status)
+ return 0;
+
+ return mips32_instruction_is_compact_branch (gdbarch, insn) == 2;
}
struct mips_frame_cache
@@ -2983,7 +4720,7 @@ micromips_scan_prologue (struct gdbarch *gdbarch,
loc = 0;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, cur_pc, NULL);
loc += MIPS_INSN16_SIZE;
- switch (mips_insn_size (ISA_MICROMIPS, insn))
+ switch (mips_insn_size (gdbarch, ISA_MICROMIPS, insn))
{
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
@@ -3080,6 +4817,11 @@ micromips_scan_prologue (struct gdbarch *gdbarch,
/* LUI $v1 is used for larger $sp adjustments. */
/* Discard LUI $gp used for PIC code. */
case 0x10: /* POOL32I: bits 010000 */
+ if (is_mipsr6_isa (gdbarch))
+ {
+ this_non_prologue_insn = 1;
+ break;
+ }
if (b5s5_op (insn >> 16) == 0xd
/* LUI: bits 010000 001101 */
&& b0s5_reg (insn >> 16) == 3)
@@ -3092,7 +4834,25 @@ micromips_scan_prologue (struct gdbarch *gdbarch,
this_non_prologue_insn = 1;
break;
- /* ORI $v1 is used for larger $sp adjustments. */
+ case 0x04: /* R6 LUI/AUI */
+ if (! is_mipsr6_isa (gdbarch))
+ {
+ this_non_prologue_insn = 1;
+ break;
+ }
+ if (b0s5_reg (insn >> 16) == 0
+ /* LUI: bits 000100 rs 00000 */
+ && b5s5_reg (insn >> 16) == 3)
+ /* LUI $v1, imm */
+ v1_off = ((b0s16_imm (insn) << 16) ^ 0x80000000) - 0x80000000;
+ else if (b0s5_reg (insn >> 16) != 0
+ /* LUI: bits 000100 rs 00000 */
+ || b5s5_reg (insn >> 16) != 28)
+ /* LUI $gp, imm */
+ this_non_prologue_insn = 1;
+ break;
+
+ /* ORI $v1 is used for larger $sp adjustments. */
case 0x14: /* ORI: bits 010100 */
sreg = b0s5_reg (insn >> 16);
dreg = b5s5_reg (insn >> 16);
@@ -3154,7 +4914,7 @@ micromips_scan_prologue (struct gdbarch *gdbarch,
break;
case 0x11: /* POOL16C: bits 010001 */
- if (b6s4_op (insn) == 0x5)
+ if (! is_mipsr6_isa (gdbarch) && b6s4_op (insn) == 0x5)
/* SWM: bits 010001 0101 */
{
offset = ((b0s4_imm (insn) << 2) ^ 0x20) - 0x20;
@@ -3164,6 +4924,15 @@ micromips_scan_prologue (struct gdbarch *gdbarch,
set_reg_offset (gdbarch, this_cache,
MIPS_RA_REGNUM, sp + 4 * i++);
}
+ else if (is_mipsr6_isa (gdbarch) && b0s4_imm (insn) == 0xa)
+ {
+ offset = ((b4s4_imm (insn) << 2) ^ 0x20) - 0x20;
+ reglist = b8s2_regl (insn);
+ for (i = 0; i <= reglist; i++)
+ set_reg_offset (gdbarch, this_cache, 16 + i, sp + 4 * i);
+ set_reg_offset (gdbarch, this_cache,
+ MIPS_RA_REGNUM, sp + 4 * i++);
+ }
else
this_non_prologue_insn = 1;
break;
@@ -3206,7 +4975,7 @@ micromips_scan_prologue (struct gdbarch *gdbarch,
stack adjustment? If so, then we must have reached the end
of the prologue by now. */
if (prev_delay_slot || non_prologue_insns > 1 || sp_adj > 0
- || micromips_instruction_is_compact_branch (insn))
+ || micromips_instruction_is_compact_branch (this_frame, cur_pc))
break;
prev_non_prologue_insn = this_non_prologue_insn;
@@ -3441,7 +5210,8 @@ restart:
reg = high_word & 0x1f;
if (high_word == 0x27bd /* addiu $sp,$sp,-i */
- || high_word == 0x23bd /* addi $sp,$sp,-i */
+ || (high_word == 0x23bd /* addi $sp,$sp,-i */
+ && !is_mipsr6_isa (gdbarch))
|| high_word == 0x67bd) /* daddiu $sp,$sp,-i */
{
if (offset < 0) /* Negative stack adjustment? */
@@ -3576,7 +5346,8 @@ restart:
/* A jump or branch, or enough non-prologue insns seen? If so,
then we must have reached the end of the prologue by now. */
- if (prev_delay_slot || non_prologue_insns > 1)
+ if (prev_delay_slot || non_prologue_insns > 1
+ || mips32_instruction_is_compact_branch (gdbarch, inst))
break;
prev_non_prologue_insn = this_non_prologue_insn;
@@ -3882,6 +5653,60 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
#define LLD_OPCODE 0x34
#define SC_OPCODE 0x38
#define SCD_OPCODE 0x3c
+#define LLSC_R6_OPCODE 0x1f
+#define LL_R6_FUNCT 0x36
+#define LLE_FUNCT 0x2e
+#define LLD_R6_FUNCT 0x37
+#define SC_R6_FUNCT 0x26
+#define SCE_FUNCT 0x1e
+#define SCD_R6_FUNCT 0x27
+
+static int
+is_ll_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+ if (itype_op (insn) == LL_OPCODE
+ || itype_op (insn) == LLD_OPCODE)
+ return 1;
+
+ if (rtype_op (insn) == LLSC_R6_OPCODE
+ && rtype_funct (insn) == LLE_FUNCT
+ && (insn & 0x40) == 0)
+ return 1;
+
+ /* Handle LL and LLX varieties. */
+ if (is_mipsr6_isa (gdbarch)
+ && rtype_op (insn) == LLSC_R6_OPCODE
+ && (rtype_funct (insn) == LL_R6_FUNCT
+ || rtype_funct (insn) == LLD_R6_FUNCT
+ || rtype_funct (insn) == LLE_FUNCT))
+ return 1;
+
+ return 0;
+}
+
+static int
+is_sc_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+ if (itype_op (insn) == SC_OPCODE
+ || itype_op (insn) == SCD_OPCODE)
+ return 1;
+
+ if (rtype_op (insn) == LLSC_R6_OPCODE
+ && rtype_funct (insn) == SCE_FUNCT
+ && (insn & 0x40) == 0)
+ return 1;
+
+ /* Handle SC and NOT SCX. The SCX must come first so we
+ do not want to prematurely end the sequence. */
+ if (is_mipsr6_isa (gdbarch)
+ && rtype_op (insn) == LLSC_R6_OPCODE
+ && (rtype_funct (insn) == SC_R6_FUNCT
+ || rtype_funct (insn) == SCD_R6_FUNCT)
+ && (insn & 0x40) == 0)
+ return 1;
+
+ return 0;
+}
static int
mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
@@ -3895,10 +5720,11 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
int index;
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
const int atomic_sequence_length = 16; /* Instruction sequence length. */
+ int is_mipsr6 = is_mipsr6_isa (gdbarch);
insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL);
/* Assume all atomic sequences start with a ll/lld instruction. */
- if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
+ if (!is_ll_insn (gdbarch, insn))
return 0;
/* Assume that no atomic sequence is longer than "atomic_sequence_length"
@@ -3928,28 +5754,77 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
return 0; /* fallback to the standard single-step code. */
case 4: /* BEQ */
case 5: /* BNE */
- case 6: /* BLEZ */
- case 7: /* BGTZ */
case 20: /* BEQL */
case 21: /* BNEL */
- case 22: /* BLEZL */
- case 23: /* BGTTL */
+ case 22: /* BLEZL (BLEZC, BGEZC, BGEC) */
+ case 23: /* BGTZL (BGTZC, BLTZC, BLTC) */
is_branch = 1;
break;
+ case 6: /* BLEZ (BLEZALC, BGEZALC, BGEUC) */
+ case 7: /* BGTZ (BGTZALC, BLTZALC, BLTUC) */
+ if (is_mipsr6)
+ {
+ /* BLEZALC, BGTZALC */
+ if (itype_rs (insn) == 0 && itype_rt (insn) != 0)
+ return 0; /* fallback to the standard single-step code. */
+ /* BGEZALC, BLTZALC */
+ else if (itype_rs (insn) == itype_rt (insn)
+ && itype_rt (insn) != 0)
+ return 0; /* fallback to the standard single-step code. */
+ }
+ is_branch = 1;
+ break;
+ case 8: /* BOVC, BEQZALC, BEQC */
+ case 24: /* BNVC, BNEZALC, BNEC */
+ if (is_mipsr6)
+ is_branch = 1;
+ break;
+ case 50: /* BC */
+ case 58: /* BALC */
+ if (is_mipsr6)
+ return 0; /* fallback to the standard single-step code. */
+ break;
+ case 54: /* BEQZC, JIC */
+ case 62: /* BNEZC, JIALC */
+ if (is_mipsr6)
+ {
+ if (itype_rs (insn) == 0) /* JIC, JIALC */
+ return 0; /* fallback to the standard single-step code. */
+ else
+ is_branch = 2; /* Marker for branches with a 21-bit offset */
+ }
+ break;
case 17: /* COP1 */
- is_branch = ((itype_rs (insn) == 9 || itype_rs (insn) == 10)
- && (itype_rt (insn) & 0x2) == 0);
- if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+ is_branch = ((!is_mipsr6
+ && (itype_rs (insn) == 9 || itype_rs (insn) == 10)
+ && ((itype_rt (insn) & 0x2) == 0))
+ /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+ || (itype_rs (insn) & 0x18) == 0x18
+ /* BZ.df: 010001 110xx */
+ /* BNZ.df: 010001 111xx */
+ || (itype_rs (insn) & 0x1b) == 0x0b);
+ /* BZ.V: 010001 01011 */
+ /* BNZ.V: 010001 01111 */
+ if (is_branch)
break;
/* Fall through. */
case 18: /* COP2 */
case 19: /* COP3 */
- is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */
+ /* BCzF, BCzFL, BCzT, BCzTL, BC*EQZ, BC*NEZ */
+ is_branch = (itype_rs (insn) == 8)
+ || (is_mipsr6
+ && itype_op (insn) != 19
+ && (itype_rs (insn) == 9
+ || itype_rs (insn) == 13));
break;
}
if (is_branch)
{
- branch_bp = loc + mips32_relative_offset (insn) + 4;
+ /* Is this a special PC21_S2 branch? */
+ if (is_branch == 2)
+ branch_bp = loc + mips32_relative_offset21 (insn) + 4;
+ else
+ branch_bp = loc + mips32_relative_offset (insn) + 4;
if (last_breakpoint >= 1)
return 0; /* More than one branch found, fallback to the
standard single-step code. */
@@ -3957,12 +5832,12 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
last_breakpoint++;
}
- if (itype_op (insn) == SC_OPCODE || itype_op (insn) == SCD_OPCODE)
+ if (is_sc_insn (gdbarch, insn))
break;
}
/* Assume that the atomic sequence ends with a sc/scd instruction. */
- if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE)
+ if (!is_sc_insn (gdbarch, insn))
return 0;
loc += MIPS_INSN32_SIZE;
@@ -3997,17 +5872,30 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
ULONGEST insn;
int insn_count;
int index;
+ int ll_found = 0;
- /* Assume all atomic sequences start with a ll/lld instruction. */
+ /* Assume all atomic sequences start with a ll/lld/llx/lldx/lle/llxe
+ instruction. */
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL);
if (micromips_op (insn) != 0x18) /* POOL32C: bits 011000 */
return 0;
loc += MIPS_INSN16_SIZE;
insn <<= 16;
insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL);
- if ((b12s4_op (insn) & 0xb) != 0x3) /* LL, LLD: bits 011000 0x11 */
- return 0;
loc += MIPS_INSN16_SIZE;
+ if (b12s4_op (insn) == 0x6 /* LD-EVA bits 0110 */
+ && (b9s3_op (insn) == 0x6 /* LLE bits 110 */
+ || (is_mipsr6_isa (gdbarch)
+ && b9s3_op (insn) == 0x2))) /* LLXE bits 010 */
+ ll_found = 1;
+ else if (b12s4_op (insn) == 0x3 /* LL bits 0011 */
+ || b12s4_op (insn) == 0x7 /* LLD bits 0111 */
+ || b12s4_op (insn) == 0x1 /* LLX bits 0001 */
+ || b12s4_op (insn) == 0x5) /* LLDX bits 0101 */
+ ll_found = 1;
+
+ if (!ll_found)
+ return 0;
/* Assume all atomic sequences end with an sc/scd instruction. Assume
that no atomic sequence is longer than "atomic_sequence_length"
@@ -4021,15 +5909,157 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL);
loc += MIPS_INSN16_SIZE;
+ if (is_mipsr6_isa (gdbarch))
+ {
+ int rt, rs;
+ switch (mips_insn_size (gdbarch, ISA_MICROMIPS, insn))
+ {
+ /* 48-bit instructions. */
+ case 3 * MIPS_INSN16_SIZE: /* POOL48A: bits 011111 */
+ loc += 2 * MIPS_INSN16_SIZE;
+ break;
+
+ /* 32-bit instructions. */
+ case 2 * MIPS_INSN16_SIZE:
+ insn <<= 16;
+ insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS,
+ loc, NULL);
+ loc += MIPS_INSN16_SIZE;
+ switch (micromips_op (insn >> 16))
+ {
+ case 0x00: /* POOL32A: bits 000000 */
+ if (b0s6_op (insn) == 0x3c
+ && ((b6s10_ext (insn) == 0x7c) /* JALRC.HB */
+ || (b6s10_ext (insn) == 0x3c))) /* JALRC */
+ return 0;
+ break;
+
+ case 0x10: /* POOL32I */
+ switch (b5s5_op (insn >> 16))
+ {
+ case 0x08: /* BC1EQZC */
+ case 0x09: /* BC1NEZC */
+ case 0x0a: /* BC2EQZC */
+ case 0x0b: /* BC2NEZC */
+ case 0x19: /* BPOSGE32 */
+ branch_bp = loc + micromips_relative_offset16 (insn);
+ is_branch = 1;
+ }
+ break;
+
+ case 0x18: /* POOL32C: bits 011000 */
+ if ((b12s4_op (insn) & 0xb) == 0xb)
+ /* SC, SCD: bits 011000 1x11 */
+ sc_found = 1;
+ else if (b12s4_op (insn) == 0xa /* ST-EVA bits 1010 */
+ && b9s3_op (insn) == 0x6) /* SCE bits 110 */
+ sc_found = 1;
+ break;
+
+ case 0x20: /* BEQZC/JIC */
+ case 0x28: /* BNEZC/JIALC */
+ if (b5s5_reg (insn >> 16) == 0) /* JIC/JIALC */
+ return 0;
+ else
+ {
+ branch_bp = loc + micromips_relative_offset21 (insn);
+ is_branch = 1;
+ }
+ break;
+
+ case 0x30: /* BLEZALC/BGEZALC/BGEUC */
+ case 0x38: /* BGTZALC/BLTZALC/BLTUC */
+ case 0x35: /* BGTZC/BLTZC/BLTC */
+ case 0x3d: /* BLEZC/BGEZC/BGEC */
+ rt = b5s5_reg (insn >> 16);
+ rs = b0s5_reg (insn >> 16);
+ if ((rt != 0 && rs == 0)
+ /* BLEZALC/BGTZALC/BGTZC/BLEZC */
+ || (rt == rs && rt != 0)
+ /* BGEZALC/BLTZALC/BLTZC/BGEZC */
+ || (rs != rt && rt != 0 && rs != 0))
+ /* BGEUC/BLTUC/BLTC/BGEC */
+ {
+ branch_bp = loc + micromips_relative_offset16 (insn);
+ is_branch = 1;
+ }
+ break;
+
+ case 0x1d: /* BOVC/BEQC/BEQZALC */
+ case 0x1f: /* BNVC/BNEC/BNEZALC */
+ rt = b5s5_reg (insn >> 16);
+ rs = b0s5_reg (insn >> 16);
+ if ((rs >= rt) /* BOVC/BNVC */
+ || (rs < rt) /* BEQC/BNEC */
+ || (rt != 0 && rs == 0)) /* BEQZALC/BNEZALC */
+ {
+ branch_bp = loc + micromips_relative_offset16 (insn);
+ is_branch = 1;
+ }
+ break;
+
+ case 0x25: /* BC */
+ case 0x2d: /* BALC */
+ return 0;
+ }
+ break;
+
+ /* 16-bit instructions. */
+ case MIPS_INSN16_SIZE:
+ switch (micromips_op (insn))
+ {
+ case 0x11: /* POOL16C */
+ switch (b0s5_imm (insn))
+ {
+ case 0x03: /* JRC16 */
+ case 0x0b: /* JALRC16 */
+ case 0x13: /* JRCADDIUSP */
+ return 0;
+ }
+ break;
+
+ case 0x23: /* BEQZC16 */
+ case 0x2b: /* BNEZC16 */
+ branch_bp = loc + micromips_relative_offset7 (insn);
+ is_branch = 1;
+ break;
+
+ case 0x33: /* BC16 */
+ return 0; /* Fall back to the standard single-step code. */
+ }
+ break;
+ }/* switch */
+
+ if (is_branch)
+ {
+ if (last_breakpoint >= 1)
+ return 0; /* More than one branch found, fallback to the
+ standard single-step code. */
+ breaks[1] = branch_bp;
+ last_breakpoint++;
+ }
+ continue;
+ }
+
/* Assume that there is at most one conditional branch in the
atomic sequence. If a branch is found, put a breakpoint in
its destination address. */
- switch (mips_insn_size (ISA_MICROMIPS, insn))
+ switch (mips_insn_size (gdbarch, ISA_MICROMIPS, insn))
{
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
switch (micromips_op (insn))
{
+ case 0x20: /* POOL32D: bits 100000 */
+ if ((b5s5_op (insn) & 0x18) != 0x18
+ /* BZ.df: bits 100000 110xx */
+ /* BNZ.df: bits 100000 111xx */
+ && (b5s5_op (insn) & 0x1b) != 0x0b)
+ /* BZ.V: bits 100000 01011 */
+ /* BNZ.V: bits 100000 01111 */
+ break;
+ goto handle_branch;
+
case 0x10: /* POOL32I: bits 010000 */
if ((b5s5_op (insn) & 0x18) != 0x0
/* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */
@@ -4052,6 +6082,7 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
case 0x25: /* BEQ: bits 100101 */
case 0x2d: /* BNE: bits 101101 */
+handle_branch:
insn <<= 16;
insn |= mips_fetch_instruction (gdbarch,
ISA_MICROMIPS, loc, NULL);
@@ -4079,9 +6110,15 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
return 0; /* Fall back to the standard single-step code. */
case 0x18: /* POOL32C: bits 011000 */
+ insn <<= 16;
+ insn |= mips_fetch_instruction (gdbarch,
+ ISA_MICROMIPS, loc, NULL);
if ((b12s4_op (insn) & 0xb) == 0xb)
/* SC, SCD: bits 011000 1x11 */
sc_found = 1;
+ else if (b12s4_op (insn) == 0xa /* ST-EVA bits 1010 */
+ && b9s3_op (insn) == 0x6) /* SCE bits 110 */
+ sc_found = 1;
break;
}
loc += MIPS_INSN16_SIZE;
@@ -4185,8 +6222,14 @@ mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
gdb_assert (mips_pc_is_mips (pc));
insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
- hint = 0x7c0;
- return (insn & ~hint) == 0x3e00008; /* jr(.hb) $ra */
+ /* Mask the hint and the jalr/jr bit */
+ hint = 0x7c1;
+
+ if (is_mipsr6_isa (gdbarch) && insn == 0xd81f0000) /* jrc $31 */
+ return 1;
+
+ /* jr(.hb) $ra and "jalr(.hb) $ra" */
+ return ((insn & ~hint) == 0x3e00008);
}
@@ -4324,11 +6367,25 @@ heuristic-fence-post' command.\n",
break;
case 0x10: /* POOL32I: bits 010000 */
- if (b5s5_op (insn) == 0xd
+ if (! is_mipsr6_isa (gdbarch))
+ {
+ if (b5s5_op (insn) == 0xd
/* LUI: bits 010000 001101 */
- && b0s5_reg (insn >> 16) == 28)
+ && b0s5_reg (insn) == 28)
/* LUI $gp, imm */
- stop = 1;
+ stop = 1;
+ }
+ break;
+
+ case 0x04: /* LUI/AUI: bits 000100 */
+ if (is_mipsr6_isa (gdbarch))
+ {
+ if (b0s5_reg (insn) == 0
+ /* LUI: bits 000100 rt 000100 */
+ && b5s5_reg (insn) == 28)
+ /* LUI $gp, imm */
+ stop = 1;
+ }
break;
case 0x13: /* POOL16D: bits 010011 */
@@ -6180,79 +8237,64 @@ mips_o64_return_value (struct gdbarch *gdbarch, struct value *function,
and below). */
/* Copy a 32-bit single-precision value from the current frame
- into rare_buffer. */
+ into rare_buffer. This is done by reading the pseudo register and extracting
+ the relevant part so as not to duplicate code.
+ Returns 0 on failure. */
-static void
+static int
mips_read_fp_register_single (struct frame_info *frame, int regno,
gdb_byte *rare_buffer)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
- int raw_size = register_size (gdbarch, regno);
- gdb_byte *raw_buffer = (gdb_byte *) alloca (raw_size);
+ int cooked_size = register_size (gdbarch, regno);
+ gdb_byte *raw_buffer = alloca (cooked_size);
+ int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
- if (!deprecated_frame_register_read (frame, regno, raw_buffer))
- error (_("can't read register %d (%s)"),
- regno, gdbarch_register_name (gdbarch, regno));
- if (raw_size == 8)
- {
- /* We have a 64-bit value for this register. Find the low-order
- 32 bits. */
- int offset;
+ if (cooked_size < 4)
+ return 0;
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- offset = 4;
- else
- offset = 0;
+ if (cooked_size == 4)
+ /* FR=0 odd */
+ return deprecated_frame_register_read (frame, regno, rare_buffer);
- memcpy (rare_buffer, raw_buffer + offset, 4);
- }
+ if (!deprecated_frame_register_read (frame, regno, raw_buffer))
+ return 0;
+
+ if (cooked_size == 12)
+ /* FR=1, FRE=1
+ Single is after double. */
+ memcpy(rare_buffer, raw_buffer+8, 8);
+ else if (cooked_size == 8)
+ /* FR=1, FRE=0
+ Single is overlapping double. */
+ memcpy(rare_buffer, raw_buffer + 4*big_endian, 4);
else
- {
- memcpy (rare_buffer, raw_buffer, 4);
- }
+ return 0;
+ return 1;
}
/* Copy a 64-bit double-precision value from the current frame into
- rare_buffer. This may include getting half of it from the next
- register. */
+ rare_buffer. This is done by reading the pseudo register and extracting the
+ relevant part so as not to duplicate code.
+ Returns 0 on failure. */
-static void
+static int
mips_read_fp_register_double (struct frame_info *frame, int regno,
gdb_byte *rare_buffer)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
- int raw_size = register_size (gdbarch, regno);
+ int cooked_size = register_size (gdbarch, regno);
+ gdb_byte *raw_buffer = alloca (cooked_size);
- if (raw_size == 8 && !mips2_fp_compat (frame))
- {
- /* We have a 64-bit value for this register, and we should use
- all 64 bits. */
- if (!deprecated_frame_register_read (frame, regno, rare_buffer))
- error (_("can't read register %d (%s)"),
- regno, gdbarch_register_name (gdbarch, regno));
- }
- else
- {
- int rawnum = regno % gdbarch_num_regs (gdbarch);
+ if (cooked_size < 8)
+ /* FR=0 odd */
+ return 0;
- if ((rawnum - mips_regnum (gdbarch)->fp0) & 1)
- internal_error (__FILE__, __LINE__,
- _("mips_read_fp_register_double: bad access to "
- "odd-numbered FP register"));
+ if (!deprecated_frame_register_read (frame, regno, raw_buffer))
+ return 0;
- /* mips_read_fp_register_single will find the correct 32 bits from
- each register. */
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- mips_read_fp_register_single (frame, regno, rare_buffer + 4);
- mips_read_fp_register_single (frame, regno + 1, rare_buffer);
- }
- else
- {
- mips_read_fp_register_single (frame, regno, rare_buffer);
- mips_read_fp_register_single (frame, regno + 1, rare_buffer + 4);
- }
- }
+ memcpy(rare_buffer, raw_buffer, 8);
+ return 1;
}
static void
@@ -6260,48 +8302,70 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
int regnum)
{ /* Do values for FP (float) regs. */
struct gdbarch *gdbarch = get_frame_arch (frame);
+ int fpsize = mips_float_regsize (gdbarch);
gdb_byte *raw_buffer;
- double doub, flt1; /* Doubles extracted from raw hex data. */
- int inv1, inv2;
+ double doub = 0, flt1 = 0; /* Doubles extracted from raw hex data. */
+ int res1, res2, inv1, inv2;
- raw_buffer
- = ((gdb_byte *)
- alloca (2 * register_size (gdbarch, mips_regnum (gdbarch)->fp0)));
+ raw_buffer = alloca (2 * fpsize);
fprintf_filtered (file, "%s:", gdbarch_register_name (gdbarch, regnum));
fprintf_filtered (file, "%*s",
4 - (int) strlen (gdbarch_register_name (gdbarch, regnum)),
"");
- if (register_size (gdbarch, regnum) == 4 || mips2_fp_compat (frame))
+ switch (gdbarch_tdep (gdbarch)->fp_mode)
+ {
+ case MIPS_FPU_32:
+ fprintf_filtered (file, "FPU32 ");
+ break;
+ case MIPS_FPU_64:
+ fprintf_filtered (file, "FPU64 ");
+ break;
+ case MIPS_FPU_HYBRID:
+ fprintf_filtered (file, "HYBRID ");
+ break;
+ }
+
+ if (fpsize == 4)
{
struct value_print_options opts;
/* 4-byte registers: Print hex and floating. Also print even
numbered registers as doubles. */
- mips_read_fp_register_single (frame, regnum, raw_buffer);
- flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
- raw_buffer, &inv1);
+ res1 = mips_read_fp_register_single (frame, regnum, raw_buffer);
+ if (res1)
+ {
+ flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
+ raw_buffer, &inv1);
- get_formatted_print_options (&opts, 'x');
- print_scalar_formatted (raw_buffer,
- builtin_type (gdbarch)->builtin_uint32,
- &opts, 'w', file);
+ get_formatted_print_options (&opts, 'x');
+ print_scalar_formatted (raw_buffer,
+ builtin_type (gdbarch)->builtin_uint32,
+ &opts, 'w', file);
+ }
+ else
+ fprintf_filtered (file, "0x????????");
fprintf_filtered (file, " flt: ");
- if (inv1)
+ if (!res1)
+ fprintf_filtered (file, " <unavailable> ");
+ else if (inv1)
fprintf_filtered (file, " <invalid float> ");
else
fprintf_filtered (file, "%-17.9g", flt1);
if ((regnum - gdbarch_num_regs (gdbarch)) % 2 == 0)
{
- mips_read_fp_register_double (frame, regnum, raw_buffer);
- doub = unpack_double (builtin_type (gdbarch)->builtin_double,
- raw_buffer, &inv2);
+ res2 = mips_read_fp_register_double (frame, regnum, raw_buffer);
+ if (res2)
+ doub = unpack_double (builtin_type (gdbarch)->builtin_double,
+ raw_buffer, &inv2);
fprintf_filtered (file, " dbl: ");
- if (inv2)
+ if (!res2)
+ fprintf_filtered (file, "<unavailable>");
+ else if (inv2)
fprintf_filtered (file, "<invalid double>");
else
fprintf_filtered (file, "%-24.17g", doub);
@@ -6310,38 +8374,100 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
else
{
struct value_print_options opts;
+ int no_odd;
+
+ /* if top half isn't provided we can't access odd floats or doubles */
+ if ((regnum - gdbarch_num_regs (gdbarch)) & 1 &&
+ register_size (gdbarch, regnum % gdbarch_num_regs (gdbarch)) < 8)
+ {
+ fprintf_filtered (file, "<unavailable>");
+ return;
+ }
/* Eight byte registers: print each one as hex, float and double. */
- mips_read_fp_register_single (frame, regnum, raw_buffer);
- flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
- raw_buffer, &inv1);
+ res1 = mips_read_fp_register_single (frame, regnum, raw_buffer);
+ if (res1)
+ flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
+ raw_buffer, &inv1);
- mips_read_fp_register_double (frame, regnum, raw_buffer);
- doub = unpack_double (builtin_type (gdbarch)->builtin_double,
- raw_buffer, &inv2);
+ res2 = mips_read_fp_register_double (frame, regnum, raw_buffer);
+ if (res2)
+ {
+ doub = unpack_double (builtin_type (gdbarch)->builtin_double,
+ raw_buffer, &inv2);
- get_formatted_print_options (&opts, 'x');
- print_scalar_formatted (raw_buffer,
- builtin_type (gdbarch)->builtin_uint64,
- &opts, 'g', file);
+ get_formatted_print_options (&opts, 'x');
+ print_scalar_formatted (raw_buffer,
+ builtin_type (gdbarch)->builtin_uint64,
+ &opts, 'g', file);
+ }
+ else
+ fprintf_filtered (file, "0x????????????????");
fprintf_filtered (file, " flt: ");
- if (inv1)
- fprintf_filtered (file, "<invalid float>");
+ if (!res1)
+ fprintf_filtered (file, " <unavailable> ");
+ else if (inv1)
+ fprintf_filtered (file, " <invalid float>");
else
fprintf_filtered (file, "%-17.9g", flt1);
fprintf_filtered (file, " dbl: ");
- if (inv2)
+ if (!res2)
+ fprintf_filtered (file, "<unavailable> ");
+ else if (inv2)
fprintf_filtered (file, "<invalid double>");
else
fprintf_filtered (file, "%-24.17g", doub);
}
}
+/* Print a single complex control register */
+
static void
-mips_print_register (struct ui_file *file, struct frame_info *frame,
- int regnum)
+print_control_register (struct ui_file *file, struct frame_info *frame,
+ int regnum)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ const char *name = gdbarch_register_name (gdbarch, regnum);
+ struct value *val = value_of_register (regnum, frame);
+ struct type *regtype = value_type (val);
+ enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype));
+ struct value_print_options opts;
+ const gdb_byte *valaddr;
+
+ fputs_filtered (name, file);
+ print_spaces_filtered (15 - strlen (name), file);
+
+ if (!value_entirely_available (val))
+ {
+ fprintf_filtered (file, "*value not available*\n");
+ return;
+ }
+ else if (value_optimized_out (val))
+ {
+ val_print_optimized_out (val, file);
+ fprintf_filtered (file, "\n");
+ return;
+ }
+
+ valaddr = value_contents_for_printing (val);
+
+ /* Print raw value */
+ fprintf_filtered (file, "\t");
+ print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order);
+
+ /* Print it according to its natural format. */
+ get_user_print_options (&opts);
+ opts.deref_ref = 1;
+ fprintf_filtered (file, "\t");
+ val_print (regtype, valaddr,
+ value_embedded_offset (val), 0,
+ file, 0, val, &opts, current_language);
+}
+
+static void
+mips_print_register (struct ui_file *file, struct frame_info *frame, int regnum)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct value_print_options opts;
@@ -6352,6 +8478,18 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
mips_print_fp_register (file, frame, regnum);
return;
}
+ if (mips_vector_register_p (gdbarch, regnum))
+ {
+ default_print_registers_info (gdbarch, file, frame, regnum, 0);
+ return;
+ }
+ if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+ mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+ {
+ /* FP & MSA control registers */
+ print_control_register (file, frame, regnum);
+ return;
+ }
val = get_frame_register_value (frame, regnum);
@@ -6498,8 +8636,12 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
{
if (*gdbarch_register_name (gdbarch, regnum) == '\0')
continue; /* unused register */
- if (mips_float_register_p (gdbarch, regnum))
+ if (mips_float_register_p (gdbarch, regnum) ||
+ mips_vector_register_p (gdbarch, regnum))
break; /* End the row: reached FP register. */
+ if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+ mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+ break;
/* Large registers are handled separately. */
if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
{
@@ -6537,8 +8679,12 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
{
if (*gdbarch_register_name (gdbarch, regnum) == '\0')
continue; /* unused register */
- if (mips_float_register_p (gdbarch, regnum))
+ if (mips_float_register_p (gdbarch, regnum) ||
+ mips_vector_register_p (gdbarch, regnum))
break; /* End row: reached FP register. */
+ if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+ mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+ break;
if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
break; /* End row: large register. */
@@ -6570,6 +8716,19 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
return regnum;
}
+/* Print a single complex control register row */
+
+static int
+print_control_register_row (struct ui_file *file, struct frame_info *frame,
+ int regnum)
+{
+ print_control_register (file, frame, regnum);
+
+ fprintf_filtered (file, "\n");
+ ++regnum;
+ return regnum;
+}
+
/* MIPS_DO_REGISTERS_INFO(): called by "info register" command. */
static void
@@ -6580,7 +8739,7 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
{
gdb_assert (regnum >= gdbarch_num_regs (gdbarch));
if (*(gdbarch_register_name (gdbarch, regnum)) == '\0')
- error (_("Not a valid register for the current processor type"));
+ return;
mips_print_register (file, frame, regnum);
fprintf_filtered (file, "\n");
@@ -6599,6 +8758,26 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
else
regnum += MIPS_NUMREGS; /* Skip floating point regs. */
}
+ else if (mips_vector_register_p (gdbarch, regnum))
+ {
+ if (all) /* True for "INFO ALL-REGISTERS" command. */
+ {
+ default_print_registers_info (gdbarch, file, frame, regnum,
+ all);
+ ++regnum;
+ }
+ else
+ regnum += MIPS_NUMREGS; /* Skip vector regs. */
+ }
+ else if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+ mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+ {
+ /* FP & MSA control registers */
+ if (all) /* True for "INFO ALL-REGISTERS" command. */
+ regnum = print_control_register_row (file, frame, regnum);
+ else
+ ++regnum;
+ }
else
regnum = print_gp_register_row (file, frame, regnum);
}
@@ -6628,7 +8807,7 @@ mips_single_step_through_delay (struct gdbarch *gdbarch,
isa = mips_pc_isa (gdbarch, pc);
/* _has_delay_slot above will have validated the read. */
insn = mips_fetch_instruction (gdbarch, isa, pc, NULL);
- size = mips_insn_size (isa, insn);
+ size = mips_insn_size (gdbarch, isa, insn);
aspace = get_frame_address_space (frame);
return breakpoint_here_p (aspace, pc + size) != no_breakpoint_here;
}
@@ -6705,7 +8884,9 @@ mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
if (high_word != 0x27bd /* addiu $sp,$sp,offset */
&& high_word != 0x67bd /* daddiu $sp,$sp,offset */
- && inst != 0x03e00008 /* jr $ra */
+ && (inst & ~0x1) != 0x03e00008 /* jr $31 or jalr $0, $31 */
+ && (!is_mipsr6_isa (gdbarch)
+ || inst != 0xd81f0000) /* jrc $31 */
&& inst != 0x00000000) /* nop */
return 0;
}
@@ -6747,7 +8928,7 @@ micromips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
loc = 0;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
loc += MIPS_INSN16_SIZE;
- switch (mips_insn_size (ISA_MICROMIPS, insn))
+ switch (mips_insn_size (gdbarch, ISA_MICROMIPS, insn))
{
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
@@ -6786,13 +8967,26 @@ micromips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
return 0;
case 0x11: /* POOL16C: bits 010001 */
- if (b5s5_op (insn) == 0x18
+ if (is_mipsr6_isa (gdbarch))
+ {
+ if (b0s5_reg (insn) == 0x13
+ /* JRCADDIUSP: bits 010001 imm5 10011 */
+ || (b0s5_reg (insn) == 0x3
+ /* JRC16: bits 010001 rs 00011 */
+ && b5s5_op (insn) == MIPS_RA_REGNUM))
+ /* JRC16 $ra */
+ break;
+ }
+ else
+ {
+ if (b5s5_op (insn) == 0x18
/* JRADDIUSP: bits 010011 11000 */
- || (b5s5_op (insn) == 0xd
+ || (b5s5_op (insn) == 0xd
/* JRC: bits 010011 01101 */
&& b0s5_reg (insn) == MIPS_RA_REGNUM))
/* JRC $ra */
- break;
+ break;
+ }
return 0;
case 0x13: /* POOL16D: bits 010011 */
@@ -7022,20 +9216,32 @@ gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
if (mips_pc_is_mips16 (gdbarch, memaddr))
info->mach = bfd_mach_mips16;
else if (mips_pc_is_micromips (gdbarch, memaddr))
- info->mach = bfd_mach_mips_micromips;
+ {
+ if (is_mipsr6_isa (gdbarch))
+ info->mach = bfd_mach_mips_micromipsr6;
+ else
+ info->mach = bfd_mach_mips_micromips;
+ }
+
/* Round down the instruction address to the appropriate boundary. */
memaddr &= (info->mach == bfd_mach_mips16
- || info->mach == bfd_mach_mips_micromips) ? ~1 : ~3;
+ || info->mach == bfd_mach_mips_micromips
+ || info->mach == bfd_mach_mips_micromipsr6) ? ~1 : ~3;
/* Set the disassembler options. */
if (!info->disassembler_options)
+ {
/* This string is not recognized explicitly by the disassembler,
but it tells the disassembler to not try to guess the ABI from
the bfd elf headers, such that, if the user overrides the ABI
of a program linked as NewABI, the disassembly will follow the
register naming conventions specified by the user. */
- info->disassembler_options = "gpr-names=32";
+ if (is_mipsr6_isa (gdbarch))
+ info->disassembler_options = "gpr-names=32,dis-both-r5-and-r6=1";
+ else
+ info->disassembler_options = "gpr-names=32";
+ }
/* Call the appropriate disassembler based on the target endian-ness. */
if (info->endian == BFD_ENDIAN_BIG)
@@ -7049,7 +9255,10 @@ gdb_print_insn_mips_n32 (bfd_vma memaddr, struct disassemble_info *info)
{
/* Set up the disassembler info, so that we get the right
register names from libopcodes. */
- info->disassembler_options = "gpr-names=n32";
+ if (is_mipsr6_isa (info->application_data))
+ info->disassembler_options = "gpr-names=n32,dis-both-r5-and-r6=1";
+ else
+ info->disassembler_options = "gpr-names=n32";
info->flavour = bfd_target_elf_flavour;
return gdb_print_insn_mips (memaddr, info);
@@ -7060,7 +9269,10 @@ gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info)
{
/* Set up the disassembler info, so that we get the right
register names from libopcodes. */
- info->disassembler_options = "gpr-names=64";
+ if (is_mipsr6_isa (info->application_data))
+ info->disassembler_options = "gpr-names=64,dis-both-r5-and-r6=1";
+ else
+ info->disassembler_options = "gpr-names=64";
info->flavour = bfd_target_elf_flavour;
return gdb_print_insn_mips (memaddr, info);
@@ -7090,17 +9302,24 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch,
}
else if (mips_pc_is_micromips (gdbarch, pc))
{
+ static gdb_byte *ptr_16bit_bp;
static gdb_byte micromips16_big_breakpoint[] = { 0x46, 0x85 };
+ static gdb_byte micromipsr616_big_breakpoint[] = { 0x45, 0x5b };
static gdb_byte micromips32_big_breakpoint[] = { 0, 0x5, 0, 0x7 };
ULONGEST insn;
int err;
int size;
+ if (is_mipsr6_isa (gdbarch))
+ ptr_16bit_bp = micromipsr616_big_breakpoint;
+ else
+ ptr_16bit_bp = micromips16_big_breakpoint;
+
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &err);
- size = err ? 2 : mips_insn_size (ISA_MICROMIPS, insn);
+ size = err ? 2 : mips_insn_size (gdbarch, ISA_MICROMIPS, insn);
*pcptr = unmake_compact_addr (pc);
*lenptr = size;
- return (size == 2) ? micromips16_big_breakpoint
+ return (size == 2) ? ptr_16bit_bp
: micromips32_big_breakpoint;
}
else
@@ -7140,17 +9359,24 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch,
}
else if (mips_pc_is_micromips (gdbarch, pc))
{
+ static gdb_byte *ptr_16bit_bp;
static gdb_byte micromips16_little_breakpoint[] = { 0x85, 0x46 };
+ static gdb_byte micromipsr616_little_breakpoint[] = { 0x5b, 0x45 };
static gdb_byte micromips32_little_breakpoint[] = { 0x5, 0, 0x7, 0 };
ULONGEST insn;
int err;
int size;
+ if (is_mipsr6_isa (gdbarch))
+ ptr_16bit_bp = micromipsr616_little_breakpoint;
+ else
+ ptr_16bit_bp = micromips16_little_breakpoint;
+
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &err);
- size = err ? 2 : mips_insn_size (ISA_MICROMIPS, insn);
+ size = err ? 2 : mips_insn_size (gdbarch, ISA_MICROMIPS, insn);
*pcptr = unmake_compact_addr (pc);
*lenptr = size;
- return (size == 2) ? micromips16_little_breakpoint
+ return (size == 2) ? ptr_16bit_bp
: micromips32_little_breakpoint;
}
else
@@ -7202,7 +9428,7 @@ mips_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
int size;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
- size = status ? 2 : mips_insn_size (ISA_MICROMIPS, insn) == 2 ? 2 : 4;
+ size = status ? 2 : mips_insn_size (gdbarch, ISA_MICROMIPS, insn) == 2 ? 2 : 4;
*pcptr = unmake_compact_addr (pc);
*kindptr = size | 1;
}
@@ -7227,15 +9453,31 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
rs = itype_rs (inst);
rt = itype_rt (inst);
return (is_octeon_bbit_op (op, gdbarch)
- || op >> 2 == 5 /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
- || op == 29 /* JALX: bits 011101 */
+ || (op >> 1 == 10) /* BEQL, BNEL: bits 01010x */
+ || (op >> 1 == 11 && rt == 0) /* BLEZL, BGTZL: bits 01011x */
+ || (!is_mipsr6_isa (gdbarch) && op == 29) /* JALX: bits 011101 */
|| (op == 17
- && (rs == 8
+ && (rs == 8))
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
- || (rs == 9 && (rt & 0x2) == 0)
+ || (op == 17
+ && !is_mipsr6_isa (gdbarch)
+ && ((rs == 9 && (rt & 0x2) == 0)
/* BC1ANY2F, BC1ANY2T: bits 010001 01001 */
- || (rs == 10 && (rt & 0x2) == 0))));
+ || (rs == 10 && (rt & 0x2) == 0)))
/* BC1ANY4F, BC1ANY4T: bits 010001 01010 */
+ || (is_mipsr6_isa (gdbarch)
+ && ((op == 17
+ && ((rs == 9 /* BC1EQZ: 010001 01001 */
+ || rs == 13 /* BC1NEZ: 010001 01101 */ )
+ || ((rs & 0x18) == 0x18)
+ /* BZ.df: bits 010001 110xx */
+ /* BNZ.df: bits 010001 111xx */
+ || ((rs & 0x1b) == 0x0b)))
+ /* BZ.V: bits 010001 01011 */
+ /* BNZ.V: bits 010001 01111 */
+ || (op == 18
+ && (rs == 9 /* BC2EQZ: 010010 01001 */
+ || rs == 13 /* BC2NEZ: 010010 01101 */ )))));
}
else
switch (op & 0x07) /* extract bits 28,27,26 */
@@ -7254,7 +9496,11 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
|| ((rt & 0x1e) == 0x1c && rs == 0));
/* BPOSGE32, BPOSGE64: bits 1110x */
break; /* end REGIMM */
- default: /* J, JAL, BEQ, BNE, BLEZ, BGTZ */
+ case 6: /* BLEZ */
+ case 7: /* BGTZ */
+ return (itype_rt (inst) == 0);
+ break;
+ default: /* J, JAL, BEQ, BNE */
return 1;
break;
}
@@ -7306,6 +9552,13 @@ micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32)
case 0x35: /* J: bits 110101 */
case 0x2d: /* BNE: bits 101101 */
case 0x25: /* BEQ: bits 100101 */
+ case 0x20: /* POOL32D: bits 100000 */
+ return ((b5s5_op (major) & 0x18) == 0x18
+ /* BZ.df: bits 100000 110xx */
+ /* BNZ.df: bits 100000 111xx */
+ || ((b5s5_op (major) & 0x1b) == 0x0b));
+ /* BZ.V: bits 100000 01011 */
+ /* BNZ.V: bits 100000 01111 */
case 0x1d: /* JALS: bits 011101 */
return 1;
case 0x10: /* POOL32I: bits 010000 */
@@ -7349,10 +9602,13 @@ micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
int status;
int size;
+ if (is_mipsr6_isa (gdbarch))
+ return 0;
+
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
if (status)
return 0;
- size = mips_insn_size (ISA_MICROMIPS, insn);
+ size = mips_insn_size (gdbarch, ISA_MICROMIPS, insn);
insn <<= 16;
if (size == 2 * MIPS_INSN16_SIZE)
{
@@ -7466,7 +9722,18 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
So, we'll use the second solution. To do this we need to know if
the instruction we're trying to set the breakpoint on is in the
- branch delay slot. */
+ branch delay slot.
+
+ A similar problem occurs for breakpoints on forbidden slots where
+ the trap will be reported for the branch with the BD bit set.
+ In this case it would be ideal to recover using solution 1 from
+ above as there is no problem with the branch being skipped
+ (since the forbidden slot only exists on not-taken branches).
+ However, the BD bit is not available in all scenarios currently
+ so instead we move the breakpoint on to the next instruction.
+ This means that it is not possible to stop on an instruction
+ that can be in a forbidden slot even if that instruction is
+ jumped to directly. */
boundary = mips_segment_boundary (bpaddr);
@@ -7488,6 +9755,13 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
prev_addr = bpaddr - 4;
if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr))
bpaddr = prev_addr;
+ /* If the previous instruction has a forbidden slot, we have to
+ move the breakpoint to the following instruction to prevent
+ breakpoints in forbidden slots being reported as unknown
+ traps. */
+ else if (mips32_insn_at_pc_has_forbidden_slot (gdbarch, prev_addr))
+
+ bpaddr += 4;
}
else
{
@@ -7900,6 +10174,8 @@ mips_in_return_stub (struct gdbarch *gdbarch, CORE_ADDR pc, const char *name)
PC of the stub target. The stub just loads $t9 and jumps to it,
so that $t9 has the correct value at function entry. */
+/* TODO: Update for compact jump trampoline */
+
static CORE_ADDR
mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
@@ -8014,7 +10290,15 @@ mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num)
if (num >= 0 && num < 32)
regnum = num;
else if (num >= 32 && num < 64)
- regnum = num + mips_regnum (gdbarch)->fp0 - 32;
+ {
+ /* If FR=1, it could be referring to an MSA vector register (which aliases
+ the corresponding single and double precision fp register). Therefore
+ if vector registers are available use them instead. */
+ if (mips_regnum (gdbarch)->w0 != -1 && mips_float_regsize (gdbarch) == 8)
+ regnum = num + mips_regnum (gdbarch)->w0 - 32;
+ else
+ regnum = num + mips_regnum (gdbarch)->fp0 - 32;
+ }
else if (num == 64)
regnum = mips_regnum (gdbarch)->hi;
else if (num == 65)
@@ -8167,6 +10451,7 @@ value_of_mips_user_reg (struct frame_info *frame, const void *baton)
static struct gdbarch *
mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
+ struct gdbarch_tdep_info tdep_info = { NULL };
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
int elf_flags;
@@ -8181,7 +10466,16 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
int dspacc;
int dspctl;
+ /* Wire in an empty template tdep_info if one hasn't been supplied. */
+ if (info.tdep_info == NULL)
+ info.tdep_info = &tdep_info;
+
/* Fill in the OS dependent register numbers and names. */
+ mips_regnum.config5 = -1;
+ mips_regnum.w0 = -1;
+ mips_regnum.msa_ir = -1;
+ mips_regnum.msa_csr = -1;
+ mips_regnum.linux_restart = -1;
if (info.osabi == GDB_OSABI_IRIX)
{
mips_regnum.fp0 = 32;
@@ -8252,6 +10546,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
const struct tdesc_feature *feature;
int valid_p;
+ int fpsize;
feature = tdesc_find_feature (info.target_desc,
"org.gnu.gdb.mips.cpu");
@@ -8295,6 +10590,15 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
valid_p &= tdesc_numbered_register (feature, tdesc_data,
mips_regnum.cause, "cause");
+ /* Optionally, Config5 contains FP mode bits */
+ if (tdesc_unnumbered_register (feature, "config5"))
+ {
+ /* Allocate a new register. */
+ mips_regnum.config5 = num_regs++;
+ tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.config5, "config5");
+ }
+
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
@@ -8311,7 +10615,23 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return NULL;
}
+ /* Set the floating-point register size, assuming that whoever
+ supplied the description got the current setting right wrt
+ CP0 Status register's bit FR if applicable. */
+ fpsize = tdesc_register_size (feature, mips_fprs[0]) / 8;
+
+ /* Only accept a description whose floating-point register size
+ matches the requested size or if none was specified. */
+#if 0
+ valid_p = (info.tdep_info->fp_mode == MIPS_FPU_UNKNOWN
+ || info.tdep_info->fp_mode == fp_mode);
+ if (!valid_p) {
+ //valid_p = 1;
+ fpsize = info.tdep_info->fp_register_size;
+ }
+#else
valid_p = 1;
+#endif
for (i = 0; i < 32; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data,
i + mips_regnum.fp0, mips_fprs[i]);
@@ -8366,6 +10686,32 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
}
+ /* MSA vector control registers */
+ feature = tdesc_find_feature (info.target_desc,
+ "org.gnu.gdb.mips.msa");
+ if (feature != NULL)
+ {
+ /* Allocate a new registers. */
+ mips_regnum.w0 = num_regs;
+ num_regs += 32;
+ mips_regnum.msa_ir = num_regs++;
+ mips_regnum.msa_csr = num_regs++;
+
+ valid_p = 1;
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.msa_csr, "msacsr");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.msa_ir, "msair");
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ }
+
+ /* Fix the floating-point register size found. */
+ //info.tdep_info->fp_mode = fpsize;
+
/* It would be nice to detect an attempt to use a 64-bit ABI
when only 32-bit registers are provided. */
reg_names = NULL;
@@ -8504,6 +10850,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
switch (elf_fpu_type)
{
case Val_GNU_MIPS_ABI_FP_DOUBLE:
+ case Val_GNU_MIPS_ABI_FP_XX:
+ case Val_GNU_MIPS_ABI_FP_64:
+ case Val_GNU_MIPS_ABI_FP_64A:
fpu_type = MIPS_FPU_DOUBLE;
break;
case Val_GNU_MIPS_ABI_FP_SINGLE:
@@ -8576,6 +10925,13 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Be pedantic about which FPU is selected. */
if (gdbarch_tdep (arches->gdbarch)->mips_fpu_type != fpu_type)
continue;
+#if 1
+ /* Ditto the requested floating-point register size if any. */
+ if (info.tdep_info->fp_mode != MIPS_FPU_UNKNOWN
+ && (gdbarch_tdep (arches->gdbarch)->fp_mode)
+ != info.tdep_info->fp_mode)
+ continue;
+#endif
if (tdesc_data != NULL)
tdesc_data_cleanup (tdesc_data);
@@ -8593,6 +10949,21 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->mips_fpu_type = fpu_type;
tdep->register_size_valid_p = 0;
tdep->register_size = 0;
+#if 1
+ tdep->fp_mode = info.tdep_info->fp_mode;
+#endif
+ tdep->fp_register_mode_fixed_p = 0;
+ tdep->config5_type = NULL;
+ tdep->fp_rm_type = NULL;
+ tdep->fp_cflags_type = NULL;
+ tdep->fp_csr_type = NULL;
+ tdep->fp_ir_type = NULL;
+ tdep->fp32_type = NULL;
+ tdep->fp64_type = NULL;
+ tdep->fp96_type = NULL;
+ tdep->msa_128b_type = NULL;
+ tdep->msa_csr_type = NULL;
+ tdep->msa_ir_type = NULL;
if (info.target_desc)
{
@@ -8609,6 +10980,14 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
}
+ /* If we haven't figured out the size of floating-point registers
+ by now yet, then assume it is the same as for general-purpose
+ registers. */
+#if 1
+ if (tdep->fp_mode == MIPS_FPU_UNKNOWN)
+ tdep->fp_mode = mips_isa_regsize (gdbarch) == 8 ? MIPS_FPU_64 : MIPS_FPU_32;
+#endif
+
/* Initially set everything according to the default ABI/ISA. */
set_gdbarch_short_bit (gdbarch, 16);
set_gdbarch_int_bit (gdbarch, 32);
@@ -8830,6 +11209,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
set_gdbarch_register_type (gdbarch, mips_register_type);
+ set_gdbarch_regcache_changed (gdbarch, mips_set_float_regsize);
set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info);
@@ -8869,7 +11249,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
mips_register_g_packet_guesses (gdbarch);
/* Hook in OS ABI-specific overrides, if they have been registered. */
- info.tdep_info = tdesc_data;
+ info.tdep_info->tdesc_data = tdesc_data;
gdbarch_init_osabi (info, gdbarch);
/* The hook may have adjusted num_regs, fetch the final value and
diff --git a/gdb-7.11/gdb/mips-tdep.h b/gdb-7.11/gdb/mips-tdep.h
index 2e4d194d2..f2b914bc9 100644
--- a/gdb-7.11/gdb/mips-tdep.h
+++ b/gdb-7.11/gdb/mips-tdep.h
@@ -63,12 +63,17 @@ struct mips_regnum
int fp0;
int fp_implementation_revision;
int fp_control_status;
+ int config5;
int badvaddr; /* Bad vaddr for addressing exception. */
int cause; /* Describes last exception. */
int hi; /* Multiply/divide temp. */
int lo; /* ... */
int dspacc; /* SmartMIPS/DSP accumulators. */
int dspctl; /* DSP control. */
+ int w0;
+ int msa_ir;
+ int msa_csr;
+ int linux_restart;
};
extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
@@ -82,6 +87,15 @@ enum mips_fpu_type
MIPS_FPU_NONE /* No floating point. */
};
+enum mips_fpu_mode
+{
+ MIPS_FPU_UNKNOWN = 0,
+ MIPS_FPU_32, /* FR=0, 32bit FP regs, doubles in pairs. */
+ MIPS_FPU_64, /* FR=1, 64bit FP regs. */
+ MIPS_FPU_HYBRID, /* FR=1, FRE=1, 64bit FP regs, odd singles in upper half
+ of even doubles. */
+};
+
/* MIPS specific per-architecture information. */
struct gdbarch_tdep
{
@@ -113,11 +127,40 @@ struct gdbarch_tdep
int register_size_valid_p;
int register_size;
+ /* The floating-point register mode determined at run time.
+ This corresponds to CP0 Status register's FR bit and Config5's FRE bit
+ unless fixed_p is set. */
+ int fp_register_mode_fixed_p;
+ enum mips_fpu_mode fp_mode;
+
+ /* ISA-specific data types. */
+ struct type *config5_type;
+ struct type *fp_rm_type;
+ struct type *fp_cflags_type;
+ struct type *fp_csr_type;
+ struct type *fp_ir_type;
+ struct type *fp32_type;
+ struct type *fp64_type;
+ struct type *fp96_type;
+ struct type *msa_128b_type;
+ struct type *msa_csr_type;
+ struct type *msa_ir_type;
+
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
};
+/* MIPS specific per-architecture initialization information. */
+struct gdbarch_tdep_info
+{
+ /* Target description data. */
+ struct tdesc_arch_data *tdesc_data;
+
+ /* The floating-point register mode determined at run time. */
+ enum mips_fpu_mode fp_mode;
+};
+
/* Register numbers of various important registers. */
enum
@@ -137,11 +180,11 @@ enum
MIPS_EMBED_BADVADDR_REGNUM = 35,
MIPS_EMBED_CAUSE_REGNUM = 36,
MIPS_EMBED_PC_REGNUM = 37,
- MIPS_EMBED_FP0_REGNUM = 38,
+ MIPS_EMBED_FP0_REGNUM = 38, /* 32 double FP registers */
MIPS_UNUSED_REGNUM = 73, /* Never used, FIXME. */
MIPS_FIRST_EMBED_REGNUM = 74, /* First CP0 register for embedded use. */
MIPS_PRID_REGNUM = 89, /* Processor ID. */
- MIPS_LAST_EMBED_REGNUM = 89 /* Last one. */
+ MIPS_LAST_EMBED_REGNUM = 89, /* Last one. */
};
/* Defined in mips-tdep.c and used in remote-mips.c. */
diff --git a/gdb-7.11/gdb/regcache.c b/gdb-7.11/gdb/regcache.c
index f0ba0cf55..3cbec6e8d 100644
--- a/gdb-7.11/gdb/regcache.c
+++ b/gdb-7.11/gdb/regcache.c
@@ -489,6 +489,7 @@ struct regcache_list
};
static struct regcache_list *current_regcache;
+static int regcache_invalidated = 1;
struct regcache *
get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
@@ -534,16 +535,36 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
static ptid_t current_thread_ptid;
static struct gdbarch *current_thread_arch;
-struct regcache *
-get_thread_regcache (ptid_t ptid)
+static void
+set_current_thread_ptid_arch (ptid_t ptid)
{
if (!current_thread_arch || !ptid_equal (current_thread_ptid, ptid))
{
current_thread_ptid = ptid;
current_thread_arch = target_thread_architecture (ptid);
}
+}
+
+struct regcache *
+get_thread_regcache (ptid_t ptid)
+{
+ int registers_changed_p = current_regcache == NULL || regcache_invalidated;
+ struct regcache *new_regcache;
+
+ set_current_thread_ptid_arch (ptid);
+ new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
+
+ if (registers_changed_p
+ && gdbarch_regcache_changed_p (current_thread_arch)
+ && gdbarch_regcache_changed (current_thread_arch, new_regcache))
+ {
+ registers_changed ();
+ set_current_thread_ptid_arch (ptid);
+ new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
+ regcache_invalidated = 0;
+ }
- return get_thread_arch_regcache (ptid, current_thread_arch);
+ return new_regcache;
}
struct regcache *
@@ -627,6 +648,7 @@ registers_changed_ptid (ptid_t ptid)
forget about any frames we have cached, too. */
reinit_frame_cache ();
}
+ regcache_invalidated = 1;
}
void
diff --git a/gdb-7.11/gdb/regformats/mips-dsp-linux.dat b/gdb-7.11/gdb/regformats/mips-dsp-linux.dat
index ce37bf38b..47932561f 100644
--- a/gdb-7.11/gdb/regformats/mips-dsp-linux.dat
+++ b/gdb-7.11/gdb/regformats/mips-dsp-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
32:badvaddr
32:cause
32:pc
+32:config5
32:f0
32:f1
32:f2
diff --git a/gdb-7.11/gdb/regformats/mips-fpu64-dsp-linux.dat b/gdb-7.11/gdb/regformats/mips-fpu64-dsp-linux.dat
new file mode 100644
index 000000000..0eac27fa1
--- /dev/null
+++ b/gdb-7.11/gdb/regformats/mips-fpu64-dsp-linux.dat
@@ -0,0 +1,85 @@
+# DO NOT EDIT: generated from mips-fpu64-dsp-linux.xml
+name:mips_fpu64_dsp_linux
+xmltarget:mips-fpu64-dsp-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:config5
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+32:fcsr
+32:fir
+32:hi1
+32:lo1
+32:hi2
+32:lo2
+32:hi3
+32:lo3
+32:dspctl
+32:restart
diff --git a/gdb-7.11/gdb/regformats/mips-fpu64-linux.dat b/gdb-7.11/gdb/regformats/mips-fpu64-linux.dat
new file mode 100644
index 000000000..ad6c3c6e1
--- /dev/null
+++ b/gdb-7.11/gdb/regformats/mips-fpu64-linux.dat
@@ -0,0 +1,78 @@
+# DO NOT EDIT: generated from mips-fpu64-linux.xml
+name:mips_fpu64_linux
+xmltarget:mips-fpu64-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:config5
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+32:fcsr
+32:fir
+32:restart
diff --git a/gdb-7.11/gdb/regformats/mips-linux.dat b/gdb-7.11/gdb/regformats/mips-linux.dat
index d95e2c9ed..69457a6b1 100644
--- a/gdb-7.11/gdb/regformats/mips-linux.dat
+++ b/gdb-7.11/gdb/regformats/mips-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
32:badvaddr
32:cause
32:pc
+32:config5
32:f0
32:f1
32:f2
diff --git a/gdb-7.11/gdb/regformats/mips-msa-linux.dat b/gdb-7.11/gdb/regformats/mips-msa-linux.dat
new file mode 100644
index 000000000..033a464a4
--- /dev/null
+++ b/gdb-7.11/gdb/regformats/mips-msa-linux.dat
@@ -0,0 +1,80 @@
+# DO NOT EDIT: generated from mips-msa-linux.xml
+name:mips_msa_linux
+xmltarget:mips-msa-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:config5
+128:f0
+128:f1
+128:f2
+128:f3
+128:f4
+128:f5
+128:f6
+128:f7
+128:f8
+128:f9
+128:f10
+128:f11
+128:f12
+128:f13
+128:f14
+128:f15
+128:f16
+128:f17
+128:f18
+128:f19
+128:f20
+128:f21
+128:f22
+128:f23
+128:f24
+128:f25
+128:f26
+128:f27
+128:f28
+128:f29
+128:f30
+128:f31
+32:fcsr
+32:fir
+32:msacsr
+32:msair
+32:restart
diff --git a/gdb-7.11/gdb/regformats/mips64-dsp-linux.dat b/gdb-7.11/gdb/regformats/mips64-dsp-linux.dat
index e73df93d6..4f30a31d7 100644
--- a/gdb-7.11/gdb/regformats/mips64-dsp-linux.dat
+++ b/gdb-7.11/gdb/regformats/mips64-dsp-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
64:badvaddr
64:cause
64:pc
+64:config5
64:f0
64:f1
64:f2
diff --git a/gdb-7.11/gdb/regformats/mips64-linux.dat b/gdb-7.11/gdb/regformats/mips64-linux.dat
index 6770c8f65..43144caf5 100644
--- a/gdb-7.11/gdb/regformats/mips64-linux.dat
+++ b/gdb-7.11/gdb/regformats/mips64-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
64:badvaddr
64:cause
64:pc
+64:config5
64:f0
64:f1
64:f2
diff --git a/gdb-7.11/gdb/regformats/mips64-msa-linux.dat b/gdb-7.11/gdb/regformats/mips64-msa-linux.dat
new file mode 100644
index 000000000..0c8413341
--- /dev/null
+++ b/gdb-7.11/gdb/regformats/mips64-msa-linux.dat
@@ -0,0 +1,80 @@
+# DO NOT EDIT: generated from mips64-msa-linux.xml
+name:mips64_msa_linux
+xmltarget:mips64-msa-linux.xml
+expedite:r29,pc
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+64:r16
+64:r17
+64:r18
+64:r19
+64:r20
+64:r21
+64:r22
+64:r23
+64:r24
+64:r25
+64:r26
+64:r27
+64:r28
+64:r29
+64:r30
+64:r31
+64:status
+64:lo
+64:hi
+64:badvaddr
+64:cause
+64:pc
+64:config5
+128:f0
+128:f1
+128:f2
+128:f3
+128:f4
+128:f5
+128:f6
+128:f7
+128:f8
+128:f9
+128:f10
+128:f11
+128:f12
+128:f13
+128:f14
+128:f15
+128:f16
+128:f17
+128:f18
+128:f19
+128:f20
+128:f21
+128:f22
+128:f23
+128:f24
+128:f25
+128:f26
+128:f27
+128:f28
+128:f29
+128:f30
+128:f31
+64:fcsr
+64:fir
+64:msacsr
+64:msair
+64:restart
diff --git a/gdb-7.11/include/elf/common.h b/gdb-7.11/include/elf/common.h
index 087d876f6..595587458 100644
--- a/gdb-7.11/include/elf/common.h
+++ b/gdb-7.11/include/elf/common.h
@@ -580,6 +580,7 @@
/* note name must be "LINUX". */
#define NT_ARM_HW_WATCH 0x403 /* AArch hardware watchpoint registers */
/* note name must be "LINUX". */
+#define NT_MIPS_MSA 0x600 /* MIPS MSA vector registers. */
#define NT_SIGINFO 0x53494749 /* Fields of siginfo_t. */
#define NT_FILE 0x46494c45 /* Description of mapped files. */
diff --git a/gdb-7.11/include/gdb/signals.def b/gdb-7.11/include/gdb/signals.def
index 61cc88c1c..aadd41aad 100644
--- a/gdb-7.11/include/gdb/signals.def
+++ b/gdb-7.11/include/gdb/signals.def
@@ -194,7 +194,10 @@ SET (GDB_EXC_EMULATION, 148, "EXC_EMULATION", "Emulation instruction")
SET (GDB_EXC_SOFTWARE, 149, "EXC_SOFTWARE", "Software generated exception")
SET (GDB_EXC_BREAKPOINT, 150, "EXC_BREAKPOINT", "Breakpoint")
+/* Actually Linux MIPS has SIG128 as highest real time signal */
+SET (GDB_SIGNAL_REALTIME_128, 151, "SIG128", "Real-time event 128")
+
/* If you are adding a new signal, add it just above this comment. */
/* Last and unused enum value, for sizing arrays, etc. */
-SET (GDB_SIGNAL_LAST, 151, NULL, "GDB_SIGNAL_LAST")
+SET (GDB_SIGNAL_LAST, 152, NULL, "GDB_SIGNAL_LAST")
diff --git a/gdb-7.11/include/opcode/mips.h b/gdb-7.11/include/opcode/mips.h
index 88bf8f8f1..eace84065 100644
--- a/gdb-7.11/include/opcode/mips.h
+++ b/gdb-7.11/include/opcode/mips.h
@@ -1102,6 +1102,10 @@ struct mips_opcode
#define INSN2_VU0_CHANNEL_SUFFIX 0x00004000
/* Instruction has a forbidden slot. */
#define INSN2_FORBIDDEN_SLOT 0x00008000
+/* This indicates pre-R6 instructions mapped to R6 ones. */
+#define INSN2_CONVERTED_TO_COMPACT 0x00010000
+/* Instruction prevents the following instruction from being in a DS */
+#define INSN2_NEXT_NO_DS 0x00020000
/* Masks used to mark instructions to indicate which MIPS ISA level
they were introduced in. INSN_ISA_MASK masks an enumeration that
@@ -1256,6 +1260,15 @@ static const unsigned int mips_isa_table[] = {
#define ASE_MSA64 0x00001000
/* eXtended Physical Address (XPA) Extension. */
#define ASE_XPA 0x00002000
+/* MXU Extension. */
+#define ASE_MXU 0x00004000
+#define ASE_DSPR3 0x00008000
+/* The Virtualization ASE has eXtended Physical Address (XPA) Extension
+ instructions which are only valid when both ASEs are enabled. */
+#define ASE_VIRT_XPA 0x00010000
+/* The eXtended Physical Address (XPA) Extension has instructions which are
+ only valid for the r6 ISA. */
+#define ASE_EVA_R6 0x00020000
/* MIPS ISA defines, use instead of hardcoding ISA level. */
diff --git a/gdb-7.11/opcodes/micromips-opc.c b/gdb-7.11/opcodes/micromips-opc.c
index e182f470d..f063f3cda 100644
--- a/gdb-7.11/opcodes/micromips-opc.c
+++ b/gdb-7.11/opcodes/micromips-opc.c
@@ -108,6 +108,7 @@ decode_micromips_operand (const char *p)
case 'G': MSB (5, 11, 33, FALSE, 64); /* (33 .. 64), 64-bit op */
case 'H': MSB (5, 11, 1, FALSE, 64); /* (1 .. 32), 64-bit op */
case 'J': HINT (10, 16);
+ case 'M': HINT (16, 6);
case 'T': INT_ADJ (10, 16, 511, 0, FALSE); /* (-512 .. 511) << 0 */
case 'U': INT_ADJ (10, 16, 511, 1, FALSE); /* (-512 .. 511) << 1 */
case 'V': INT_ADJ (10, 16, 511, 2, FALSE); /* (-512 .. 511) << 2 */
@@ -253,6 +254,9 @@ decode_micromips_operand (const char *p)
are accepted as 64-bit microMIPS ISA. */
#define I1 INSN_ISA1
#define I3 INSN_ISA3
+#define I36 INSN_ISA32R5
+#define I37 INSN_ISA32R6
+#define I69 INSN_ISA64R6
/* MIPS DSP ASE support. */
#define WR_a WR_HILO /* Write DSP accumulators (reuse WR_HILO). */
@@ -995,6 +999,7 @@ const struct mips_opcode micromips_opcodes[] =
{"sh", "mq,mH(ml)", 0xa800, 0xfc00, RD_1|RD_3|SM, 0, I1, 0, 0 },
{"sh", "t,o(b)", 0x38000000, 0xfc000000, RD_1|RD_3|SM, 0, I1, 0, 0 },
{"sh", "t,A(b)", 0, (int) M_SH_AB, INSN_MACRO, 0, I1, 0, 0 },
+{"sigrie", "+M", 0x0000003f, 0xffc0003f, TRAP, 0, I37, 0, 0 },
{"sle", "d,v,t", 0, (int) M_SLE, INSN_MACRO, 0, I1, 0, 0 },
{"sle", "d,v,I", 0, (int) M_SLE_I, INSN_MACRO, 0, I1, 0, 0 },
{"sleu", "d,v,t", 0, (int) M_SLEU, INSN_MACRO, 0, I1, 0, 0 },
diff --git a/gdb-7.11/opcodes/mips-dis.c b/gdb-7.11/opcodes/mips-dis.c
index e15287664..becf98089 100644
--- a/gdb-7.11/opcodes/mips-dis.c
+++ b/gdb-7.11/opcodes/mips-dis.c
@@ -661,6 +661,23 @@ const struct mips_arch_choice mips_arch_choices[] =
{ "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3, 0,
mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
mips_hwr_names_numeric },
+
+ { "", 1, bfd_mach_mips_micromips, CPU_MIPS32R5,
+ ISA_MIPS32R5,
+ (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
+ | ASE_MT | ASE_MCU | ASE_VIRT | ASE_VIRT_XPA | ASE_MSA | ASE_XPA
+ | ASE_MXU),
+ mips_cp0_names_mips3264r2,
+ mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
+ mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
+
+ { "", 1, bfd_mach_mips_micromipsr6, CPU_MIPS32R6,
+ ISA_MIPS32R6,
+ (ASE_EVA | ASE_EVA_R6 | ASE_MSA | ASE_VIRT | ASE_VIRT_XPA | ASE_XPA |
+ ASE_MCU | ASE_MT | ASE_DSPR3),
+ mips_cp0_names_mips3264r2,
+ mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
+ mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 }
};
/* ISA and processor type to disassemble for, and register names to use.
@@ -668,6 +685,7 @@ const struct mips_arch_choice mips_arch_choices[] =
values. */
static int mips_processor;
static int mips_isa;
+static int alt_isa = -1;
static int mips_ase;
static int micromips_ase;
static const char * const *mips_gpr_names;
@@ -764,6 +782,17 @@ is_micromips (Elf_Internal_Ehdr *header)
return 0;
}
+/* Check if ISA is R6. */
+
+static inline int
+is_isa_r6 (unsigned long isa)
+{
+ if ((isa & INSN_ISA_MASK) == ISA_MIPS32R6
+ || ((isa & INSN_ISA_MASK) == ISA_MIPS64R6))
+ return 1;
+ return 0;
+}
+
static void
set_default_mips_dis_options (struct disassemble_info *info)
{
@@ -836,6 +865,17 @@ parse_mips_dis_option (const char *option, unsigned int len)
return;
}
+ if (CONST_STRNEQ (option, "dis-both-r5-and-r6"))
+ {
+ if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6)
+ alt_isa = ISA_MIPS32R5;
+ else if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
+ alt_isa = ISA_MIPS64R5;
+ else
+ alt_isa = -1;
+ return;
+ }
+
if (CONST_STRNEQ (option, "msa"))
{
mips_ase |= ASE_MSA;
@@ -1702,10 +1742,12 @@ print_insn_mips (bfd_vma memaddr,
&& (word & op->mask) == op->match)
{
/* We always disassemble the jalx instruction, except for MIPS r6. */
- if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
- && (strcmp (op->name, "jalx")
- || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
- || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
+ if ((!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
+ && (alt_isa == -1
+ || !opcode_is_member (op, alt_isa, 0, 0))
+ && (strcmp (op->name, "jalx")
+ || is_isa_r6 (mips_isa)))
+ || (op->pinfo2 & INSN2_CONVERTED_TO_COMPACT))
continue;
/* Figure out instruction type and branch delay information. */
@@ -2320,7 +2362,8 @@ _print_insn_mips (bfd_vma memaddr,
if (info->mach == bfd_mach_mips16)
return print_insn_mips16 (memaddr, info);
- if (info->mach == bfd_mach_mips_micromips)
+ if (info->mach == bfd_mach_mips_micromips
+ || info->mach == bfd_mach_mips_micromipsr6)
return print_insn_micromips (memaddr, info);
print_insn_compr = !micromips_ase ? print_insn_mips16 : print_insn_micromips;
diff --git a/gdb-7.11/opcodes/mips-opc.c b/gdb-7.11/opcodes/mips-opc.c
index 79a841776..c5c775502 100644
--- a/gdb-7.11/opcodes/mips-opc.c
+++ b/gdb-7.11/opcodes/mips-opc.c
@@ -1243,9 +1243,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"ldc1", "E,A(b)", 0, (int) M_LDC1_AB, INSN_MACRO, INSN2_M_FP_D, I2, 0, SF },
{"l.d", "T,o(b)", 0xd4000000, 0xfc000000, WR_1|RD_3|CLD|FP_D, 0, I2, 0, SF }, /* ldc1 */
{"l.d", "T,A(b)", 0, (int) M_L_DAB, INSN_MACRO, INSN2_M_FP_D, I1, 0, 0 },
-{"ldc2", "E,+:(d)", 0x49c00000, 0xffe00000, RD_3|WR_C2|CLD, 0, I37, 0, 0 },
-{"ldc2", "E,o(b)", 0xd8000000, 0xfc000000, RD_3|WR_CC|CLD, 0, I2, 0, IOCT|IOCTP|IOCT2|EE|I37 },
-{"ldc2", "E,A(b)", 0, (int) M_LDC2_AB, INSN_MACRO, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
+/* ldc2 is at the end of the table. */
{"ldc3", "E,o(b)", 0xdc000000, 0xfc000000, RD_3|WR_CC|CLD, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
{"ldc3", "E,A(b)", 0, (int) M_LDC3_AB, INSN_MACRO, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
{"ldl", "t,o(b)", 0x68000000, 0xfc000000, WR_1|RD_3|LM, 0, I3, 0, I69 },
@@ -1812,9 +1810,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"sdc1", "E,o(b)", 0xf4000000, 0xfc000000, RD_1|RD_3|SM|FP_D, 0, I2, 0, SF },
{"sdc1", "T,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, INSN2_M_FP_D, I2, 0, SF },
{"sdc1", "E,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, INSN2_M_FP_D, I2, 0, SF },
-{"sdc2", "E,+:(d)", 0x49e00000, 0xffe00000, RD_3|RD_C2|SM, 0, I37, 0, 0 },
-{"sdc2", "E,o(b)", 0xf8000000, 0xfc000000, RD_3|RD_C2|SM, 0, I2, 0, IOCT|IOCTP|IOCT2|EE|I37 },
-{"sdc2", "E,A(b)", 0, (int) M_SDC2_AB, INSN_MACRO, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
+/* sdc2 is at the end of the table. */
{"sdc3", "E,o(b)", 0xfc000000, 0xfc000000, RD_3|RD_C3|SM, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
{"sdc3", "E,A(b)", 0, (int) M_SDC3_AB, INSN_MACRO, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
{"s.d", "T,o(b)", 0xf4000000, 0xfc000000, RD_1|RD_3|SM|FP_D, 0, I2, 0, SF },
@@ -3347,6 +3343,12 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"cop3", "C", 0, (int) M_COP3, INSN_MACRO, 0, I1, 0, IOCT|IOCTP|IOCT2 },
/* RFE conflicts with the new Virt spec instruction tlbgp. */
{"rfe", "", 0x42000010, 0xffffffff, 0, 0, I1|T3, 0, 0 },
+{"ldc2", "E,+:(d)", 0x49c00000, 0xffe00000, RD_3|WR_C2|CLD, 0, I37, 0, 0 },
+{"ldc2", "E,o(b)", 0xd8000000, 0xfc000000, RD_3|WR_CC|CLD, 0, I2, 0, IOCT|IOCTP|IOCT2|EE|I37 },
+{"ldc2", "E,A(b)", 0, (int) M_LDC2_AB, INSN_MACRO, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
+{"sdc2", "E,+:(d)", 0x49e00000, 0xffe00000, RD_3|RD_C2|SM, 0, I37, 0, 0 },
+{"sdc2", "E,o(b)", 0xf8000000, 0xfc000000, RD_3|RD_C2|SM, 0, I2, 0, IOCT|IOCTP|IOCT2|EE|I37 },
+{"sdc2", "E,A(b)", 0, (int) M_SDC2_AB, INSN_MACRO, 0, I2, 0, IOCT|IOCTP|IOCT2|EE },
};
#define MIPS_NUM_OPCODES \