Skip to content

Commit

Permalink
target/openrisc: Add print_insn_or1k
Browse files Browse the repository at this point in the history
Rather than emit disassembly while translating, reuse the
generated decoder to build a separate disassembler.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Stafford Horne <shorne@gmail.com>
  • Loading branch information
rth7680 authored and stffrdhrn committed Jul 2, 2018
1 parent c3513c8 commit d5cabcc
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 115 deletions.
3 changes: 2 additions & 1 deletion target/openrisc/Makefile.objs
@@ -1,5 +1,5 @@
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o disas.o
obj-y += exception_helper.o fpu_helper.o \
interrupt_helper.o mmu_helper.o sys_helper.o
obj-y += gdbstub.o
Expand All @@ -12,3 +12,4 @@ target/openrisc/decode.inc.c: \
$(PYTHON) $(DECODETREE) -o $@ $<, "GEN", $(TARGET_DIR)$@)

target/openrisc/translate.o: target/openrisc/decode.inc.c
target/openrisc/disas.o: target/openrisc/decode.inc.c
6 changes: 6 additions & 0 deletions target/openrisc/cpu.c
Expand Up @@ -35,6 +35,11 @@ static bool openrisc_cpu_has_work(CPUState *cs)
CPU_INTERRUPT_TIMER);
}

static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info)
{
info->print_insn = print_insn_or1k;
}

/* CPUClass::reset() */
static void openrisc_cpu_reset(CPUState *s)
{
Expand Down Expand Up @@ -152,6 +157,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
#endif
cc->gdb_num_core_regs = 32 + 3;
cc->tcg_initialize = openrisc_translate_init;
cc->disas_set_info = openrisc_disas_set_info;
}

/* Sort alphabetically by type name, except for "any". */
Expand Down
1 change: 1 addition & 0 deletions target/openrisc/cpu.h
Expand Up @@ -358,6 +358,7 @@ void openrisc_translate_init(void);
int openrisc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
int rw, int mmu_idx);
int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
int print_insn_or1k(bfd_vma addr, disassemble_info *info);

#define cpu_list cpu_openrisc_list
#define cpu_signal_handler cpu_openrisc_signal_handler
Expand Down
170 changes: 170 additions & 0 deletions target/openrisc/disas.c
@@ -0,0 +1,170 @@
/*
* OpenRISC disassembler
*
* Copyright (c) 2018 Richard Henderson <rth@twiddle.net>
*
* 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 "qemu-common.h"
#include "disas/bfd.h"
#include "qemu/bitops.h"
#include "cpu.h"

typedef disassemble_info DisasContext;

/* Include the auto-generated decoder. */
#include "decode.inc.c"

#define output(mnemonic, format, ...) \
(info->fprintf_func(info->stream, "%-9s " format, \
mnemonic, ##__VA_ARGS__))

int print_insn_or1k(bfd_vma addr, disassemble_info *info)
{
bfd_byte buffer[4];
uint32_t insn;
int status;

status = info->read_memory_func(addr, buffer, 4, info);
if (status != 0) {
info->memory_error_func(status, addr, info);
return -1;
}
insn = bfd_getb32(buffer);

if (!decode(info, insn)) {
output(".long", "%#08x", insn);
}
return 4;
}

#define INSN(opcode, format, ...) \
static bool trans_l_##opcode(disassemble_info *info, \
arg_l_##opcode *a, uint32_t insn) \
{ \
output("l." #opcode, format, ##__VA_ARGS__); \
return true; \
}

INSN(add, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(addc, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(sub, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(and, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(or, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(xor, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(sll, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(srl, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(sra, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(ror, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(exths, "r%d, r%d", a->d, a->a)
INSN(extbs, "r%d, r%d", a->d, a->a)
INSN(exthz, "r%d, r%d", a->d, a->a)
INSN(extbz, "r%d, r%d", a->d, a->a)
INSN(cmov, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(ff1, "r%d, r%d", a->d, a->a)
INSN(fl1, "r%d, r%d", a->d, a->a)
INSN(mul, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(mulu, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(div, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(divu, "r%d, r%d, r%d", a->d, a->a, a->b)
INSN(muld, "r%d, r%d", a->a, a->b)
INSN(muldu, "r%d, r%d", a->a, a->b)
INSN(j, "%d", a->n)
INSN(jal, "%d", a->n)
INSN(bf, "%d", a->n)
INSN(bnf, "%d", a->n)
INSN(jr, "r%d", a->b)
INSN(jalr, "r%d", a->b)
INSN(lwa, "r%d, %d(r%d)", a->d, a->i, a->a)
INSN(lwz, "r%d, %d(r%d)", a->d, a->i, a->a)
INSN(lws, "r%d, %d(r%d)", a->d, a->i, a->a)
INSN(lbz, "r%d, %d(r%d)", a->d, a->i, a->a)
INSN(lbs, "r%d, %d(r%d)", a->d, a->i, a->a)
INSN(lhz, "r%d, %d(r%d)", a->d, a->i, a->a)
INSN(lhs, "r%d, %d(r%d)", a->d, a->i, a->a)
INSN(swa, "%d(r%d), r%d", a->i, a->a, a->b)
INSN(sw, "%d(r%d), r%d", a->i, a->a, a->b)
INSN(sb, "%d(r%d), r%d", a->i, a->a, a->b)
INSN(sh, "%d(r%d), r%d", a->i, a->a, a->b)
INSN(nop, "")
INSN(addi, "r%d, r%d, %d", a->d, a->a, a->i)
INSN(addic, "r%d, r%d, %d", a->d, a->a, a->i)
INSN(muli, "r%d, r%d, %d", a->d, a->a, a->i)
INSN(maci, "r%d, %d", a->a, a->i)
INSN(andi, "r%d, r%d, %d", a->d, a->a, a->k)
INSN(ori, "r%d, r%d, %d", a->d, a->a, a->k)
INSN(xori, "r%d, r%d, %d", a->d, a->a, a->i)
INSN(mfspr, "r%d, r%d, %d", a->d, a->a, a->k)
INSN(mtspr, "r%d, r%d, %d", a->a, a->b, a->k)
INSN(mac, "r%d, r%d", a->a, a->b)
INSN(msb, "r%d, r%d", a->a, a->b)
INSN(macu, "r%d, r%d", a->a, a->b)
INSN(msbu, "r%d, r%d", a->a, a->b)
INSN(slli, "r%d, r%d, %d", a->d, a->a, a->l)
INSN(srli, "r%d, r%d, %d", a->d, a->a, a->l)
INSN(srai, "r%d, r%d, %d", a->d, a->a, a->l)
INSN(rori, "r%d, r%d, %d", a->d, a->a, a->l)
INSN(movhi, "r%d, %d", a->d, a->k)
INSN(macrc, "r%d", a->d)
INSN(sfeq, "r%d, r%d", a->a, a->b)
INSN(sfne, "r%d, r%d", a->a, a->b)
INSN(sfgtu, "r%d, r%d", a->a, a->b)
INSN(sfgeu, "r%d, r%d", a->a, a->b)
INSN(sfltu, "r%d, r%d", a->a, a->b)
INSN(sfleu, "r%d, r%d", a->a, a->b)
INSN(sfgts, "r%d, r%d", a->a, a->b)
INSN(sfges, "r%d, r%d", a->a, a->b)
INSN(sflts, "r%d, r%d", a->a, a->b)
INSN(sfles, "r%d, r%d", a->a, a->b)
INSN(sfeqi, "r%d, %d", a->a, a->i)
INSN(sfnei, "r%d, %d", a->a, a->i)
INSN(sfgtui, "r%d, %d", a->a, a->i)
INSN(sfgeui, "r%d, %d", a->a, a->i)
INSN(sfltui, "r%d, %d", a->a, a->i)
INSN(sfleui, "r%d, %d", a->a, a->i)
INSN(sfgtsi, "r%d, %d", a->a, a->i)
INSN(sfgesi, "r%d, %d", a->a, a->i)
INSN(sfltsi, "r%d, %d", a->a, a->i)
INSN(sflesi, "r%d, %d", a->a, a->i)
INSN(sys, "%d", a->k)
INSN(trap, "%d", a->k)
INSN(msync, "")
INSN(psync, "")
INSN(csync, "")
INSN(rfe, "")

#define FP_INSN(opcode, suffix, format, ...) \
static bool trans_lf_##opcode##_##suffix(disassemble_info *info, \
arg_lf_##opcode##_##suffix *a, uint32_t insn) \
{ \
output("lf." #opcode "." #suffix, format, ##__VA_ARGS__); \
return true; \
}

FP_INSN(add, s, "r%d, r%d, r%d", a->d, a->a, a->b)
FP_INSN(sub, s, "r%d, r%d, r%d", a->d, a->a, a->b)
FP_INSN(mul, s, "r%d, r%d, r%d", a->d, a->a, a->b)
FP_INSN(div, s, "r%d, r%d, r%d", a->d, a->a, a->b)
FP_INSN(rem, s, "r%d, r%d, r%d", a->d, a->a, a->b)
FP_INSN(itof, s, "r%d, r%d", a->d, a->a)
FP_INSN(ftoi, s, "r%d, r%d", a->d, a->a)
FP_INSN(madd, s, "r%d, r%d, r%d", a->d, a->a, a->b)
FP_INSN(sfeq, s, "r%d, r%d", a->a, a->b)
FP_INSN(sfne, s, "r%d, r%d", a->a, a->b)
FP_INSN(sfgt, s, "r%d, r%d", a->a, a->b)
FP_INSN(sfge, s, "r%d, r%d", a->a, a->b)
FP_INSN(sflt, s, "r%d, r%d", a->a, a->b)
FP_INSN(sfle, s, "r%d, r%d", a->a, a->b)

0 comments on commit d5cabcc

Please sign in to comment.