diff options
author | Claudio Fontana <claudio.fontana@linaro.org> | 2014-02-05 17:27:28 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-02-08 14:50:48 +0000 |
commit | 999b53ec8794f203964db3ecf939a3da5c4bc843 (patch) | |
tree | b9b9a8cffdc54b2d6a6f4386396e557642b21170 /disas | |
parent | 37fd5b53ba688e2a32d3966870361e667381ca95 (diff) |
disas: Implement disassembly output for A64
Use libvixl to implement disassembly output in debug
logs for A64, for use with both AArch64 hosts and targets.
Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
[PMM:
* added support for target disassembly
* switched to custom QEMUDisassembler so the output format
matches what QEMU expects
* make sure we correctly fall back to "just print hex"
if we didn't build the AArch64 disassembler because of
lack of a C++ compiler
* rename from 'aarch64' to 'arm-a64' because this is a
disassembler for the A64 instruction set
* merge aarch64.c and aarch64-cxx.cc into one C++ file
* simplify the aarch64.c<->aarch64-cxx.cc interface]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'disas')
-rw-r--r-- | disas/Makefile.objs | 5 | ||||
-rw-r--r-- | disas/arm-a64.cc | 87 | ||||
-rw-r--r-- | disas/libvixl/Makefile.objs | 8 |
3 files changed, 100 insertions, 0 deletions
diff --git a/disas/Makefile.objs b/disas/Makefile.objs index 3b1e77ace5..41c237424a 100644 --- a/disas/Makefile.objs +++ b/disas/Makefile.objs @@ -1,5 +1,10 @@ + common-obj-$(CONFIG_ALPHA_DIS) += alpha.o common-obj-$(CONFIG_ARM_DIS) += arm.o +common-obj-$(CONFIG_ARM_A64_DIS) += arm-a64.o +common-obj-$(CONFIG_ARM_A64_DIS) += libvixl/ +libvixldir = $(SRC_PATH)/disas/libvixl +$(obj)/arm-a64.o: QEMU_CFLAGS += -I$(libvixldir) common-obj-$(CONFIG_CRIS_DIS) += cris.o common-obj-$(CONFIG_HPPA_DIS) += hppa.o common-obj-$(CONFIG_I386_DIS) += i386.o diff --git a/disas/arm-a64.cc b/disas/arm-a64.cc new file mode 100644 index 0000000000..162be0c420 --- /dev/null +++ b/disas/arm-a64.cc @@ -0,0 +1,87 @@ +/* + * ARM A64 disassembly output wrapper to libvixl + * Copyright (c) 2013 Linaro Limited + * Written by Claudio Fontana + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "a64/disasm-a64.h" + +extern "C" { +#include "disas/bfd.h" +} + +using namespace vixl; + +static Decoder *vixl_decoder = NULL; +static Disassembler *vixl_disasm = NULL; + +/* We don't use libvixl's PrintDisassembler because its output + * is a little unhelpful (trailing newlines, for example). + * Instead we use our own very similar variant so we have + * control over the format. + */ +class QEMUDisassembler : public Disassembler { +public: + explicit QEMUDisassembler(FILE *stream) : stream_(stream) { } + ~QEMUDisassembler() { } + +protected: + void ProcessOutput(Instruction *instr) { + fprintf(stream_, "%08" PRIx32 " %s", + instr->InstructionBits(), GetOutput()); + } + +private: + FILE *stream_; +}; + +static int vixl_is_initialized(void) +{ + return vixl_decoder != NULL; +} + +static void vixl_init(FILE *f) { + vixl_decoder = new Decoder(); + vixl_disasm = new QEMUDisassembler(f); + vixl_decoder->AppendVisitor(vixl_disasm); +} + +#define INSN_SIZE 4 + +/* Disassemble ARM A64 instruction. This is our only entry + * point from QEMU's C code. + */ +int print_insn_arm_a64(uint64_t addr, disassemble_info *info) +{ + uint8_t bytes[INSN_SIZE]; + uint32_t instr; + int status; + + status = info->read_memory_func(addr, bytes, INSN_SIZE, info); + if (status != 0) { + info->memory_error_func(status, addr, info); + return -1; + } + + if (!vixl_is_initialized()) { + vixl_init(info->stream); + } + + instr = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24; + vixl_decoder->Decode(reinterpret_cast<Instruction*>(&instr)); + + return INSN_SIZE; +} diff --git a/disas/libvixl/Makefile.objs b/disas/libvixl/Makefile.objs new file mode 100644 index 0000000000..0adb3ced7b --- /dev/null +++ b/disas/libvixl/Makefile.objs @@ -0,0 +1,8 @@ +libvixl_OBJS = utils.o \ + a64/instructions-a64.o \ + a64/decoder-a64.o \ + a64/disasm-a64.o + +$(addprefix $(obj)/,$(libvixl_OBJS)): QEMU_CFLAGS += -I$(SRC_PATH)/disas/libvixl + +common-obj-$(CONFIG_ARM_A64_DIS) += $(libvixl_OBJS) |