aboutsummaryrefslogtreecommitdiff
path: root/hwacha
diff options
context:
space:
mode:
authorYunsup Lee <yunsup@cs.berkeley.edu>2013-10-18 17:34:54 -0700
committerYunsup Lee <yunsup@cs.berkeley.edu>2013-10-18 17:34:54 -0700
commitcb6cfc5f3ad18280c6dce1f03ee4ff87e4677dad (patch)
tree2f2416b151713f95aaa0d24d7a5163330c3d0d90 /hwacha
parent9543d241b320cb1c4982949aa6d012940c8f5377 (diff)
downloadspike-cb6cfc5f3ad18280c6dce1f03ee4ff87e4677dad.zip
spike-cb6cfc5f3ad18280c6dce1f03ee4ff87e4677dad.tar.gz
spike-cb6cfc5f3ad18280c6dce1f03ee4ff87e4677dad.tar.bz2
refactor disassembler, and add hwacha disassembler
Diffstat (limited to 'hwacha')
-rw-r--r--hwacha/hwacha.cc1
-rw-r--r--hwacha/hwacha.h8
-rw-r--r--hwacha/hwacha.mk.in2
-rw-r--r--hwacha/hwacha_disasm.cc200
-rw-r--r--hwacha/insns/vf.h17
5 files changed, 223 insertions, 5 deletions
diff --git a/hwacha/hwacha.cc b/hwacha/hwacha.cc
index 0d6b906..192d308 100644
--- a/hwacha/hwacha.cc
+++ b/hwacha/hwacha.cc
@@ -1,5 +1,6 @@
#include "hwacha.h"
#include "hwacha_xcpt.h"
+#include "mmu.h"
#include "trap.h"
void ct_state_t::reset()
diff --git a/hwacha/hwacha.h b/hwacha/hwacha.h
index e48bf52..7504e57 100644
--- a/hwacha/hwacha.h
+++ b/hwacha/hwacha.h
@@ -30,9 +30,12 @@ struct ut_state_t
class hwacha_t : public extension_t
{
public:
+ hwacha_t() : debug(false) {}
std::vector<insn_desc_t> get_instructions();
+ std::vector<disasm_insn_t*> get_disasms();
const char* name() { return "hwacha"; }
void reset();
+ void set_debug(bool value) { debug = value; }
ct_state_t* get_ct_state() { return &ct_state; }
ut_state_t* get_ut_state(int idx) { return &ut_state[idx]; }
@@ -40,10 +43,15 @@ public:
void take_exception(reg_t, reg_t);
void clear_exception() { clear_interrupt(); }
+ bool get_debug() { return debug; }
+ disassembler_t* get_ut_disassembler() { return &ut_disassembler; }
+
private:
static const int max_uts = 2048;
ct_state_t ct_state;
ut_state_t ut_state[max_uts];
+ disassembler_t ut_disassembler;
+ bool debug;
};
REGISTER_EXTENSION(hwacha, []() { return new hwacha_t; })
diff --git a/hwacha/hwacha.mk.in b/hwacha/hwacha.mk.in
index cf698d3..bf16b6f 100644
--- a/hwacha/hwacha.mk.in
+++ b/hwacha/hwacha.mk.in
@@ -9,6 +9,7 @@ hwacha_install_prog_srcs = \
hwacha_hdrs = \
hwacha.h \
+ hwacha_xcpt.h \
decode_hwacha.h \
decode_hwacha_ut.h \
opcodes_hwacha.h \
@@ -16,6 +17,7 @@ hwacha_hdrs = \
hwacha_srcs = \
hwacha.cc \
+ hwacha_disasm.cc \
$(hwacha_gen_srcs) \
$(hwacha_ut_gen_srcs) \
diff --git a/hwacha/hwacha_disasm.cc b/hwacha/hwacha_disasm.cc
new file mode 100644
index 0000000..46ec080
--- /dev/null
+++ b/hwacha/hwacha_disasm.cc
@@ -0,0 +1,200 @@
+#include "hwacha.h"
+
+static const char* xpr[] = {
+ "zero", "ra", "s0", "s1", "s2", "s3", "s4", "s5",
+ "s6", "s7", "s8", "s9", "s10", "s11", "sp", "tp",
+ "v0", "v1", "a0", "a1", "a2", "a3", "a4", "a5",
+ "a6", "a7", "t0", "t1", "t2", "t3", "t4", "gp"
+};
+
+static const char* fpr[] = {
+ "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
+ "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15",
+ "fv0", "fv1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
+ "fa6", "fa7", "ft0", "ft1", "ft2", "ft3", "ft4", "ft5"
+};
+
+static const char* vxpr[] = {
+ "vx0", "vx1", "vx2", "vx3", "vx4", "vx5", "vx6", "vx7",
+ "vx8", "vx9", "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
+ "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
+ "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
+};
+
+static const char* vfpr[] = {
+ "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7",
+ "vf8", "vf9", "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
+ "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
+ "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
+};
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return xpr[insn.rs1()];
+ }
+} xrs1;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return xpr[insn.rs2()];
+ }
+} xrs2;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return xpr[insn.rd()];
+ }
+} xrd;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return fpr[insn.rd()];
+ }
+} frd;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return fpr[insn.rs1()];
+ }
+} frs1;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return fpr[insn.rs2()];
+ }
+} frs2;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return fpr[insn.rs3()];
+ }
+} frs3;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return vxpr[insn.rd()];
+ }
+} vxrd;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return vxpr[insn.rs1()];
+ }
+} vxrs1;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return vfpr[insn.rd()];
+ }
+} vfrd;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return vfpr[insn.rs1()];
+ }
+} vfrs1;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return std::to_string(insn.i_imm() & 0x3f);
+ }
+} nxregs;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return std::to_string((insn.i_imm() >> 6) & 0x3f);
+ }
+} nfregs;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return std::to_string((int)insn.s_imm()) + '(' + xpr[insn.rs1()] + ')';
+ }
+} vf_addr;
+
+std::vector<disasm_insn_t*> hwacha_t::get_disasms()
+{
+ std::vector<disasm_insn_t*> insns;
+
+ #define DECLARE_INSN(code, match, mask) \
+ const uint32_t match_##code = match; \
+ const uint32_t mask_##code = mask;
+ #include "opcodes_hwacha.h"
+ #undef DECLARE_INSN
+
+ #define DISASM_INSN(name, code, extra, ...) \
+ insns.push_back(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__));
+
+ DISASM_INSN("vsetcfg", vsetcfg, 0, {&xrs1, &nxregs, &nfregs});
+ DISASM_INSN("vsetvl", vsetvl, 0, {&xrd, &xrs1});
+ DISASM_INSN("vgetcfg", vgetcfg, 0, {&xrd});
+ DISASM_INSN("vgetvl", vgetvl, 0, {&xrd});
+
+ DISASM_INSN("vmvv", vmvv, 0, {&vxrd, &vxrs1});
+ DISASM_INSN("vmsv", vmsv, 0, {&vxrd, &xrs1});
+ DISASM_INSN("vf", vf, 0, {&vf_addr});
+
+ DISASM_INSN("vxcptcause", vxcptcause, 0, {&xrd});
+ DISASM_INSN("vxcptaux", vxcptaux, 0, {&xrd});
+ DISASM_INSN("vxcptsave", vxcptsave, 0, {&xrs1});
+ DISASM_INSN("vxcptrestore", vxcptrestore, 0, {&xrs1});
+ DISASM_INSN("vxcptkill", vxcptkill, 0, {});
+
+ const uint32_t mask_vseglen = 0x7UL << 29;
+
+ #define DISASM_VMEM_INSN(name1, name2, code, ...) \
+ DISASM_INSN(name1, code, mask_vseglen, __VA_ARGS__) \
+ DISASM_INSN(name2, code, 0, __VA_ARGS__) \
+
+ DISASM_VMEM_INSN("vld", "vlsegd", vlsegd, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vlw", "vlsegw", vlsegw, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vlwu", "vlsegwu", vlsegwu, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vlh", "vlsegh", vlsegh, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vlhu", "vlseghu", vlseghu, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vlb", "vlsegb", vlsegb, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vlbu", "vlsegbu", vlsegbu, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vfld", "vflsegd", vflsegd, {&vfrd, &xrs1});
+ DISASM_VMEM_INSN("vflw", "vflsegw", vflsegw, {&vfrd, &xrs1});
+
+ DISASM_VMEM_INSN("vlstd", "vlsegstd", vlsegstd, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vlstw", "vlsegstw", vlsegstw, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vlstwu", "vlsegstwu", vlsegstwu, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vlsth", "vlsegsth", vlsegsth, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vlsthu", "vlsegsthu", vlsegsthu, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vlstb", "vlsegstb", vlsegstb, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vlstbu", "vlsegstbu", vlsegstbu, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vflstd", "vflsegstd", vflsegstd, {&vfrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vflstw", "vflsegstw", vflsegstw, {&vfrd, &xrs1, &xrs2});
+
+ DISASM_VMEM_INSN("vsd", "vssegd", vssegd, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vsw", "vssegw", vssegw, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vsh", "vssegh", vssegh, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vsb", "vssegb", vssegb, {&vxrd, &xrs1});
+ DISASM_VMEM_INSN("vfsd", "vfssegd", vfssegd, {&vfrd, &xrs1});
+ DISASM_VMEM_INSN("vfsw", "vfssegw", vfssegw, {&vfrd, &xrs1});
+
+ DISASM_VMEM_INSN("vsstd", "vssegstd", vssegstd, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vsstw", "vssegstw", vssegstw, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vssth", "vssegsth", vssegsth, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vsstb", "vssegstb", vssegstb, {&vxrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vfsstd", "vfssegstd", vfssegstd, {&vfrd, &xrs1, &xrs2});
+ DISASM_VMEM_INSN("vfsstw", "vfssegstw", vfssegstw, {&vfrd, &xrs1, &xrs2});
+
+ #define DECLARE_INSN(code, match, mask) \
+ const uint32_t match_##code = match; \
+ const uint32_t mask_##code = mask;
+ #include "opcodes_hwacha_ut.h"
+ #undef DECLARE_INSN
+
+ #define DISASM_UT_INSN(name, code, extra, ...) \
+ ut_disassembler.add_insn(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__));
+
+ DISASM_UT_INSN("stop", ut_stop, 0, {});
+ DISASM_UT_INSN("utidx", ut_utidx, 0, {&xrd});
+ DISASM_UT_INSN("movz", ut_movz, 0, {&xrd, &xrs1, &xrs2});
+ DISASM_UT_INSN("movn", ut_movn, 0, {&xrd, &xrs1, &xrs2});
+ DISASM_UT_INSN("fmovz", ut_fmovz, 0, {&frd, &xrs1, &frs2});
+ DISASM_UT_INSN("fmovn", ut_fmovn, 0, {&frd, &xrs1, &frs2});
+
+ return insns;
+}
diff --git a/hwacha/insns/vf.h b/hwacha/insns/vf.h
index 7bd1973..fafb8b9 100644
--- a/hwacha/insns/vf.h
+++ b/hwacha/insns/vf.h
@@ -5,11 +5,12 @@ if (VL) {
h->get_ut_state(i)->run = true;
}
+vf_loop:
+
if (VF_PC & 3)
h->take_exception(HWACHA_CAUSE_VF_MISALIGNED_FETCH, VF_PC);
- mmu_t::insn_fetch_t ut_fetch = p->get_mmu()->load_insn(VF_PC);
- insn_t ut_insn = ut_fetch.insn.insn;
+ insn_t ut_insn = p->get_mmu()->load_insn(VF_PC).insn.insn;
bool matched = false;
@@ -25,7 +26,13 @@ if (VL) {
if (!matched)
h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_INSTRUCTION, VF_PC);
- // if vf is still running, rewind pc so that it will execute again
- if (h->vf_active())
- npc = pc;
+ if (!h->get_debug()) {
+ if (h->vf_active())
+ goto vf_loop;
+ } else {
+ fprintf(stderr, "vf block: 0x%016" PRIx64 " (0x%08" PRIx32 ") %s\n",
+ VF_PC, ut_insn.bits(), h->get_ut_disassembler()->disassemble(ut_insn).c_str());
+ if (h->vf_active())
+ npc = pc;
+ }
}