mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-gdbstub-170320-1' into staging
Testing and gdbstub updates: - docker updates for VirGL - re-factor gdbstub for static GDBState - re-factor gdbstub for dynamic arrays - add SVE support to arm gdbstub - add some guest debug tests to check-tcg - add aarch64 userspace register tests - remove packet size limit to gdbstub - simplify gdbstub monitor code - report vContSupported in gdbstub to use proper single-step # gpg: Signature made Tue 17 Mar 2020 17:47:46 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-and-gdbstub-170320-1: (28 commits) gdbstub: Fix single-step issue by confirming 'vContSupported+' feature to gdb gdbstub: do not split gdb_monitor_write payload gdbstub: change GDBState.last_packet to GByteArray tests/tcg/aarch64: add test-sve-ioctl guest-debug test tests/tcg/aarch64: add SVE iotcl test tests/tcg/aarch64: add a gdbstub testcase for SVE registers tests/guest-debug: add a simple test runner configure: allow user to specify what gdb to use tests/tcg/aarch64: userspace system register test target/arm: don't bother with id_aa64pfr0_read for USER_ONLY target/arm: generate xml description of our SVE registers target/arm: default SVE length to 64 bytes for linux-user target/arm: explicitly encode regnum in our XML target/arm: prepare for multiple dynamic XMLs gdbstub: extend GByteArray to read register helpers target/i386: use gdb_get_reg helpers target/m68k: use gdb_get_reg helpers target/arm: use gdb_get_reg helpers gdbstub: add helper for 128 bit registers gdbstub: move mem_buf to GDBState and use GByteArray ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -79,6 +79,7 @@ env:
|
||||
- MAIN_SOFTMMU_TARGETS="aarch64-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
|
||||
- CCACHE_SLOPPINESS="include_file_ctime,include_file_mtime"
|
||||
- CCACHE_MAXSIZE=1G
|
||||
- G_MESSAGES_DEBUG=error
|
||||
|
||||
|
||||
git:
|
||||
|
||||
@@ -303,6 +303,7 @@ libs_qga=""
|
||||
debug_info="yes"
|
||||
stack_protector=""
|
||||
use_containers="yes"
|
||||
gdb_bin=$(command -v "gdb")
|
||||
|
||||
if test -e "$source_path/.git"
|
||||
then
|
||||
@@ -1598,6 +1599,8 @@ for opt do
|
||||
;;
|
||||
--disable-fuzzing) fuzzing=no
|
||||
;;
|
||||
--gdb=*) gdb_bin="$optarg"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown option $opt"
|
||||
echo "Try '$0 --help' for more information"
|
||||
@@ -1783,6 +1786,7 @@ Advanced options (experts only):
|
||||
--enable-plugins
|
||||
enable plugins via shared library loading
|
||||
--disable-containers don't use containers for cross-building
|
||||
--gdb=GDB-path gdb to use for gdbstub tests [$gdb_bin]
|
||||
|
||||
Optional features, enabled with --enable-FEATURE and
|
||||
disabled with --disable-FEATURE, default is enabled if available:
|
||||
@@ -6785,6 +6789,7 @@ echo "libudev $libudev"
|
||||
echo "default devices $default_devices"
|
||||
echo "plugin support $plugins"
|
||||
echo "fuzzing support $fuzzing"
|
||||
echo "gdb $gdb_bin"
|
||||
|
||||
if test "$supported_cpu" = "no"; then
|
||||
echo
|
||||
@@ -7666,6 +7671,10 @@ if test "$plugins" = "yes" ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$gdb_bin" ; then
|
||||
echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$tcg_interpreter" = "yes"; then
|
||||
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
|
||||
elif test "$ARCH" = "sparc64" ; then
|
||||
|
||||
+1
-1
@@ -177,7 +177,7 @@ static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
|
||||
}
|
||||
|
||||
|
||||
static int cpu_common_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg)
|
||||
static int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
+49
-13
@@ -68,40 +68,76 @@ void gdb_signalled(CPUArchState *, int);
|
||||
void gdbserver_fork(CPUState *);
|
||||
#endif
|
||||
/* Get or set a register. Returns the size of the register. */
|
||||
typedef int (*gdb_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
|
||||
typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
|
||||
typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
|
||||
void gdb_register_coprocessor(CPUState *cpu,
|
||||
gdb_reg_cb get_reg, gdb_reg_cb set_reg,
|
||||
gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
|
||||
int num_regs, const char *xml, int g_pos);
|
||||
|
||||
/* The GDB remote protocol transfers values in target byte order. This means
|
||||
* we can use the raw memory access routines to access the value buffer.
|
||||
* Conveniently, these also handle the case where the buffer is mis-aligned.
|
||||
/*
|
||||
* The GDB remote protocol transfers values in target byte order. As
|
||||
* the gdbstub may be batching up several register values we always
|
||||
* append to the array.
|
||||
*/
|
||||
|
||||
static inline int gdb_get_reg8(uint8_t *mem_buf, uint8_t val)
|
||||
static inline int gdb_get_reg8(GByteArray *buf, uint8_t val)
|
||||
{
|
||||
stb_p(mem_buf, val);
|
||||
g_byte_array_append(buf, &val, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int gdb_get_reg16(uint8_t *mem_buf, uint16_t val)
|
||||
static inline int gdb_get_reg16(GByteArray *buf, uint16_t val)
|
||||
{
|
||||
stw_p(mem_buf, val);
|
||||
uint16_t to_word = tswap16(val);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_word, 2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static inline int gdb_get_reg32(uint8_t *mem_buf, uint32_t val)
|
||||
static inline int gdb_get_reg32(GByteArray *buf, uint32_t val)
|
||||
{
|
||||
stl_p(mem_buf, val);
|
||||
uint32_t to_long = tswap32(val);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_long, 4);
|
||||
return 4;
|
||||
}
|
||||
|
||||
static inline int gdb_get_reg64(uint8_t *mem_buf, uint64_t val)
|
||||
static inline int gdb_get_reg64(GByteArray *buf, uint64_t val)
|
||||
{
|
||||
stq_p(mem_buf, val);
|
||||
uint64_t to_quad = tswap64(val);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
|
||||
return 8;
|
||||
}
|
||||
|
||||
static inline int gdb_get_reg128(GByteArray *buf, uint64_t val_hi,
|
||||
uint64_t val_lo)
|
||||
{
|
||||
uint64_t to_quad;
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
to_quad = tswap64(val_hi);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
|
||||
to_quad = tswap64(val_lo);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
|
||||
#else
|
||||
to_quad = tswap64(val_lo);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
|
||||
to_quad = tswap64(val_hi);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
|
||||
#endif
|
||||
return 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdb_get_reg_ptr: get pointer to start of last element
|
||||
* @len: length of element
|
||||
*
|
||||
* This is a helper function to extract the pointer to the last
|
||||
* element for additional processing. Some front-ends do additional
|
||||
* dynamic swapping of the elements based on CPU state.
|
||||
*/
|
||||
static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len)
|
||||
{
|
||||
return buf->data + buf->len - len;
|
||||
}
|
||||
|
||||
#if TARGET_LONG_BITS == 64
|
||||
#define gdb_get_regl(buf, val) gdb_get_reg64(buf, val)
|
||||
#define ldtul_p(addr) ldq_p(addr)
|
||||
|
||||
@@ -195,7 +195,7 @@ typedef struct CPUClass {
|
||||
hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
|
||||
MemTxAttrs *attrs);
|
||||
int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
|
||||
int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
|
||||
bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
|
||||
void (*debug_excp_handler)(CPUState *cpu);
|
||||
|
||||
+1
-1
@@ -280,7 +280,7 @@ void alpha_cpu_do_interrupt(CPUState *cpu);
|
||||
bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags);
|
||||
hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
|
||||
MMUAccessType access_type,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
int alpha_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
int alpha_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(cs);
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
|
||||
+4
-3
@@ -195,9 +195,10 @@ static void arm_cpu_reset(CPUState *s)
|
||||
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
|
||||
/* and to the SVE instructions */
|
||||
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
|
||||
/* with maximum vector length */
|
||||
env->vfp.zcr_el[1] = cpu_isar_feature(aa64_sve, cpu) ?
|
||||
cpu->sve_max_vq - 1 : 0;
|
||||
/* with reasonable vector length */
|
||||
if (cpu_isar_feature(aa64_sve, cpu)) {
|
||||
env->vfp.zcr_el[1] = MIN(cpu->sve_max_vq - 1, 3);
|
||||
}
|
||||
/*
|
||||
* Enable TBI0 and TBI1. While the real kernel only enables TBI0,
|
||||
* turning on both here will produce smaller code and otherwise
|
||||
|
||||
+20
-11
@@ -128,14 +128,20 @@ enum {
|
||||
/**
|
||||
* DynamicGDBXMLInfo:
|
||||
* @desc: Contains the XML descriptions.
|
||||
* @num_cpregs: Number of the Coprocessor registers seen by GDB.
|
||||
* @cpregs_keys: Array that contains the corresponding Key of
|
||||
* a given cpreg with the same order of the cpreg in the XML description.
|
||||
* @num: Number of the registers in this XML seen by GDB.
|
||||
* @data: A union with data specific to the set of registers
|
||||
* @cpregs_keys: Array that contains the corresponding Key of
|
||||
* a given cpreg with the same order of the cpreg
|
||||
* in the XML description.
|
||||
*/
|
||||
typedef struct DynamicGDBXMLInfo {
|
||||
char *desc;
|
||||
int num_cpregs;
|
||||
uint32_t *cpregs_keys;
|
||||
int num;
|
||||
union {
|
||||
struct {
|
||||
uint32_t *keys;
|
||||
} cpregs;
|
||||
} data;
|
||||
} DynamicGDBXMLInfo;
|
||||
|
||||
/* CPU state for each instance of a generic timer (in cp15 c14) */
|
||||
@@ -749,7 +755,8 @@ struct ARMCPU {
|
||||
uint64_t *cpreg_vmstate_values;
|
||||
int32_t cpreg_vmstate_array_len;
|
||||
|
||||
DynamicGDBXMLInfo dyn_xml;
|
||||
DynamicGDBXMLInfo dyn_sysreg_xml;
|
||||
DynamicGDBXMLInfo dyn_svereg_xml;
|
||||
|
||||
/* Timers used by the generic (architected) timer */
|
||||
QEMUTimer *gt_timer[NUM_GTIMERS];
|
||||
@@ -968,13 +975,15 @@ bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
|
||||
MemTxAttrs *attrs);
|
||||
|
||||
int arm_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
/* Dynamically generates for gdb stub an XML description of the sysregs from
|
||||
* the cp_regs hashtable. Returns the registered sysregs number.
|
||||
/*
|
||||
* Helpers to dynamically generates XML descriptions of the sysregs
|
||||
* and SVE registers. Returns the number of registers in each set.
|
||||
*/
|
||||
int arm_gen_dynamic_xml(CPUState *cpu);
|
||||
int arm_gen_dynamic_sysreg_xml(CPUState *cpu, int base_reg);
|
||||
int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
|
||||
|
||||
/* Returns the dynamically generated XML for the gdb stub.
|
||||
* Returns a pointer to the XML contents for the specified XML file or NULL
|
||||
@@ -988,7 +997,7 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||
int cpuid, void *opaque);
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
|
||||
void aarch64_sve_change_el(CPUARMState *env, int old_el,
|
||||
|
||||
+156
-17
@@ -24,6 +24,7 @@
|
||||
typedef struct RegisterSysregXmlParam {
|
||||
CPUState *cs;
|
||||
GString *s;
|
||||
int n;
|
||||
} RegisterSysregXmlParam;
|
||||
|
||||
/* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect
|
||||
@@ -32,7 +33,7 @@ typedef struct RegisterSysregXmlParam {
|
||||
We hack round this by giving the FPA regs zero size when talking to a
|
||||
newer gdb. */
|
||||
|
||||
int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
@@ -106,15 +107,16 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arm_gen_one_xml_reg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
|
||||
ARMCPRegInfo *ri, uint32_t ri_key,
|
||||
int bitsize)
|
||||
static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
|
||||
ARMCPRegInfo *ri, uint32_t ri_key,
|
||||
int bitsize, int regnum)
|
||||
{
|
||||
g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
|
||||
g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
|
||||
g_string_append_printf(s, " regnum=\"%d\"", regnum);
|
||||
g_string_append_printf(s, " group=\"cp_regs\"/>");
|
||||
dyn_xml->num_cpregs++;
|
||||
dyn_xml->cpregs_keys[dyn_xml->num_cpregs - 1] = ri_key;
|
||||
dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
|
||||
dyn_xml->num++;
|
||||
}
|
||||
|
||||
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
|
||||
@@ -126,12 +128,13 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
|
||||
GString *s = param->s;
|
||||
ARMCPU *cpu = ARM_CPU(param->cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_xml;
|
||||
DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
|
||||
|
||||
if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
|
||||
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
|
||||
if (ri->state == ARM_CP_STATE_AA64) {
|
||||
arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
|
||||
arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
|
||||
param->n++);
|
||||
}
|
||||
} else {
|
||||
if (ri->state == ARM_CP_STATE_AA32) {
|
||||
@@ -140,38 +143,174 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
|
||||
return;
|
||||
}
|
||||
if (ri->type & ARM_CP_64BIT) {
|
||||
arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
|
||||
arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
|
||||
param->n++);
|
||||
} else {
|
||||
arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 32);
|
||||
arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
|
||||
param->n++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int arm_gen_dynamic_xml(CPUState *cs)
|
||||
int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
GString *s = g_string_new(NULL);
|
||||
RegisterSysregXmlParam param = {cs, s};
|
||||
RegisterSysregXmlParam param = {cs, s, base_reg};
|
||||
|
||||
cpu->dyn_xml.num_cpregs = 0;
|
||||
cpu->dyn_xml.cpregs_keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
|
||||
cpu->dyn_sysreg_xml.num = 0;
|
||||
cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
|
||||
g_string_printf(s, "<?xml version=\"1.0\"?>");
|
||||
g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
|
||||
g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
|
||||
g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, ¶m);
|
||||
g_string_append_printf(s, "</feature>");
|
||||
cpu->dyn_xml.desc = g_string_free(s, false);
|
||||
return cpu->dyn_xml.num_cpregs;
|
||||
cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
|
||||
return cpu->dyn_sysreg_xml.num;
|
||||
}
|
||||
|
||||
struct TypeSize {
|
||||
const char *gdb_type;
|
||||
int size;
|
||||
const char sz, suffix;
|
||||
};
|
||||
|
||||
static const struct TypeSize vec_lanes[] = {
|
||||
/* quads */
|
||||
{ "uint128", 128, 'q', 'u' },
|
||||
{ "int128", 128, 'q', 's' },
|
||||
/* 64 bit */
|
||||
{ "uint64", 64, 'd', 'u' },
|
||||
{ "int64", 64, 'd', 's' },
|
||||
{ "ieee_double", 64, 'd', 'f' },
|
||||
/* 32 bit */
|
||||
{ "uint32", 32, 's', 'u' },
|
||||
{ "int32", 32, 's', 's' },
|
||||
{ "ieee_single", 32, 's', 'f' },
|
||||
/* 16 bit */
|
||||
{ "uint16", 16, 'h', 'u' },
|
||||
{ "int16", 16, 'h', 's' },
|
||||
{ "ieee_half", 16, 'h', 'f' },
|
||||
/* bytes */
|
||||
{ "uint8", 8, 'b', 'u' },
|
||||
{ "int8", 8, 'b', 's' },
|
||||
};
|
||||
|
||||
|
||||
int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
GString *s = g_string_new(NULL);
|
||||
DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
|
||||
g_autoptr(GString) ts = g_string_new("");
|
||||
int i, bits, reg_width = (cpu->sve_max_vq * 128);
|
||||
info->num = 0;
|
||||
g_string_printf(s, "<?xml version=\"1.0\"?>");
|
||||
g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
|
||||
g_string_append_printf(s, "<feature name=\"org.qemu.gdb.aarch64.sve\">");
|
||||
|
||||
/* First define types and totals in a whole VL */
|
||||
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||
int count = reg_width / vec_lanes[i].size;
|
||||
g_string_printf(ts, "vq%d%c%c", count,
|
||||
vec_lanes[i].sz, vec_lanes[i].suffix);
|
||||
g_string_append_printf(s,
|
||||
"<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
|
||||
ts->str, vec_lanes[i].gdb_type, count);
|
||||
}
|
||||
/*
|
||||
* Now define a union for each size group containing unsigned and
|
||||
* signed and potentially float versions of each size from 128 to
|
||||
* 8 bits.
|
||||
*/
|
||||
for (bits = 128; bits >= 8; bits /= 2) {
|
||||
int count = reg_width / bits;
|
||||
g_string_append_printf(s, "<union id=\"vq%dn\">", count);
|
||||
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||
if (vec_lanes[i].size == bits) {
|
||||
g_string_append_printf(s, "<field name=\"%c\" type=\"vq%d%c%c\"/>",
|
||||
vec_lanes[i].suffix,
|
||||
count,
|
||||
vec_lanes[i].sz, vec_lanes[i].suffix);
|
||||
}
|
||||
}
|
||||
g_string_append(s, "</union>");
|
||||
}
|
||||
/* And now the final union of unions */
|
||||
g_string_append(s, "<union id=\"vq\">");
|
||||
for (bits = 128; bits >= 8; bits /= 2) {
|
||||
int count = reg_width / bits;
|
||||
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||
if (vec_lanes[i].size == bits) {
|
||||
g_string_append_printf(s, "<field name=\"%c\" type=\"vq%dn\"/>",
|
||||
vec_lanes[i].sz, count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_string_append(s, "</union>");
|
||||
|
||||
/* Then define each register in parts for each vq */
|
||||
for (i = 0; i < 32; i++) {
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"z%d\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"vq\"/>",
|
||||
i, reg_width, base_reg++);
|
||||
info->num++;
|
||||
}
|
||||
/* fpscr & status registers */
|
||||
g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
|
||||
" regnum=\"%d\" group=\"float\""
|
||||
" type=\"int\"/>", base_reg++);
|
||||
g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
|
||||
" regnum=\"%d\" group=\"float\""
|
||||
" type=\"int\"/>", base_reg++);
|
||||
info->num += 2;
|
||||
/*
|
||||
* Predicate registers aren't so big they are worth splitting up
|
||||
* but we do need to define a type to hold the array of quad
|
||||
* references.
|
||||
*/
|
||||
g_string_append_printf(s,
|
||||
"<vector id=\"vqp\" type=\"uint16\" count=\"%d\"/>",
|
||||
cpu->sve_max_vq);
|
||||
for (i = 0; i < 16; i++) {
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"p%d\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"vqp\"/>",
|
||||
i, cpu->sve_max_vq * 16, base_reg++);
|
||||
info->num++;
|
||||
}
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"ffr\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"vqp\"/>",
|
||||
cpu->sve_max_vq * 16, base_reg++);
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"vg\" bitsize=\"64\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"uint32\"/>",
|
||||
base_reg++);
|
||||
info->num += 2;
|
||||
g_string_append_printf(s, "</feature>");
|
||||
cpu->dyn_svereg_xml.desc = g_string_free(s, false);
|
||||
|
||||
return cpu->dyn_svereg_xml.num;
|
||||
}
|
||||
|
||||
|
||||
const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
|
||||
if (strcmp(xmlname, "system-registers.xml") == 0) {
|
||||
return cpu->dyn_xml.desc;
|
||||
return cpu->dyn_sysreg_xml.desc;
|
||||
} else if (strcmp(xmlname, "sve-registers.xml") == 0) {
|
||||
return cpu->dyn_svereg_xml.desc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
int aarch64_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
|
||||
+154
-32
@@ -48,30 +48,27 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
|
||||
|
||||
static void switch_mode(CPUARMState *env, int mode);
|
||||
|
||||
static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
|
||||
|
||||
/* VFP data registers are always little-endian. */
|
||||
if (reg < nregs) {
|
||||
stq_le_p(buf, *aa32_vfp_dreg(env, reg));
|
||||
return 8;
|
||||
return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
|
||||
}
|
||||
if (arm_feature(env, ARM_FEATURE_NEON)) {
|
||||
/* Aliases for Q regs. */
|
||||
nregs += 16;
|
||||
if (reg < nregs) {
|
||||
uint64_t *q = aa32_vfp_qreg(env, reg - 32);
|
||||
stq_le_p(buf, q[0]);
|
||||
stq_le_p(buf + 8, q[1]);
|
||||
return 16;
|
||||
return gdb_get_reg128(buf, q[0], q[1]);
|
||||
}
|
||||
}
|
||||
switch (reg - nregs) {
|
||||
case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
|
||||
case 1: stl_p(buf, vfp_get_fpscr(env)); return 4;
|
||||
case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
|
||||
case 0: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); break;
|
||||
case 1: return gdb_get_reg32(buf, vfp_get_fpscr(env)); break;
|
||||
case 2: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -102,25 +99,21 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0 ... 31:
|
||||
/* 128 bit FP register */
|
||||
{
|
||||
uint64_t *q = aa64_vfp_qreg(env, reg);
|
||||
stq_le_p(buf, q[0]);
|
||||
stq_le_p(buf + 8, q[1]);
|
||||
return 16;
|
||||
}
|
||||
{
|
||||
/* 128 bit FP register - quads are in LE order */
|
||||
uint64_t *q = aa64_vfp_qreg(env, reg);
|
||||
return gdb_get_reg128(buf, q[1], q[0]);
|
||||
}
|
||||
case 32:
|
||||
/* FPSR */
|
||||
stl_p(buf, vfp_get_fpsr(env));
|
||||
return 4;
|
||||
return gdb_get_reg32(buf, vfp_get_fpsr(env));
|
||||
case 33:
|
||||
/* FPCR */
|
||||
stl_p(buf, vfp_get_fpcr(env));
|
||||
return 4;
|
||||
return gdb_get_reg32(buf,vfp_get_fpcr(env));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -209,13 +202,22 @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
}
|
||||
}
|
||||
|
||||
static int arm_gdb_get_sysreg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
/**
|
||||
* arm_get/set_gdb_*: get/set a gdb register
|
||||
* @env: the CPU state
|
||||
* @buf: a buffer to copy to/from
|
||||
* @reg: register number (offset from start of group)
|
||||
*
|
||||
* We return the number of bytes copied
|
||||
*/
|
||||
|
||||
static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
const ARMCPRegInfo *ri;
|
||||
uint32_t key;
|
||||
|
||||
key = cpu->dyn_xml.cpregs_keys[reg];
|
||||
key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
|
||||
ri = get_arm_cp_reginfo(cpu->cp_regs, key);
|
||||
if (ri) {
|
||||
if (cpreg_field_is_64bit(ri)) {
|
||||
@@ -232,6 +234,102 @@ static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
switch (reg) {
|
||||
/* The first 32 registers are the zregs */
|
||||
case 0 ... 31:
|
||||
{
|
||||
int vq, len = 0;
|
||||
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
|
||||
len += gdb_get_reg128(buf,
|
||||
env->vfp.zregs[reg].d[vq * 2 + 1],
|
||||
env->vfp.zregs[reg].d[vq * 2]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
case 32:
|
||||
return gdb_get_reg32(buf, vfp_get_fpsr(env));
|
||||
case 33:
|
||||
return gdb_get_reg32(buf, vfp_get_fpcr(env));
|
||||
/* then 16 predicates and the ffr */
|
||||
case 34 ... 50:
|
||||
{
|
||||
int preg = reg - 34;
|
||||
int vq, len = 0;
|
||||
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
|
||||
len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
case 51:
|
||||
{
|
||||
/*
|
||||
* We report in Vector Granules (VG) which is 64bit in a Z reg
|
||||
* while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
|
||||
*/
|
||||
int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
|
||||
return gdb_get_reg32(buf, vq * 2);
|
||||
}
|
||||
default:
|
||||
/* gdbstub asked for something out our range */
|
||||
qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
/* The first 32 registers are the zregs */
|
||||
switch (reg) {
|
||||
/* The first 32 registers are the zregs */
|
||||
case 0 ... 31:
|
||||
{
|
||||
int vq, len = 0;
|
||||
uint64_t *p = (uint64_t *) buf;
|
||||
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
|
||||
env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
|
||||
env->vfp.zregs[reg].d[vq * 2] = *p++;
|
||||
len += 16;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
case 32:
|
||||
vfp_set_fpsr(env, *(uint32_t *)buf);
|
||||
return 4;
|
||||
case 33:
|
||||
vfp_set_fpcr(env, *(uint32_t *)buf);
|
||||
return 4;
|
||||
case 34 ... 50:
|
||||
{
|
||||
int preg = reg - 34;
|
||||
int vq, len = 0;
|
||||
uint64_t *p = (uint64_t *) buf;
|
||||
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
|
||||
env->vfp.pregs[preg].p[vq / 4] = *p++;
|
||||
len += 8;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
case 51:
|
||||
/* cannot set vg via gdbstub */
|
||||
return 0;
|
||||
default:
|
||||
/* gdbstub asked for something out our range */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TARGET_AARCH64 */
|
||||
|
||||
static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
|
||||
{
|
||||
/* Return true if the regdef would cause an assertion if you called
|
||||
@@ -6599,6 +6697,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
return pfr1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
@@ -6609,6 +6708,7 @@ static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
}
|
||||
return pfr0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shared logic between LORID and the rest of the LOR* registers.
|
||||
* Secure state has already been delt with.
|
||||
@@ -7182,16 +7282,24 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
* define new registers here.
|
||||
*/
|
||||
ARMCPRegInfo v8_idregs[] = {
|
||||
/* ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST because we don't
|
||||
* know the right value for the GIC field until after we
|
||||
* define these regs.
|
||||
/*
|
||||
* ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST in system
|
||||
* emulation because we don't know the right value for the
|
||||
* GIC field until after we define these regs.
|
||||
*/
|
||||
{ .name = "ID_AA64PFR0_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 0,
|
||||
.access = PL1_R, .type = ARM_CP_NO_RAW,
|
||||
.access = PL1_R,
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
.type = ARM_CP_CONST,
|
||||
.resetvalue = cpu->isar.id_aa64pfr0
|
||||
#else
|
||||
.type = ARM_CP_NO_RAW,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.readfn = id_aa64pfr0_read,
|
||||
.writefn = arm_cp_write_ignore },
|
||||
.writefn = arm_cp_write_ignore
|
||||
#endif
|
||||
},
|
||||
{ .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -7966,9 +8074,22 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
|
||||
CPUARMState *env = &cpu->env;
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
|
||||
gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
|
||||
aarch64_fpu_gdb_set_reg,
|
||||
34, "aarch64-fpu.xml", 0);
|
||||
/*
|
||||
* The lower part of each SVE register aliases to the FPU
|
||||
* registers so we don't need to include both.
|
||||
*/
|
||||
#ifdef TARGET_AARCH64
|
||||
if (isar_feature_aa64_sve(&cpu->isar)) {
|
||||
gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
|
||||
arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
|
||||
"sve-registers.xml", 0);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
|
||||
aarch64_fpu_gdb_set_reg,
|
||||
34, "aarch64-fpu.xml", 0);
|
||||
}
|
||||
} else if (arm_feature(env, ARM_FEATURE_NEON)) {
|
||||
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
|
||||
51, "arm-neon.xml", 0);
|
||||
@@ -7980,8 +8101,9 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
|
||||
19, "arm-vfp.xml", 0);
|
||||
}
|
||||
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
|
||||
arm_gen_dynamic_xml(cs),
|
||||
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
|
||||
"system-registers.xml", 0);
|
||||
|
||||
}
|
||||
|
||||
/* Sort alphabetically by type name, except for "any". */
|
||||
|
||||
+2
-2
@@ -195,8 +195,8 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags);
|
||||
|
||||
hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
|
||||
int crisv10_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int cris_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int crisv10_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int cris_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
int crisv10_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
CRISCPU *cpu = CRIS_CPU(cs);
|
||||
CPUCRISState *env = &cpu->env;
|
||||
@@ -53,7 +53,7 @@ int crisv10_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cris_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
CRISCPU *cpu = CRIS_CPU(cs);
|
||||
CPUCRISState *env = &cpu->env;
|
||||
|
||||
+1
-1
@@ -321,7 +321,7 @@ void cpu_hppa_change_prot_id(CPUHPPAState *env);
|
||||
|
||||
int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
|
||||
int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int hppa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
void hppa_cpu_do_interrupt(CPUState *cpu);
|
||||
bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
int hppa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
HPPACPU *cpu = HPPA_CPU(cs);
|
||||
CPUHPPAState *env = &cpu->env;
|
||||
|
||||
+1
-1
@@ -1766,7 +1766,7 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags);
|
||||
hwaddr x86_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
|
||||
MemTxAttrs *attrs);
|
||||
|
||||
int x86_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int x86_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
void x86_cpu_exec_enter(CPUState *cpu);
|
||||
|
||||
+12
-17
@@ -79,7 +79,7 @@ static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
#endif
|
||||
|
||||
|
||||
int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
@@ -98,26 +98,22 @@ int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
return gdb_get_reg64(mem_buf,
|
||||
env->regs[gpr_map[n]] & 0xffffffffUL);
|
||||
} else {
|
||||
memset(mem_buf, 0, sizeof(target_ulong));
|
||||
return sizeof(target_ulong);
|
||||
return gdb_get_regl(mem_buf, 0);
|
||||
}
|
||||
} else {
|
||||
return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]);
|
||||
}
|
||||
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
|
||||
#ifdef USE_X86LDOUBLE
|
||||
/* FIXME: byteswap float values - after fixing fpregs layout. */
|
||||
memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10);
|
||||
#else
|
||||
memset(mem_buf, 0, 10);
|
||||
#endif
|
||||
return 10;
|
||||
floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS];
|
||||
int len = gdb_get_reg64(mem_buf, cpu_to_le64(fp->low));
|
||||
len += gdb_get_reg16(mem_buf + len, cpu_to_le16(fp->high));
|
||||
return len;
|
||||
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
|
||||
n -= IDX_XMM_REGS;
|
||||
if (n < CPU_NB_REGS32 || TARGET_LONG_BITS == 64) {
|
||||
stq_p(mem_buf, env->xmm_regs[n].ZMM_Q(0));
|
||||
stq_p(mem_buf + 8, env->xmm_regs[n].ZMM_Q(1));
|
||||
return 16;
|
||||
return gdb_get_reg128(mem_buf,
|
||||
env->xmm_regs[n].ZMM_Q(0),
|
||||
env->xmm_regs[n].ZMM_Q(1));
|
||||
}
|
||||
} else {
|
||||
switch (n) {
|
||||
@@ -290,10 +286,9 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
return 4;
|
||||
}
|
||||
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
|
||||
#ifdef USE_X86LDOUBLE
|
||||
/* FIXME: byteswap float values - after fixing fpregs layout. */
|
||||
memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);
|
||||
#endif
|
||||
floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS];
|
||||
fp->low = le64_to_cpu(* (uint64_t *) mem_buf);
|
||||
fp->high = le16_to_cpu(* (uint16_t *) (mem_buf + 8));
|
||||
return 10;
|
||||
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
|
||||
n -= IDX_XMM_REGS;
|
||||
|
||||
+1
-1
@@ -202,7 +202,7 @@ void lm32_cpu_do_interrupt(CPUState *cpu);
|
||||
bool lm32_cpu_exec_interrupt(CPUState *cs, int int_req);
|
||||
void lm32_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||
hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
int lm32_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int lm32_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int lm32_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
typedef enum {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user