Browse Source
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>pull/6/merge
committed by
Peter Maydell
7 changed files with 118 additions and 3 deletions
@ -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; |
|||
} |
|||
@ -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) |
|||
Loading…
Reference in new issue