From: Andrew Waterman Date: Tue, 8 Sep 2015 22:09:23 +0000 (-0700) Subject: Improve instruction fetch X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=71d04ecd7ab631193a0943f8ddae222090d8e048;p=riscv-isa-sim.git Improve instruction fetch - Performance for variable-length instructions is much better - Refill is simpler and faster - Support for instructions with overlapping opcodes (e.g. C.ADD + C.JALR) --- diff --git a/riscv/decode.h b/riscv/decode.h index 16e57d7..8462da2 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -53,6 +53,8 @@ const int NFPR = 32; ((x) & 0x1f) < 0x1f ? 4 : \ ((x) & 0x3f) < 0x3f ? 6 : \ 8) +#define MAX_INSN_LENGTH 8 +#define PC_ALIGN 2 typedef uint64_t insn_bits_t; class insn_t diff --git a/riscv/encoding.h b/riscv/encoding.h index 039ffdf..16a7792 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -225,6 +225,8 @@ #define MASK_C_ADD 0xf003 #define MATCH_C_ADDI 0xc002 #define MASK_C_ADDI 0xe003 +#define MATCH_C_ADDI16SP 0xa002 +#define MASK_C_ADDI16SP 0xef83 #define MATCH_C_ADDI4SPN 0x8000 #define MASK_C_ADDI4SPN 0xe003 #define MATCH_C_ADDIW 0xe002 @@ -235,6 +237,8 @@ #define MASK_C_BEQZ 0xe003 #define MATCH_C_BNEZ 0x6002 #define MASK_C_BNEZ 0xe003 +#define MATCH_C_EBREAK 0x1000 +#define MASK_C_EBREAK 0xffff #define MATCH_C_FLD 0xa000 #define MASK_C_FLD 0xe003 #define MATCH_C_FLDSP 0xa001 @@ -255,6 +259,14 @@ #define MASK_C_J 0xe003 #define MATCH_C_JAL 0x2002 #define MASK_C_JAL 0xe003 +#define MATCH_C_JALR 0x1000 +#define MASK_C_JALR 0xf07f +#define MATCH_C_JR 0x0 +#define MASK_C_JR 0xf07f +#define MATCH_C_LD 0xe000 +#define MASK_C_LD 0xe003 +#define MATCH_C_LDSP 0xe001 +#define MASK_C_LDSP 0xe003 #define MATCH_C_LI 0x8002 #define MASK_C_LI 0xe003 #define MATCH_C_LUI 0xa002 @@ -265,6 +277,12 @@ #define MASK_C_LWSP 0xe003 #define MATCH_C_MV 0x0 #define MASK_C_MV 0xf003 +#define MATCH_C_NOP 0xc002 +#define MASK_C_NOP 0xffff +#define MATCH_C_SD 0x6000 +#define MASK_C_SD 0xe003 +#define MATCH_C_SDSP 0x6001 +#define MASK_C_SDSP 0xe003 #define MATCH_C_SLLI 0x1 #define MASK_C_SLLI 0xe003 #define MATCH_C_SW 0x4000 @@ -646,11 +664,13 @@ DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) +DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) +DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) @@ -661,11 +681,18 @@ DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) +DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) +DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) +DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) +DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) +DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) +DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) +DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) diff --git a/riscv/execute.cc b/riscv/execute.cc new file mode 100644 index 0000000..bb7ed34 --- /dev/null +++ b/riscv/execute.cc @@ -0,0 +1,117 @@ +// See LICENSE for license details. + +#include "processor.h" +#include "mmu.h" +#include + +static void commit_log(state_t* state, reg_t pc, insn_t insn) +{ +#ifdef RISCV_ENABLE_COMMITLOG + if (get_field(state->mstatus, MSTATUS_IE)) { + uint64_t mask = (insn.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn.length() * 8))) - 1; + if (state->log_reg_write.addr) { + fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIu64 " 0x%016" PRIx64 "\n", + pc, + insn.bits() & mask, + state->log_reg_write.addr & 1 ? 'f' : 'x', + state->log_reg_write.addr >> 1, + state->log_reg_write.data); + } else { + fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ")\n", pc, insn.bits() & mask); + } + } + state->log_reg_write.addr = 0; +#endif +} + +inline void processor_t::update_histogram(size_t pc) +{ +#ifdef RISCV_ENABLE_HISTOGRAM + size_t idx = pc >> 2; + pc_histogram[idx]++; +#endif +} + +static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch) +{ + reg_t npc = fetch.func(p, fetch.insn, pc); + if (npc != PC_SERIALIZE) { + commit_log(p->get_state(), pc, fetch.insn); + p->update_histogram(pc); + } + return npc; +} + +// fetch/decode/execute loop +void processor_t::step(size_t n) +{ + while (run && n > 0) { + size_t instret = 0; + reg_t pc = state.pc; + mmu_t* _mmu = mmu; + + #define advance_pc() \ + if (unlikely(pc == PC_SERIALIZE)) { \ + pc = state.pc; \ + state.serialized = true; \ + break; \ + } else { \ + state.pc = pc; \ + instret++; \ + } + + try + { + check_timer(); + take_interrupt(); + + if (unlikely(debug)) + { + while (instret < n) + { + insn_fetch_t fetch = mmu->load_insn(pc); + if (!state.serialized) + disasm(fetch.insn); + pc = execute_insn(this, pc, fetch); + advance_pc(); + } + } + else while (instret < n) + { + size_t idx = _mmu->icache_index(pc); + auto ic_entry = _mmu->access_icache(pc); + + #define ICACHE_ACCESS(i) { \ + insn_fetch_t fetch = ic_entry->data; \ + ic_entry++; \ + pc = execute_insn(this, pc, fetch); \ + if (i == mmu_t::ICACHE_ENTRIES-1) break; \ + if (unlikely(ic_entry->tag != pc)) goto miss; \ + if (unlikely(instret+1 == n)) break; \ + instret++; \ + state.pc = pc; \ + } + + switch (idx) { + #include "icache.h" + } + + advance_pc(); + continue; + +miss: + advance_pc(); + // refill I$ if it looks like there wasn't a taken branch + if (pc > (ic_entry-1)->tag && pc <= (ic_entry-1)->tag + MAX_INSN_LENGTH) + _mmu->refill_icache(pc, ic_entry); + } + } + catch(trap_t& t) + { + take_trap(t, pc); + } + + state.minstret += instret; + n -= instret; + } +} diff --git a/riscv/insns/c_add.h b/riscv/insns/c_add.h index c13385e..ab7d4d4 100644 --- a/riscv/insns/c_add.h +++ b/riscv/insns/c_add.h @@ -1,12 +1,3 @@ require_extension('C'); -if (insn.rvc_rs2() == 0) { - if (insn.rvc_rs1() == 0) { // c.ebreak - throw trap_breakpoint(); - } else { // c.jalr - reg_t tmp = npc; - set_pc(RVC_RS1 & ~reg_t(1)); - WRITE_REG(X_RA, tmp); - } -} else { - WRITE_RD(sext_xlen(RVC_RS1 + RVC_RS2)); -} +require(insn.rvc_rs2() != 0); +WRITE_RD(sext_xlen(RVC_RS1 + RVC_RS2)); diff --git a/riscv/insns/c_addi16sp.h b/riscv/insns/c_addi16sp.h new file mode 100644 index 0000000..3bc88a4 --- /dev/null +++ b/riscv/insns/c_addi16sp.h @@ -0,0 +1,3 @@ +require_extension('C'); +require(insn.rvc_addi16sp_imm() != 0); +WRITE_REG(X_SP, sext_xlen(RVC_SP + insn.rvc_addi16sp_imm())); diff --git a/riscv/insns/c_addiw.h b/riscv/insns/c_addiw.h index fe87872..05d3497 100644 --- a/riscv/insns/c_addiw.h +++ b/riscv/insns/c_addiw.h @@ -1,2 +1,3 @@ require_extension('C'); +require_rv64; WRITE_RD(sext32(RVC_RS1 + insn.rvc_imm())); diff --git a/riscv/insns/c_ebreak.h b/riscv/insns/c_ebreak.h new file mode 100644 index 0000000..a17200f --- /dev/null +++ b/riscv/insns/c_ebreak.h @@ -0,0 +1,2 @@ +require_extension('C'); +throw trap_breakpoint(); diff --git a/riscv/insns/c_jalr.h b/riscv/insns/c_jalr.h new file mode 100644 index 0000000..cb1e422 --- /dev/null +++ b/riscv/insns/c_jalr.h @@ -0,0 +1,5 @@ +require_extension('C'); +require(insn.rvc_rs1() != 0); +reg_t tmp = npc; +set_pc(RVC_RS1 & ~reg_t(1)); +WRITE_REG(X_RA, tmp); diff --git a/riscv/insns/c_jr.h b/riscv/insns/c_jr.h new file mode 100644 index 0000000..9c4a8ea --- /dev/null +++ b/riscv/insns/c_jr.h @@ -0,0 +1,3 @@ +require_extension('C'); +require(insn.rvc_rs1() != 0); +set_pc(RVC_RS1 & ~reg_t(1)); diff --git a/riscv/insns/c_lui.h b/riscv/insns/c_lui.h index cb76c61..e5060a3 100644 --- a/riscv/insns/c_lui.h +++ b/riscv/insns/c_lui.h @@ -1,6 +1,3 @@ require_extension('C'); -if (insn.rvc_rd() == 0) { // c.addi16sp - WRITE_REG(X_SP, sext_xlen(RVC_SP + insn.rvc_addi16sp_imm())); -} else { - WRITE_RD(insn.rvc_imm() << 12); -} +require(insn.rvc_rd() != 0); +WRITE_RD(insn.rvc_imm() << 12); diff --git a/riscv/insns/c_mv.h b/riscv/insns/c_mv.h index 4a23063..a03d0d0 100644 --- a/riscv/insns/c_mv.h +++ b/riscv/insns/c_mv.h @@ -1,7 +1,3 @@ require_extension('C'); -if (insn.rvc_rs2() == 0) { - require(insn.rvc_rd() != 0); - set_pc(RVC_RS1 & ~reg_t(1)); -} else { - WRITE_RD(RVC_RS2); -} +require(insn.rvc_rs2() != 0); +WRITE_RD(RVC_RS2); diff --git a/riscv/mmu.h b/riscv/mmu.h index ddb1d51..ce8685d 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -72,18 +72,11 @@ public: inline size_t icache_index(reg_t addr) { - // for instruction sizes != 4, this hash still works but is suboptimal - return (addr / 4) % ICACHE_ENTRIES; + return (addr / PC_ALIGN) % ICACHE_ENTRIES; } - // load instruction from memory at aligned address. - icache_entry_t* access_icache(reg_t addr) __attribute__((always_inline)) + inline icache_entry_t* refill_icache(reg_t addr, icache_entry_t* entry) { - reg_t idx = icache_index(addr); - icache_entry_t* entry = &icache[idx]; - if (likely(entry->tag == addr)) - return entry; - char* iaddr = (char*)translate(addr, 1, false, true); insn_bits_t insn = *(uint16_t*)iaddr; int length = insn_length(insn); @@ -106,16 +99,23 @@ public: } insn_fetch_t fetch = {proc->decode_insn(insn), insn}; - icache[idx].tag = addr; - icache[idx].data = fetch; + entry->tag = addr; + entry->data = fetch; reg_t paddr = iaddr - mem; - if (!tracer.empty() && tracer.interested_in_range(paddr, paddr + 1, false, true)) - { - icache[idx].tag = -1; + if (tracer.interested_in_range(paddr, paddr + 1, false, true)) { + entry->tag = -1; tracer.trace(paddr, length, false, true); } - return &icache[idx]; + return entry; + } + + inline icache_entry_t* access_icache(reg_t addr) + { + icache_entry_t* entry = &icache[icache_index(addr)]; + if (likely(entry->tag == addr)) + return entry; + return refill_icache(addr, entry); } inline insn_fetch_t load_insn(reg_t addr) diff --git a/riscv/processor.cc b/riscv/processor.cc index 5b53391..d1e7ce3 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -30,10 +30,7 @@ processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id) reset(true); - #define DECLARE_INSN(name, match, mask) REGISTER_INSN(this, name, match, mask) - #include "encoding.h" - #undef DECLARE_INSN - build_opcode_map(); + register_base_instructions(); } processor_t::~processor_t() @@ -173,121 +170,12 @@ void processor_t::take_interrupt() } } -static void commit_log(state_t* state, reg_t pc, insn_t insn) -{ -#ifdef RISCV_ENABLE_COMMITLOG - if (get_field(state->mstatus, MSTATUS_IE)) { - uint64_t mask = (insn.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn.length() * 8))) - 1; - if (state->log_reg_write.addr) { - fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIu64 " 0x%016" PRIx64 "\n", - pc, - insn.bits() & mask, - state->log_reg_write.addr & 1 ? 'f' : 'x', - state->log_reg_write.addr >> 1, - state->log_reg_write.data); - } else { - fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ")\n", pc, insn.bits() & mask); - } - } - state->log_reg_write.addr = 0; -#endif -} - -inline void processor_t::update_histogram(size_t pc) -{ -#ifdef RISCV_ENABLE_HISTOGRAM - size_t idx = pc >> 2; - pc_histogram[idx]++; -#endif -} - -static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch) -{ - reg_t npc = fetch.func(p, fetch.insn, pc); - if (npc != PC_SERIALIZE) { - commit_log(p->get_state(), pc, fetch.insn); - p->update_histogram(pc); - } - return npc; -} - void processor_t::check_timer() { if (sim->rtc >= state.mtimecmp) state.mip |= MIP_MTIP; } -void processor_t::step(size_t n) -{ - size_t instret = 0; - reg_t pc = state.pc; - mmu_t* _mmu = mmu; - - if (unlikely(!run || !n)) - return; - - #define maybe_serialize() \ - if (unlikely(pc == PC_SERIALIZE)) { \ - pc = state.pc; \ - state.serialized = true; \ - break; \ - } - - try - { - check_timer(); - take_interrupt(); - - if (unlikely(debug)) - { - while (instret < n) - { - insn_fetch_t fetch = mmu->load_insn(pc); - if (!state.serialized) - disasm(fetch.insn); - pc = execute_insn(this, pc, fetch); - maybe_serialize(); - instret++; - state.pc = pc; - } - } - else while (instret < n) - { - size_t idx = _mmu->icache_index(pc); - auto ic_entry = _mmu->access_icache(pc); - - #define ICACHE_ACCESS(idx) { \ - insn_fetch_t fetch = ic_entry->data; \ - ic_entry++; \ - pc = execute_insn(this, pc, fetch); \ - if (idx == mmu_t::ICACHE_ENTRIES-1) break; \ - if (unlikely(ic_entry->tag != pc)) break; \ - if (unlikely(instret+1 == n)) break; \ - instret++; \ - state.pc = pc; \ - } - - switch (idx) { - #include "icache.h" - } - - maybe_serialize(); - instret++; - state.pc = pc; - } - } - catch(trap_t& t) - { - take_trap(t, pc); - } - - state.minstret += instret; - - // tail-recurse if we didn't execute as many instructions as we'd hoped - if (instret < n) - step(n - instret); -} - void processor_t::push_privilege_stack() { reg_t s = state.mstatus; @@ -463,7 +351,7 @@ void processor_t::set_csr(int which, reg_t val) break; } case CSR_SEPC: state.sepc = val; break; - case CSR_STVEC: state.stvec = val & ~3; break; + case CSR_STVEC: state.stvec = val >> 2 << 2; break; case CSR_SPTBR: state.sptbr = zext_xlen(val & -PGSIZE); break; case CSR_SSCRATCH: state.sscratch = val; break; case CSR_MEPC: state.mepc = val; break; @@ -602,55 +490,51 @@ reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc) insn_func_t processor_t::decode_insn(insn_t insn) { - size_t mask = opcode_map.size()-1; - insn_desc_t* desc = opcode_map[insn.bits() & mask]; + // look up opcode in hash table + size_t idx = insn.bits() % OPCODE_CACHE_SIZE; + insn_desc_t desc = opcode_cache[idx]; + + if (unlikely(insn.bits() != desc.match)) { + // fall back to linear search + insn_desc_t* p = &instructions[0]; + while ((insn.bits() & p->mask) != p->match) + p++; + desc = *p; + + if (p->mask != 0 && p > &instructions[0]) { + if (p->match != (p-1)->match && p->match != (p+1)->match) { + // move to front of opcode list to reduce miss penalty + while (--p >= &instructions[0]) + *(p+1) = *p; + instructions[0] = desc; + } + } - while ((insn.bits() & desc->mask) != desc->match) - desc++; + opcode_cache[idx] = desc; + opcode_cache[idx].match = insn.bits(); + } - return xlen == 64 ? desc->rv64 : desc->rv32; + return xlen == 64 ? desc.rv64 : desc.rv32; } void processor_t::register_insn(insn_desc_t desc) { - assert(desc.mask & 1); instructions.push_back(desc); } void processor_t::build_opcode_map() { - size_t buckets = -1; - for (auto& inst : instructions) - while ((inst.mask & buckets) != buckets) - buckets /= 2; - buckets++; - struct cmp { - decltype(insn_desc_t::match) mask; - cmp(decltype(mask) mask) : mask(mask) {} bool operator()(const insn_desc_t& lhs, const insn_desc_t& rhs) { - if ((lhs.match & mask) != (rhs.match & mask)) - return (lhs.match & mask) < (rhs.match & mask); - return lhs.match < rhs.match; + if (lhs.match == rhs.match) + return lhs.mask > rhs.mask; + return lhs.match > rhs.match; } }; - std::sort(instructions.begin(), instructions.end(), cmp(buckets-1)); - - opcode_map.resize(buckets); - opcode_store.resize(instructions.size() + 1); + std::sort(instructions.begin(), instructions.end(), cmp()); - size_t j = 0; - for (size_t b = 0, i = 0; b < buckets; b++) - { - opcode_map[b] = &opcode_store[j]; - while (i < instructions.size() && b == (instructions[i].match & (buckets-1))) - opcode_store[j++] = instructions[i++]; - } - - assert(j == opcode_store.size()-1); - opcode_store[j].match = opcode_store[j].mask = 0; - opcode_store[j].rv32 = &illegal_instruction; - opcode_store[j].rv64 = &illegal_instruction; + for (size_t i = 0; i < OPCODE_CACHE_SIZE; i++) + opcode_cache[i] = {1, 0, &illegal_instruction, &illegal_instruction}; } void processor_t::register_extension(extension_t* x) @@ -665,3 +549,23 @@ void processor_t::register_extension(extension_t* x) ext = x; x->set_processor(this); } + +void processor_t::register_base_instructions() +{ + std::map> opcodes; + + #define DECLARE_INSN(name, match, mask) \ + opcodes[#name] = std::make_pair(match, mask); + #include "encoding.h" + #undef DECLARE_INSN + + #define DEFINE_INSN(name) \ + if (!opcodes.count(#name)) \ + throw std::logic_error("opcode for " #name " not found"); \ + REGISTER_INSN(this, name, opcodes[#name].first, opcodes[#name].second) + #include "insn_list.h" + #undef DEFINE_INSN + + register_insn({0, 0, &illegal_instruction, &illegal_instruction}); + build_opcode_map(); +} diff --git a/riscv/processor.h b/riscv/processor.h index 6af7887..d117ff1 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -18,8 +18,8 @@ class disassembler_t; struct insn_desc_t { - uint32_t match; - uint32_t mask; + insn_bits_t match; + insn_bits_t mask; insn_func_t rv32; insn_func_t rv64; }; @@ -115,10 +115,11 @@ private: bool histogram_enabled; std::vector instructions; - std::vector opcode_map; - std::vector opcode_store; std::map pc_histogram; + static const size_t OPCODE_CACHE_SIZE = 8191; + insn_desc_t opcode_cache[OPCODE_CACHE_SIZE]; + void check_timer(); void take_interrupt(); // take a trap if any interrupts are pending void take_trap(trap_t& t, reg_t epc); // take an exception @@ -130,6 +131,7 @@ private: void parse_isa_string(const char* isa); void build_opcode_map(); + void register_base_instructions(); insn_func_t decode_insn(insn_t insn); }; diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 7ce2cb9..f35f200 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -29,6 +29,7 @@ riscv_precompiled_hdrs = \ riscv_srcs = \ htif.cc \ processor.cc \ + execute.cc \ sim.cc \ interactive.cc \ trap.cc \ @@ -45,9 +46,203 @@ riscv_test_srcs = riscv_gen_hdrs = \ icache.h \ + insn_list.h \ + +riscv_insn_list = \ + add \ + addi \ + addiw \ + addw \ + amoadd_d \ + amoadd_w \ + amoand_d \ + amoand_w \ + amomax_d \ + amomaxu_d \ + amomaxu_w \ + amomax_w \ + amomin_d \ + amominu_d \ + amominu_w \ + amomin_w \ + amoor_d \ + amoor_w \ + amoswap_d \ + amoswap_w \ + amoxor_d \ + amoxor_w \ + and \ + andi \ + auipc \ + beq \ + bge \ + bgeu \ + blt \ + bltu \ + bne \ + c_add \ + c_addi16sp \ + c_addi4spn \ + c_addi \ + c_addiw \ + c_addw \ + c_beqz \ + c_bnez \ + c_ebreak \ + c_fld \ + c_fldsp \ + c_flw \ + c_flwsp \ + c_fsd \ + c_fsdsp \ + c_fsw \ + c_fswsp \ + c_jal \ + c_jalr \ + c_j \ + c_jr \ + c_li \ + c_lui \ + c_lw \ + c_lwsp \ + c_mv \ + c_slli \ + csrrc \ + csrrci \ + csrrs \ + csrrsi \ + csrrw \ + csrrwi \ + c_sw \ + c_swsp \ + div \ + divu \ + divuw \ + divw \ + fadd_d \ + fadd_s \ + fclass_d \ + fclass_s \ + fcvt_d_l \ + fcvt_d_lu \ + fcvt_d_s \ + fcvt_d_w \ + fcvt_d_wu \ + fcvt_l_d \ + fcvt_l_s \ + fcvt_lu_d \ + fcvt_lu_s \ + fcvt_s_d \ + fcvt_s_l \ + fcvt_s_lu \ + fcvt_s_w \ + fcvt_s_wu \ + fcvt_w_d \ + fcvt_w_s \ + fcvt_wu_d \ + fcvt_wu_s \ + fdiv_d \ + fdiv_s \ + fence \ + fence_i \ + feq_d \ + feq_s \ + fld \ + fle_d \ + fle_s \ + flt_d \ + flt_s \ + flw \ + fmadd_d \ + fmadd_s \ + fmax_d \ + fmax_s \ + fmin_d \ + fmin_s \ + fmsub_d \ + fmsub_s \ + fmul_d \ + fmul_s \ + fmv_d_x \ + fmv_s_x \ + fmv_x_d \ + fmv_x_s \ + fnmadd_d \ + fnmadd_s \ + fnmsub_d \ + fnmsub_s \ + fsd \ + fsgnj_d \ + fsgnjn_d \ + fsgnjn_s \ + fsgnj_s \ + fsgnjx_d \ + fsgnjx_s \ + fsqrt_d \ + fsqrt_s \ + fsub_d \ + fsub_s \ + fsw \ + hrts \ + jal \ + jalr \ + lb \ + lbu \ + ld \ + lh \ + lhu \ + lr_d \ + lr_w \ + lui \ + lw \ + lwu \ + mrth \ + mrts \ + mul \ + mulh \ + mulhsu \ + mulhu \ + mulw \ + or \ + ori \ + rem \ + remu \ + remuw \ + remw \ + sb \ + sbreak \ + scall \ + sc_d \ + sc_w \ + sd \ + sfence_vm \ + sh \ + sll \ + slli \ + slliw \ + sllw \ + slt \ + slti \ + sltiu \ + sltu \ + sra \ + srai \ + sraiw \ + sraw \ + sret \ + srl \ + srli \ + srliw \ + srlw \ + sub \ + subw \ + sw \ + wfi \ + xor \ + xori \ riscv_gen_srcs = \ - $(addsuffix .cc, $(call get_insn_list,$(src_dir)/riscv/encoding.h)) + $(addsuffix .cc,$(riscv_insn_list)) icache_entries := `grep "ICACHE_ENTRIES =" $(src_dir)/riscv/mmu.h | sed 's/.* = \(.*\);/\1/'` @@ -55,6 +250,10 @@ icache.h: mmu.h $(src_dir)/riscv/gen_icache $(icache_entries) > $@.tmp mv $@.tmp $@ +insn_list.h: $(src_dir)/riscv/riscv.mk.in + echo $(riscv_insn_list) | sed 's/\s\+\|$$/\n/g' | sed '/^$$/d' | sed 's/\./_/g' | sed 's/\(.*\)/DEFINE_INSN(\1)/' > $@.tmp + mv $@.tmp $@ + $(riscv_gen_srcs): %.cc: insns/%.h insn_template.cc sed 's/NAME/$(subst .cc,,$@)/' $(src_dir)/riscv/insn_template.cc | sed 's/OPCODE/$(call get_opcode,$(src_dir)/riscv/encoding.h,$(subst .cc,,$@))/' > $@