target/avr: CPU class: Add GDB support

This includes GDB hooks for reading from wnd wrtiting to AVR
registers, and xml register definition file as well.

[AM: Split a larger AVR introduction patch into logical units]
Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
Co-developed-by: Michael Rolnik <mrolnik@gmail.com>
Co-developed-by: Sarah Harris <S.E.Harris@kent.ac.uk>
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Signed-off-by: Sarah Harris <S.E.Harris@kent.ac.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
[thuth: Fixed avr_cpu_gdb_read_register() parameter]
Signed-off-by: Thomas Huth <huth@tuxfamily.org>
Message-Id: <20200705140315.260514-7-huth@tuxfamily.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
Michael Rolnik 2020-01-26 18:52:23 +01:00 committed by Philippe Mathieu-Daudé
parent 3fa28dd6cf
commit 12b3540547
5 changed files with 140 additions and 0 deletions

View File

@ -171,6 +171,7 @@ AVR TCG CPUs
M: Michael Rolnik <mrolnik@gmail.com> M: Michael Rolnik <mrolnik@gmail.com>
R: Sarah Harris <S.E.Harris@kent.ac.uk> R: Sarah Harris <S.E.Harris@kent.ac.uk>
S: Maintained S: Maintained
F: gdb-xml/avr-cpu.xml
F: target/avr/ F: target/avr/
CRIS TCG CPUs CRIS TCG CPUs

49
gdb-xml/avr-cpu.xml Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 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. -->
<!-- Register numbers are hard-coded in order to maintain backward
compatibility with older versions of tools that didn't use xml
register descriptions. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.cpu">
<reg name="r0" bitsize="8" type="int" regnum="0"/>
<reg name="r1" bitsize="8" type="int"/>
<reg name="r2" bitsize="8" type="int"/>
<reg name="r3" bitsize="8" type="int"/>
<reg name="r4" bitsize="8" type="int"/>
<reg name="r5" bitsize="8" type="int"/>
<reg name="r6" bitsize="8" type="int"/>
<reg name="r7" bitsize="8" type="int"/>
<reg name="r8" bitsize="8" type="int"/>
<reg name="r9" bitsize="8" type="int"/>
<reg name="r10" bitsize="8" type="int"/>
<reg name="r11" bitsize="8" type="int"/>
<reg name="r12" bitsize="8" type="int"/>
<reg name="r13" bitsize="8" type="int"/>
<reg name="r14" bitsize="8" type="int"/>
<reg name="r15" bitsize="8" type="int"/>
<reg name="r16" bitsize="8" type="int"/>
<reg name="r17" bitsize="8" type="int"/>
<reg name="r18" bitsize="8" type="int"/>
<reg name="r19" bitsize="8" type="int"/>
<reg name="r20" bitsize="8" type="int"/>
<reg name="r21" bitsize="8" type="int"/>
<reg name="r22" bitsize="8" type="int"/>
<reg name="r23" bitsize="8" type="int"/>
<reg name="r24" bitsize="8" type="int"/>
<reg name="r25" bitsize="8" type="int"/>
<reg name="r26" bitsize="8" type="int"/>
<reg name="r27" bitsize="8" type="int"/>
<reg name="r28" bitsize="8" type="int"/>
<reg name="r29" bitsize="8" type="int"/>
<reg name="r30" bitsize="8" type="int"/>
<reg name="r31" bitsize="8" type="int"/>
<reg name="sreg" bitsize="8" type="int"/>
<reg name="sp" bitsize="8" type="int"/>
<reg name="pc" bitsize="8" type="int"/>
</feature>

View File

@ -210,4 +210,8 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
cc->disas_set_info = avr_cpu_disas_set_info; cc->disas_set_info = avr_cpu_disas_set_info;
cc->tcg_initialize = avr_cpu_tcg_init; cc->tcg_initialize = avr_cpu_tcg_init;
cc->synchronize_from_tb = avr_cpu_synchronize_from_tb; cc->synchronize_from_tb = avr_cpu_synchronize_from_tb;
cc->gdb_read_register = avr_cpu_gdb_read_register;
cc->gdb_write_register = avr_cpu_gdb_write_register;
cc->gdb_num_core_regs = 35;
cc->gdb_core_xml_file = "avr-cpu.xml";
} }

View File

@ -123,6 +123,8 @@ extern const struct VMStateDescription vms_avr_cpu;
void avr_cpu_do_interrupt(CPUState *cpu); void avr_cpu_do_interrupt(CPUState *cpu);
bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req); bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int avr_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#define cpu_list avr_cpu_list #define cpu_list avr_cpu_list
#define cpu_signal_handler cpu_avr_signal_handler #define cpu_signal_handler cpu_avr_signal_handler

84
target/avr/gdbstub.c Normal file
View File

@ -0,0 +1,84 @@
/*
* QEMU AVR gdbstub
*
* Copyright (c) 2016-2020 Michael Rolnik
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>
*/
#include "qemu/osdep.h"
#include "exec/gdbstub.h"
int avr_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
AVRCPU *cpu = AVR_CPU(cs);
CPUAVRState *env = &cpu->env;
/* R */
if (n < 32) {
return gdb_get_reg8(mem_buf, env->r[n]);
}
/* SREG */
if (n == 32) {
uint8_t sreg = cpu_get_sreg(env);
return gdb_get_reg8(mem_buf, sreg);
}
/* SP */
if (n == 33) {
return gdb_get_reg16(mem_buf, env->sp & 0x0000ffff);
}
/* PC */
if (n == 34) {
return gdb_get_reg32(mem_buf, env->pc_w * 2);
}
return 0;
}
int avr_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
AVRCPU *cpu = AVR_CPU(cs);
CPUAVRState *env = &cpu->env;
/* R */
if (n < 32) {
env->r[n] = *mem_buf;
return 1;
}
/* SREG */
if (n == 32) {
cpu_set_sreg(env, *mem_buf);
return 1;
}
/* SP */
if (n == 33) {
env->sp = lduw_p(mem_buf);
return 2;
}
/* PC */
if (n == 34) {
env->pc_w = ldl_p(mem_buf) / 2;
return 4;
}
return 0;
}