From: Michael Rolnik <mrolnik@gmail.com>
To: qemu-devel@nongnu.org
Cc: thuth@redhat.com, Michael Rolnik <mrolnik@gmail.com>,
me@xcancerberox.com.ar, richard.henderson@linaro.org,
dovgaluk@ispras.ru, imammedo@redhat.com, philmd@redhat.com,
aleksandar.m.mail@gmail.com
Subject: [PATCH v39 11/22] target/avr: Add instruction disassembly function
Date: Wed, 18 Dec 2019 23:03:18 +0200 [thread overview]
Message-ID: <20191218210329.1960-12-mrolnik@gmail.com> (raw)
In-Reply-To: <20191218210329.1960-1-mrolnik@gmail.com>
Provide function disassembles executed instruction when `-d in_asm` is
provided
Example:
`./avr-softmmu/qemu-system-avr -bios free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf -d in_asm` will produce something like the following
```
...
IN:
0x0000014a: CALL 0x3808
IN: main
0x00003808: CALL 0x4b4
IN: vParTestInitialise
0x000004b4: LDI r24, 255
0x000004b6: STS r24, 0
0x000004b8: MULS r16, r20
0x000004ba: OUT $1, r24
0x000004bc: LDS r24, 0
0x000004be: MULS r16, r20
0x000004c0: OUT $2, r24
0x000004c2: RET
...
```
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
target/avr/cpu.h | 1 +
target/avr/cpu.c | 2 +-
target/avr/disas.c | 245 +++++++++++++++++++++++++++++++++++++++++
target/avr/translate.c | 11 ++
4 files changed, 258 insertions(+), 1 deletion(-)
create mode 100644 target/avr/disas.c
diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index b74bcf01ae..af89b6611e 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -160,6 +160,7 @@ bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int avr_print_insn(bfd_vma addr, disassemble_info *info);
static inline int avr_feature(CPUAVRState *env, AVRFeature feature)
{
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 49aa304d4e..08ad21e38e 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -84,7 +84,7 @@ static void avr_cpu_reset(CPUState *cs)
static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
{
info->mach = bfd_arch_avr;
- info->print_insn = NULL;
+ info->print_insn = avr_print_insn;
}
static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
diff --git a/target/avr/disas.c b/target/avr/disas.c
new file mode 100644
index 0000000000..f3fa3d6bef
--- /dev/null
+++ b/target/avr/disas.c
@@ -0,0 +1,245 @@
+/*
+ * AVR disassembler
+ *
+ * Copyright (c) 2019 Richard Henderson <rth@twiddle.net>
+ * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com>
+ *
+ * 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 "qemu/osdep.h"
+#include "cpu.h"
+
+typedef struct {
+ disassemble_info *info;
+ uint16_t next_word;
+ bool next_word_used;
+} DisasContext;
+
+static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
+{
+ return 16 + (indx % 16);
+}
+
+static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
+{
+ return 16 + (indx % 8);
+}
+static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
+{
+ return 24 + (indx % 4) * 2;
+}
+static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
+{
+ return (indx % 16) * 2;
+}
+
+static uint16_t next_word(DisasContext *ctx)
+{
+ ctx->next_word_used = true;
+ return ctx->next_word;
+}
+
+static int append_16(DisasContext *ctx, int x)
+{
+ return x << 16 | next_word(ctx);
+}
+
+
+/* Include the auto-generated decoder. */
+static bool decode_insn(DisasContext *ctx, uint16_t insn);
+#include "decode_insn.inc.c"
+
+#define output(mnemonic, format, ...) \
+ (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
+ mnemonic, ##__VA_ARGS__))
+
+int avr_print_insn(bfd_vma addr, disassemble_info *info)
+{
+ DisasContext ctx;
+ DisasContext *pctx = &ctx;
+ bfd_byte buffer[4];
+ uint16_t insn;
+ int status;
+
+ ctx.info = info;
+
+ status = info->read_memory_func(addr, buffer, 4, info);
+ if (status != 0) {
+ info->memory_error_func(status, addr, info);
+ return -1;
+ }
+ insn = bfd_getl16(buffer);
+ ctx.next_word = bfd_getl16(buffer + 2);
+ ctx.next_word_used = false;
+
+ if (!decode_insn(&ctx, insn)) {
+ output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
+ }
+
+ return ctx.next_word_used ? 4 : 2;
+}
+
+
+#define INSN(opcode, format, ...) \
+static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \
+{ \
+ output(#opcode, format, ##__VA_ARGS__); \
+ return true; \
+}
+
+#define INSN_MNEMONIC(opcode, mnemonic, format, ...) \
+static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \
+{ \
+ output(mnemonic, format, ##__VA_ARGS__); \
+ return true; \
+}
+
+/*
+ * C Z N V S H T I
+ * 0 1 2 3 4 5 6 7
+ */
+static const char *brbc[] = {
+ "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
+};
+
+static const char *brbs[] = {
+ "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
+};
+
+static const char *bset[] = {
+ "SEC", "SEZ", "SEN", "SEZ", "SES", "SEH", "SET", "SEI"
+};
+
+static const char *bclr[] = {
+ "CLC", "CLZ", "CLN", "CLZ", "CLS", "CLH", "CLT", "CLI"
+};
+
+/*
+ * Arithmetic Instructions
+ */
+INSN(ADD, "r%d, r%d", a->rd, a->rr)
+INSN(ADC, "r%d, r%d", a->rd, a->rr)
+INSN(ADIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
+INSN(SUB, "r%d, r%d", a->rd, a->rr)
+INSN(SUBI, "r%d, %d", a->rd, a->imm)
+INSN(SBC, "r%d, r%d", a->rd, a->rr)
+INSN(SBCI, "r%d, %d", a->rd, a->imm)
+INSN(SBIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
+INSN(AND, "r%d, r%d", a->rd, a->rr)
+INSN(ANDI, "r%d, %d", a->rd, a->imm)
+INSN(OR, "r%d, r%d", a->rd, a->rr)
+INSN(ORI, "r%d, %d", a->rd, a->imm)
+INSN(EOR, "r%d, r%d", a->rd, a->rr)
+INSN(COM, "r%d", a->rd)
+INSN(NEG, "r%d", a->rd)
+INSN(INC, "r%d", a->rd)
+INSN(DEC, "r%d", a->rd)
+INSN(MUL, "r%d, r%d", a->rd, a->rr)
+INSN(MULS, "r%d, r%d", a->rd, a->rr)
+INSN(MULSU, "r%d, r%d", a->rd, a->rr)
+INSN(FMUL, "r%d, r%d", a->rd, a->rr)
+INSN(FMULS, "r%d, r%d", a->rd, a->rr)
+INSN(FMULSU, "r%d, r%d", a->rd, a->rr)
+INSN(DES, "%d", a->imm)
+
+/*
+ * Branch Instructions
+ */
+INSN(RJMP, ".%+d", a->imm * 2)
+INSN(IJMP, "")
+INSN(EIJMP, "")
+INSN(JMP, "0x%x", a->imm * 2)
+INSN(RCALL, ".%+d", a->imm * 2)
+INSN(ICALL, "")
+INSN(EICALL, "")
+INSN(CALL, "0x%x", a->imm * 2)
+INSN(RET, "")
+INSN(RETI, "")
+INSN(CPSE, "r%d, r%d", a->rd, a->rr)
+INSN(CP, "r%d, r%d", a->rd, a->rr)
+INSN(CPC, "r%d, r%d", a->rd, a->rr)
+INSN(CPI, "r%d, %d", a->rd, a->imm)
+INSN(SBRC, "r%d, %d", a->rr, a->bit)
+INSN(SBRS, "r%d, %d", a->rr, a->bit)
+INSN(SBIC, "$%d, %d", a->reg, a->bit)
+INSN(SBIS, "$%d, %d", a->reg, a->bit)
+INSN_MNEMONIC(BRBS, brbs[a->bit], ".%+d", a->imm * 2)
+INSN_MNEMONIC(BRBC, brbc[a->bit], ".%+d", a->imm * 2)
+
+/*
+ * Data Transfer Instructions
+ */
+INSN(MOV, "r%d, r%d", a->rd, a->rr)
+INSN(MOVW, "r%d:r%d, r%d:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr)
+INSN(LDI, "r%d, %d", a->rd, a->imm)
+INSN(LDS, "r%d, %d", a->rd, a->imm)
+INSN(LDX1, "r%d, X", a->rd)
+INSN(LDX2, "r%d, X+", a->rd)
+INSN(LDX3, "r%d, -X", a->rd)
+INSN(LDY2, "r%d, Y+", a->rd)
+INSN(LDY3, "r%d, -Y", a->rd)
+INSN(LDZ2, "r%d, Z+", a->rd)
+INSN(LDZ3, "r%d, -Z", a->rd)
+INSN(LDDY, "r%d, Y+%d", a->rd, a->imm)
+INSN(LDDZ, "r%d, Z+%d", a->rd, a->imm)
+INSN(STS, "r%d, %d", a->rd, a->imm)
+INSN(STX1, "r%d, X", a->rr)
+INSN(STX2, "r%d, X+", a->rr)
+INSN(STX3, "r%d, -X", a->rr)
+INSN(STY2, "r%d, Y+", a->rd)
+INSN(STY3, "r%d, -Y", a->rd)
+INSN(STZ2, "r%d, Z+", a->rd)
+INSN(STZ3, "r%d, -Z", a->rd)
+INSN(STDY, "r%d, Y+%d", a->rd, a->imm)
+INSN(STDZ, "r%d, Z+%d", a->rd, a->imm)
+INSN(LPM1, "")
+INSN(LPM2, "r%d, Z", a->rd)
+INSN(LPMX, "r%d, Z+", a->rd)
+INSN(ELPM1, "")
+INSN(ELPM2, "r%d, Z", a->rd)
+INSN(ELPMX, "r%d, Z+", a->rd)
+INSN(SPM, "")
+INSN(SPMX, "Z+")
+INSN(IN, "r%d, $%d", a->rd, a->imm)
+INSN(OUT, "$%d, r%d", a->imm, a->rd)
+INSN(PUSH, "r%d", a->rd)
+INSN(POP, "r%d", a->rd)
+INSN(XCH, "Z, r%d", a->rd)
+INSN(LAC, "Z, r%d", a->rd)
+INSN(LAS, "Z, r%d", a->rd)
+INSN(LAT, "Z, r%d", a->rd)
+
+/*
+ * Bit and Bit-test Instructions
+ */
+INSN(LSR, "r%d", a->rd)
+INSN(ROR, "r%d", a->rd)
+INSN(ASR, "r%d", a->rd)
+INSN(SWAP, "r%d", a->rd)
+INSN(SBI, "$%d, %d", a->reg, a->bit)
+INSN(CBI, "%d, %d", a->reg, a->bit)
+INSN(BST, "r%d, %d", a->rd, a->bit)
+INSN(BLD, "r%d, %d", a->rd, a->bit)
+INSN_MNEMONIC(BSET, bset[a->bit], "")
+INSN_MNEMONIC(BCLR, bclr[a->bit], "")
+
+/*
+ * MCU Control Instructions
+ */
+INSN(BREAK, "")
+INSN(NOP, "")
+INSN(SLEEP, "")
+INSN(WDR, "")
+
diff --git a/target/avr/translate.c b/target/avr/translate.c
index 302d643068..9474265ae9 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -2901,6 +2901,17 @@ done_generating:
tb->size = (ctx.npc - pc_start) * 2;
tb->icount = num_insns;
+
+#ifdef DEBUG_DISAS
+ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
+ && qemu_log_in_addr_range(tb->pc)) {
+ qemu_log_lock();
+ qemu_log("IN: %s\n", lookup_symbol(tb->pc));
+ log_target_disas(cs, tb->pc, tb->size);
+ qemu_log("\n");
+ qemu_log_unlock();
+ }
+#endif
}
void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
--
2.17.2 (Apple Git-113)
next prev parent reply other threads:[~2019-12-18 21:12 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-18 21:03 [PATCH v39 00/22] QEMU AVR 8 bit cores Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 01/22] target/avr: Add outward facing interfaces and core CPU logic Michael Rolnik
2019-12-21 10:53 ` Aleksandar Markovic
2019-12-21 11:22 ` Philippe Mathieu-Daudé
2019-12-21 12:32 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 02/22] target/avr: Add instruction helpers Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 03/22] target/avr: Add instruction decoding Michael Rolnik
2019-12-21 11:18 ` Aleksandar Markovic
2019-12-21 15:57 ` Michael Rolnik
2019-12-21 16:21 ` Aleksandar Markovic
2019-12-21 17:15 ` Aleksandar Markovic
2019-12-28 19:31 ` Michael Rolnik
2019-12-29 14:37 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 04/22] target/avr: Add instruction translation - Registers definition Michael Rolnik
2019-12-22 15:54 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 05/22] target/avr: Add instruction translation - Arithmetic and Logic Instructions Michael Rolnik
2019-12-22 15:41 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 06/22] target/avr: Add instruction translation - Branch Instructions Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 07/22] target/avr: Add instruction translation - Data Transfer Instructions Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 08/22] target/avr: Add instruction translation - Bit and Bit-test Instructions Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 09/22] target/avr: Add instruction translation - MCU Control Instructions Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 10/22] target/avr: Add instruction translation - CPU main translation function Michael Rolnik
2019-12-18 21:03 ` Michael Rolnik [this message]
2019-12-18 21:03 ` [PATCH v39 12/22] target/avr: Add limited support for USART peripheral Michael Rolnik
2019-12-20 15:56 ` Philippe Mathieu-Daudé
2019-12-18 21:03 ` [PATCH v39 13/22] target/avr: Add limited support for 16 bit timer peripheral Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 14/22] target/avr: Add dummy mask device Michael Rolnik
2019-12-23 8:46 ` Aleksandar Markovic
2019-12-28 18:52 ` Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 15/22] target/avr: Add example board configuration Michael Rolnik
2019-12-20 9:51 ` Igor Mammedov
2019-12-20 12:30 ` Michael Rolnik
2019-12-20 15:18 ` Igor Mammedov
2019-12-20 23:12 ` Philippe Mathieu-Daudé
2020-01-21 21:32 ` Philippe Mathieu-Daudé
2019-12-18 21:03 ` [PATCH v39 16/22] target/avr: Add section about AVR into QEMU documentation Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 17/22] target/avr: Register AVR support with the rest of QEMU Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 18/22] target/avr: Add machine none test Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 19/22] target/avr: Update build system Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 20/22] target/avr: Add boot serial test Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 21/22] target/avr: Add Avocado test Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 22/22] target/avr: Update MAINTAINERS file Michael Rolnik
2019-12-23 8:56 ` Aleksandar Markovic
2019-12-23 9:13 ` [PATCH v39 00/22] QEMU AVR 8 bit cores Aleksandar Markovic
2019-12-28 18:01 ` Michael Rolnik
2019-12-28 19:38 ` Aleksandar Markovic
2019-12-28 20:00 ` Michael Rolnik
2019-12-29 14:19 ` Aleksandar Markovic
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191218210329.1960-12-mrolnik@gmail.com \
--to=mrolnik@gmail.com \
--cc=aleksandar.m.mail@gmail.com \
--cc=dovgaluk@ispras.ru \
--cc=imammedo@redhat.com \
--cc=me@xcancerberox.com.ar \
--cc=philmd@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.