4 Commits

16 changed files with 3843 additions and 3578 deletions

View File

@ -1,5 +1,5 @@
RV32I: RVI:
LUI: LUI:
index: 0 index: 0
encoding: 0b00000000000000000000000000110111 encoding: 0b00000000000000000000000000110111
@ -27,84 +27,84 @@ RV32I:
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: true branch: true
delay: [1,2] delay: [1,1]
BEQ: BEQ:
index: 4 index: 4
encoding: 0b00000000000000000000000001100011 encoding: 0b00000000000000000000000001100011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: true branch: true
delay: [1,2] delay: [1,1]
BNE: BNE:
index: 5 index: 5
encoding: 0b00000000000000000001000001100011 encoding: 0b00000000000000000001000001100011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: true branch: true
delay: [1,2] delay: [1,1]
BLT: BLT:
index: 6 index: 6
encoding: 0b00000000000000000100000001100011 encoding: 0b00000000000000000100000001100011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: true branch: true
delay: [1,2] delay: [1,1]
BGE: BGE:
index: 7 index: 7
encoding: 0b00000000000000000101000001100011 encoding: 0b00000000000000000101000001100011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: true branch: true
delay: [1,2] delay: [1,1]
BLTU: BLTU:
index: 8 index: 8
encoding: 0b00000000000000000110000001100011 encoding: 0b00000000000000000110000001100011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: true branch: true
delay: [1,2] delay: [1,1]
BGEU: BGEU:
index: 9 index: 9
encoding: 0b00000000000000000111000001100011 encoding: 0b00000000000000000111000001100011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: true branch: true
delay: [1,2] delay: [1,1]
LB: LB:
index: 10 index: 10
encoding: 0b00000000000000000000000000000011 encoding: 0b00000000000000000000000000000011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
LH: LH:
index: 11 index: 11
encoding: 0b00000000000000000001000000000011 encoding: 0b00000000000000000001000000000011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
LW: LW:
index: 12 index: 12
encoding: 0b00000000000000000010000000000011 encoding: 0b00000000000000000010000000000011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
LBU: LBU:
index: 13 index: 13
encoding: 0b00000000000000000100000000000011 encoding: 0b00000000000000000100000000000011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
LHU: LHU:
index: 14 index: 14
encoding: 0b00000000000000000101000000000011 encoding: 0b00000000000000000101000000000011
mask: 0b00000000000000000111000001111111 mask: 0b00000000000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
SB: SB:
index: 15 index: 15
encoding: 0b00000000000000000000000000100011 encoding: 0b00000000000000000000000000100011
@ -356,56 +356,56 @@ RV32M:
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
MULH: MULH:
index: 50 index: 50
encoding: 0b00000010000000000001000000110011 encoding: 0b00000010000000000001000000110011
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
MULHSU: MULHSU:
index: 51 index: 51
encoding: 0b00000010000000000010000000110011 encoding: 0b00000010000000000010000000110011
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
MULHU: MULHU:
index: 52 index: 52
encoding: 0b00000010000000000011000000110011 encoding: 0b00000010000000000011000000110011
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 2 delay: 1
DIV: DIV:
index: 53 index: 53
encoding: 0b00000010000000000100000000110011 encoding: 0b00000010000000000100000000110011
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 17 delay: 1
DIVU: DIVU:
index: 54 index: 54
encoding: 0b00000010000000000101000000110011 encoding: 0b00000010000000000101000000110011
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 17 delay: 1
REM: REM:
index: 55 index: 55
encoding: 0b00000010000000000110000000110011 encoding: 0b00000010000000000110000000110011
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 17 delay: 1
REMU: REMU:
index: 56 index: 56
encoding: 0b00000010000000000111000000110011 encoding: 0b00000010000000000111000000110011
mask: 0b11111110000000000111000001111111 mask: 0b11111110000000000111000001111111
size: 32 size: 32
branch: false branch: false
delay: 17 delay: 1
Zca: Zca:
C__ADDI4SPN: C__ADDI4SPN:
index: 57 index: 57
@ -420,7 +420,7 @@ Zca:
mask: 0b1110000000000011 mask: 0b1110000000000011
size: 16 size: 16
branch: false branch: false
delay: 2 delay: 1
C__SW: C__SW:
index: 59 index: 59
encoding: 0b1100000000000000 encoding: 0b1100000000000000
@ -542,14 +542,14 @@ Zca:
mask: 0b1110000000000011 mask: 0b1110000000000011
size: 16 size: 16
branch: true branch: true
delay: [1,2] delay: [1,1]
C__BNEZ: C__BNEZ:
index: 76 index: 76
encoding: 0b1110000000000001 encoding: 0b1110000000000001
mask: 0b1110000000000011 mask: 0b1110000000000011
size: 16 size: 16
branch: true branch: true
delay: [1,2] delay: [1,1]
C__SLLI: C__SLLI:
index: 77 index: 77
encoding: 0b0000000000000010 encoding: 0b0000000000000010
@ -564,7 +564,7 @@ Zca:
mask: 0b1110000000000011 mask: 0b1110000000000011
size: 16 size: 16
branch: false branch: false
delay: 2 delay: 1
C__MV: C__MV:
index: 79 index: 79
encoding: 0b1000000000000010 encoding: 0b1000000000000010

View File

@ -37,6 +37,7 @@ def getRegisterSizes(){
return regs return regs
} }
%> %>
// clang-format off
#include "${coreDef.name.toLowerCase()}.h" #include "${coreDef.name.toLowerCase()}.h"
#include "util/ities.h" #include "util/ities.h"
#include <util/logging.h> #include <util/logging.h>
@ -73,4 +74,4 @@ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) { ${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
} }
// clang-format on

View File

@ -60,7 +60,7 @@ def getCString(def val){
%> %>
#ifndef _${coreDef.name.toUpperCase()}_H_ #ifndef _${coreDef.name.toUpperCase()}_H_
#define _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_
// clang-format off
#include <array> #include <array>
#include <iss/arch/traits.h> #include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
@ -174,3 +174,4 @@ if(fcsr != null) {%>
} }
} }
#endif /* _${coreDef.name.toUpperCase()}_H_ */ #endif /* _${coreDef.name.toUpperCase()}_H_ */
// clang-format on

View File

@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
*******************************************************************************/ *******************************************************************************/
// clang-format off
#include <sysc/iss_factory.h> #include <sysc/iss_factory.h>
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/arch/riscv_hart_m_p.h> #include <iss/arch/riscv_hart_m_p.h>
@ -128,3 +128,4 @@ volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
} }
#endif #endif
} }
// clang-format on

View File

@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
*******************************************************************************/ *******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h> #include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
@ -37,7 +37,7 @@
#include <iss/asmjit/vm_base.h> #include <iss/asmjit/vm_base.h>
#include <asmjit/asmjit.h> #include <asmjit/asmjit.h>
#include <util/logging.h> #include <util/logging.h>
#include <fp_functions.h>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
@ -92,7 +92,7 @@ protected:
auto sign_mask = 1ULL<<(W-1); auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0); return (from & mask) | ((from & sign_mask) ? ~mask : 0);
} }
#include "helper_func.h" #include <vm/asmjit/helper_func.h>
private: private:
/**************************************************************************** /****************************************************************************
@ -278,3 +278,4 @@ volatile std::array<bool, 2> dummy = {
}; };
} }
} }
// clang-format on

View File

@ -34,6 +34,7 @@ def nativeTypeSize(int size){
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
} }
%> %>
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h> #include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
@ -377,3 +378,4 @@ volatile std::array<bool, 2> dummy = {
}; };
} }
} }
// clang-format on

View File

@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
*******************************************************************************/ *******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h> #include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
@ -380,3 +380,4 @@ volatile std::array<bool, 2> dummy = {
}; };
} }
} }
// clang-format on

View File

@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
*******************************************************************************/ *******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h> #include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
@ -344,3 +344,4 @@ volatile std::array<bool, 2> dummy = {
}; };
} }
} }
// clang-format on

View File

@ -320,6 +320,8 @@ protected:
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
riscv_hart_m_p<BASE, FEAT>& arch; riscv_hart_m_p<BASE, FEAT>& arch;
}; };
@ -822,7 +824,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
x |= 0x80; // set pll lock upon writing x |= 0x80; // set pll lock upon writing
return iss::Ok; return iss::Ok;
} break; } break;
default: {} default: {
}
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {

View File

@ -371,6 +371,8 @@ protected:
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
riscv_hart_msu_vp<BASE>& arch; riscv_hart_msu_vp<BASE>& arch;
}; };
@ -802,7 +804,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
x |= 0x80; // set pll lock upon writing x |= 0x80; // set pll lock upon writing
return iss::Ok; return iss::Ok;
} break; } break;
default: {} default: {
}
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
@ -1225,9 +1228,9 @@ template <typename BASE> typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_har
break; break;
} else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { } else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break; break;
} else if(type == iss::access_type::FETCH ? !(pte & PTE_X) } else if(type == iss::access_type::FETCH ? !(pte & PTE_X)
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
: !((pte & PTE_R) && (pte & PTE_W))) { : !((pte & PTE_R) && (pte & PTE_W))) {
break; break;
} else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { } else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break; break;

View File

@ -347,6 +347,8 @@ protected:
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
riscv_hart_mu_p<BASE, FEAT>& arch; riscv_hart_mu_p<BASE, FEAT>& arch;
}; };
@ -1005,7 +1007,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
x |= 0x80; // set pll lock upon writing x |= 0x80; // set pll lock upon writing
return iss::Ok; return iss::Ok;
} break; } break;
default: {} default: {
}
} }
} break; } break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {

View File

@ -30,37 +30,41 @@
* *
*******************************************************************************/ *******************************************************************************/
// clang-format off
#include "tgc5c.h" #include "tgc5c.h"
#include "util/ities.h" #include "util/ities.h"
#include <util/logging.h>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <util/logging.h>
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_names; constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_names;
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_aliases; constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_aliases;
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_bit_widths; constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_bit_widths;
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_byte_offsets; constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_byte_offsets;
tgc5c::tgc5c() = default; tgc5c::tgc5c() = default;
tgc5c::~tgc5c() = default; tgc5c::~tgc5c() = default;
void tgc5c::reset(uint64_t address) { void tgc5c::reset(uint64_t address) {
auto base_ptr = reinterpret_cast<traits<tgc5c>::reg_t*>(get_regs_base_ptr()); auto base_ptr = reinterpret_cast<traits<tgc5c>::reg_t*>(get_regs_base_ptr());
for(size_t i = 0; i < traits<tgc5c>::NUM_REGS; ++i) for(size_t i=0; i<traits<tgc5c>::NUM_REGS; ++i)
*(base_ptr + i) = 0; *(base_ptr+i)=0;
reg.PC = address; reg.PC=address;
reg.NEXT_PC = reg.PC; reg.NEXT_PC=reg.PC;
reg.PRIV = 0x3; reg.PRIV=0x3;
reg.trap_state = 0; reg.trap_state=0;
reg.icount = 0; reg.icount=0;
} }
uint8_t* tgc5c::get_regs_base_ptr() { return reinterpret_cast<uint8_t*>(&reg); } uint8_t *tgc5c::get_regs_base_ptr() {
return reinterpret_cast<uint8_t*>(&reg);
tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t& addr) {
return phys_addr_t(addr.access, addr.space, addr.val & traits<tgc5c>::addr_mask);
} }
tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<tgc5c>::addr_mask);
}
// clang-format on

View File

@ -32,7 +32,7 @@
#ifndef _TGC5C_H_ #ifndef _TGC5C_H_
#define _TGC5C_H_ #define _TGC5C_H_
// clang-format off
#include <array> #include <array>
#include <iss/arch/traits.h> #include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
@ -46,103 +46,43 @@ struct tgc5c;
template <> struct traits<tgc5c> { template <> struct traits<tgc5c> {
constexpr static char const* const core_type = "TGC5C"; constexpr static char const* const core_type = "TGC5C";
static constexpr std::array<const char*, 36> reg_names{{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", static constexpr std::array<const char*, 36> reg_names{
"x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}};
"x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26",
"x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}};
static constexpr std::array<const char*, 36> reg_aliases{ static constexpr std::array<const char*, 36> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}};
"s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}};
enum constants { enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL};
MISA_VAL = 1073746180ULL,
MARCHID_VAL = 2147483651ULL,
XLEN = 32ULL,
INSTR_ALIGNMENT = 2ULL,
RFS = 32ULL,
fence = 0ULL,
fencei = 1ULL,
fencevmal = 2ULL,
fencevmau = 3ULL,
CSR_SIZE = 4096ULL,
MUL_LEN = 64ULL
};
constexpr static unsigned FP_REGS_SIZE = 0; constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e { enum reg_e {
X0, X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
X1,
X2,
X3,
X4,
X5,
X6,
X7,
X8,
X9,
X10,
X11,
X12,
X13,
X14,
X15,
X16,
X17,
X18,
X19,
X20,
X21,
X22,
X23,
X24,
X25,
X26,
X27,
X28,
X29,
X30,
X31,
PC,
NEXT_PC,
PRIV,
DPC,
NUM_REGS,
TRAP_STATE = NUM_REGS,
PENDING_TRAP,
ICOUNT,
CYCLE,
INSTRET,
INSTRUCTION,
LAST_BRANCH
}; };
using reg_t = uint32_t; using reg_t = uint32_t;
using addr_t = uint32_t; using addr_t = uint32_t;
using code_word_t = uint32_t; // TODO: check removal using code_word_t = uint32_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>; using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 43> reg_bit_widths{{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, static constexpr std::array<const uint32_t, 43> reg_bit_widths{
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32,32}};
32, 32, 32, 32, 8, 32, 32, 32, 64, 64, 64, 32, 32}};
static constexpr std::array<const uint32_t, 43> reg_byte_offsets{ static constexpr std::array<const uint32_t, 43> reg_byte_offsets{
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}};
88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 137, 141, 145, 149, 157, 165, 173, 177}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e { FLAGS }; enum sreg_flag_e { FLAGS };
enum mem_type_e { MEM, FENCE, RES, CSR }; enum mem_type_e { MEM, FENCE, RES, CSR };
enum class opcode_e { enum class opcode_e {
LUI = 0, LUI = 0,
AUIPC = 1, AUIPC = 1,
@ -235,17 +175,17 @@ template <> struct traits<tgc5c> {
}; };
}; };
struct tgc5c : public arch_if { struct tgc5c: public arch_if {
using virt_addr_t = typename traits<tgc5c>::virt_addr_t; using virt_addr_t = typename traits<tgc5c>::virt_addr_t;
using phys_addr_t = typename traits<tgc5c>::phys_addr_t; using phys_addr_t = typename traits<tgc5c>::phys_addr_t;
using reg_t = typename traits<tgc5c>::reg_t; using reg_t = typename traits<tgc5c>::reg_t;
using addr_t = typename traits<tgc5c>::addr_t; using addr_t = typename traits<tgc5c>::addr_t;
tgc5c(); tgc5c();
~tgc5c(); ~tgc5c();
void reset(uint64_t address = 0) override; void reset(uint64_t address=0) override;
uint8_t* get_regs_base_ptr() override; uint8_t* get_regs_base_ptr() override;
@ -261,43 +201,44 @@ struct tgc5c : public arch_if {
inline uint32_t get_last_branch() { return reg.last_branch; } inline uint32_t get_last_branch() { return reg.last_branch; }
#pragma pack(push, 1) #pragma pack(push, 1)
struct TGC5C_regs { struct TGC5C_regs {
uint32_t X0 = 0; uint32_t X0 = 0;
uint32_t X1 = 0; uint32_t X1 = 0;
uint32_t X2 = 0; uint32_t X2 = 0;
uint32_t X3 = 0; uint32_t X3 = 0;
uint32_t X4 = 0; uint32_t X4 = 0;
uint32_t X5 = 0; uint32_t X5 = 0;
uint32_t X6 = 0; uint32_t X6 = 0;
uint32_t X7 = 0; uint32_t X7 = 0;
uint32_t X8 = 0; uint32_t X8 = 0;
uint32_t X9 = 0; uint32_t X9 = 0;
uint32_t X10 = 0; uint32_t X10 = 0;
uint32_t X11 = 0; uint32_t X11 = 0;
uint32_t X12 = 0; uint32_t X12 = 0;
uint32_t X13 = 0; uint32_t X13 = 0;
uint32_t X14 = 0; uint32_t X14 = 0;
uint32_t X15 = 0; uint32_t X15 = 0;
uint32_t X16 = 0; uint32_t X16 = 0;
uint32_t X17 = 0; uint32_t X17 = 0;
uint32_t X18 = 0; uint32_t X18 = 0;
uint32_t X19 = 0; uint32_t X19 = 0;
uint32_t X20 = 0; uint32_t X20 = 0;
uint32_t X21 = 0; uint32_t X21 = 0;
uint32_t X22 = 0; uint32_t X22 = 0;
uint32_t X23 = 0; uint32_t X23 = 0;
uint32_t X24 = 0; uint32_t X24 = 0;
uint32_t X25 = 0; uint32_t X25 = 0;
uint32_t X26 = 0; uint32_t X26 = 0;
uint32_t X27 = 0; uint32_t X27 = 0;
uint32_t X28 = 0; uint32_t X28 = 0;
uint32_t X29 = 0; uint32_t X29 = 0;
uint32_t X30 = 0; uint32_t X30 = 0;
uint32_t X31 = 0; uint32_t X31 = 0;
uint32_t PC = 0; uint32_t PC = 0;
uint32_t NEXT_PC = 0; uint32_t NEXT_PC = 0;
uint8_t PRIV = 0; uint8_t PRIV = 0;
uint32_t DPC = 0; uint32_t DPC = 0;
uint32_t trap_state = 0, pending_trap = 0; uint32_t trap_state = 0, pending_trap = 0;
uint64_t icount = 0; uint64_t icount = 0;
@ -308,13 +249,15 @@ struct tgc5c : public arch_if {
} reg; } reg;
#pragma pack(pop) #pragma pack(pop)
std::array<address_type, 4> addr_mode; std::array<address_type, 4> addr_mode;
uint64_t interrupt_sim=0;
uint64_t interrupt_sim = 0; uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
uint32_t get_fcsr() { return 0; }
void set_fcsr(uint32_t val) {}
}; };
} // namespace arch }
} // namespace iss }
#endif /* _TGC5C_H_ */ #endif /* _TGC5C_H_ */
// clang-format on

View File

@ -19,7 +19,7 @@ x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx) {
} }
} }
x86::Gp get_reg_for(jit_holder& jh, unsigned idx) { x86::Gp get_reg_for(jit_holder& jh, unsigned idx) {
// can check for regs in jh and return them instead of creating new ones // TODO can check for regs in jh and return them instead of creating new ones
switch(traits::reg_bit_widths[idx]) { switch(traits::reg_bit_widths[idx]) {
case 8: case 8:
return jh.cc.newInt8(); return jh.cc.newInt8();
@ -82,7 +82,9 @@ void gen_instr_prologue(jit_holder& jh, addr_t pc) {
cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc); cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc);
cc.comment("\n//*trap_state=*pending_trap;"); cc.comment("\n//*trap_state=*pending_trap;");
cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), jh.trap_state); x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE));
cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), current_trap_state);
cc.comment("\n//increment *next_pc"); cc.comment("\n//increment *next_pc");
cc.mov(jh.next_pc, pc); cc.mov(jh.next_pc, pc);
@ -91,20 +93,20 @@ void gen_instr_epilogue(jit_holder& jh) {
auto& cc = jh.cc; auto& cc = jh.cc;
cc.comment("\n//if(*trap_state!=0) goto trap_entry;"); cc.comment("\n//if(*trap_state!=0) goto trap_entry;");
cc.test(jh.trap_state, jh.trap_state); x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
cc.jnz(jh.trap_entry); cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE));
cc.cmp(current_trap_state, 0);
cc.jne(jh.trap_entry);
// Does this need to be done after every single instruction? // TODO: Does not need to be done for every instruction, only when needed
cc.comment("\n//write back regs to mem"); cc.comment("\n//write back regs to mem");
write_reg_to_mem(jh, jh.pc, traits::PC); write_reg_to_mem(jh, jh.pc, traits::PC);
write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC); write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC);
write_reg_to_mem(jh, jh.trap_state, traits::TRAP_STATE);
} }
void gen_block_prologue(jit_holder& jh) override { void gen_block_prologue(jit_holder& jh) override {
jh.pc = load_reg_from_mem(jh, traits::PC); jh.pc = load_reg_from_mem(jh, traits::PC);
jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC); jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC);
jh.trap_state = load_reg_from_mem(jh, traits::TRAP_STATE);
} }
void gen_block_epilogue(jit_holder& jh) override { void gen_block_epilogue(jit_holder& jh) override {
x86::Compiler& cc = jh.cc; x86::Compiler& cc = jh.cc;
@ -112,7 +114,12 @@ void gen_block_epilogue(jit_holder& jh) override {
cc.ret(jh.next_pc); cc.ret(jh.next_pc);
cc.bind(jh.trap_entry); cc.bind(jh.trap_entry);
cc.comment("\n//enter_trap(core_ptr, *trap_state, *pc, 0);"); cc.comment("\n//Prepare for enter_trap;");
// Make sure cached values are written back
cc.comment("\n//write back regs to mem");
write_reg_to_mem(jh, jh.pc, traits::PC);
write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC);
this->gen_sync(jh, POST_SYNC, -1);
x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE); x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE);
cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE)); cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE));
@ -121,23 +128,43 @@ void gen_block_epilogue(jit_holder& jh) override {
cc.mov(current_pc, get_reg_ptr(jh, traits::PC)); cc.mov(current_pc, get_reg_ptr(jh, traits::PC));
x86::Gp instr = cc.newInt32("instr"); x86::Gp instr = cc.newInt32("instr");
cc.mov(instr, 0); cc.mov(instr, 0); // this is not correct
cc.comment("\n//enter trap call;");
InvokeNode* call_enter_trap; InvokeNode* call_enter_trap;
cc.invoke(&call_enter_trap, &enter_trap, FuncSignatureT<uint64_t, void*, uint64_t, uint64_t, uint64_t>()); cc.invoke(&call_enter_trap, &enter_trap, FuncSignatureT<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
call_enter_trap->setArg(0, jh.arch_if_ptr); call_enter_trap->setArg(0, jh.arch_if_ptr);
call_enter_trap->setArg(1, current_trap_state); call_enter_trap->setArg(1, current_trap_state);
call_enter_trap->setArg(2, current_pc); call_enter_trap->setArg(2, current_pc);
call_enter_trap->setArg(3, instr); call_enter_trap->setArg(3, instr);
x86::Gp current_next_pc = get_reg_for(jh, traits::NEXT_PC);
cc.mov(current_next_pc, get_reg_ptr(jh, traits::NEXT_PC));
cc.mov(jh.next_pc, current_next_pc);
cc.comment("\n//*last_branch = std::numeric_limits<uint32_t>::max();"); cc.comment("\n//*last_branch = std::numeric_limits<uint32_t>::max();");
cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max()); cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max());
cc.comment("\n//return *next_pc;"); cc.comment("\n//return *next_pc;");
cc.ret(jh.next_pc); cc.ret(jh.next_pc);
} }
// TODO implement /*
inline void raise(uint16_t trap_id, uint16_t cause){
void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { jh.cc.comment("//gen_raise"); } auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
void gen_wait(jit_holder& jh, unsigned type) { jh.cc.comment("//gen_wait"); } this->core.reg.trap_state = trap_val;
void gen_leave(jit_holder& jh, unsigned lvl) { jh.cc.comment("//gen_leave"); } this->template get_reg<uint32_t>(traits::NEXT_PC) = std::numeric_limits<uint32_t>::max();
}
*/
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
auto& cc = jh.cc;
cc.comment("//gen_raise");
auto tmp1 = get_reg_for(jh, traits::TRAP_STATE);
cc.mov(tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
cc.mov(get_reg_ptr(jh, traits::TRAP_STATE), tmp1);
auto tmp2 = get_reg_for(jh, traits::NEXT_PC);
cc.mov(tmp2, std::numeric_limits<uint32_t>::max());
cc.mov(get_reg_ptr(jh, traits::NEXT_PC), tmp2);
}
inline void gen_wait(jit_holder& jh, unsigned type) { jh.cc.comment("//gen_wait"); }
inline void gen_leave(jit_holder& jh, unsigned lvl) { jh.cc.comment("//gen_leave"); }
enum operation { add, sub, band, bor, bxor, shl, sar, shr }; enum operation { add, sub, band, bor, bxor, shl, sar, shr };
@ -342,24 +369,12 @@ x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a) {
return a; return a;
} }
/* template <typename T>
inline typename std::enable_if_t<std::is_unsigned<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool
is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg,
val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp;
}
template <typename T>
inline typename std::enable_if_t<std::is_signed<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool
is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg,
val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp;
} */
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) { inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) {
auto val_reg = get_reg_for(jh, sizeof(val) * 8); auto val_reg = get_reg_for(jh, sizeof(val) * 8, is_signed);
jh.cc.mov(val_reg, val); jh.cc.mov(val_reg, val);
return gen_ext(jh, val_reg, size, is_signed); return gen_ext(jh, val_reg, size, is_signed);
} }
// explicit Gp size cast
inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) { inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) {
auto& cc = jh.cc; auto& cc = jh.cc;
if(is_signed) { if(is_signed) {
@ -398,7 +413,6 @@ inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signe
throw std::runtime_error("Invalid size in gen_ext"); throw std::runtime_error("Invalid size in gen_ext");
} }
} }
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint32_t length) { inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint32_t length) {
x86::Compiler& cc = jh.cc; x86::Compiler& cc = jh.cc;
auto ret_reg = cc.newInt32(); auto ret_reg = cc.newInt32();
@ -447,31 +461,18 @@ inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint3
invokeNode->setArg(2, mem_type_reg); invokeNode->setArg(2, mem_type_reg);
invokeNode->setArg(3, addr); invokeNode->setArg(3, addr);
invokeNode->setArg(4, val_ptr); invokeNode->setArg(4, val_ptr);
cc.cmp(ret_reg, 0);
cc.jne(jh.trap_entry);
cc.mov(val_reg, x86::ptr_64(val_ptr)); cc.mov(val_reg, x86::ptr_64(val_ptr));
cc.and_(val_reg, mask); cc.and_(val_reg, mask);
cc.cmp(ret_reg, 0);
cc.jne(jh.trap_entry);
return val_reg; return val_reg;
} }
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length) { inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length) {
uint32_t length_val = 0; throw std::runtime_error("Invalid gen_read_mem");
auto length_ptr = jh.cc.newIntPtr();
jh.cc.mov(length_ptr, &length_val);
jh.cc.mov(x86::ptr_32(length_ptr), length);
return gen_read_mem(jh, type, addr, length);
} }
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length) { inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length) {
auto addr_reg = jh.cc.newInt64(); throw std::runtime_error("Invalid gen_read_mem");
jh.cc.mov(addr_reg, addr);
uint32_t length_val = 0;
auto length_ptr = jh.cc.newIntPtr();
jh.cc.mov(length_ptr, &length_val);
jh.cc.mov(x86::ptr_32(length_ptr), length);
return gen_read_mem(jh, type, addr_reg, length_val);
} }
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint32_t length) { inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint32_t length) {
auto addr_reg = jh.cc.newInt64(); auto addr_reg = jh.cc.newInt64();
@ -479,32 +480,38 @@ inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint
return gen_read_mem(jh, type, addr_reg, length); return gen_read_mem(jh, type, addr_reg, length);
} }
inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t val) { inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t val, uint32_t length) {
auto val_reg = jh.cc.newInt64(); auto val_reg = get_reg_for(jh, length * 8, true);
jh.cc.mov(val_reg, val); jh.cc.mov(val_reg, val);
gen_write_mem(jh, type, addr, val_reg); gen_write_mem(jh, type, addr, val_reg, length);
} }
inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val) { inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val, uint32_t length) {
x86::Compiler& cc = jh.cc; x86::Compiler& cc = jh.cc;
assert(val.size() == length);
auto mem_type_reg = cc.newInt32(); auto mem_type_reg = cc.newInt32();
jh.cc.mov(mem_type_reg, type); jh.cc.mov(mem_type_reg, type);
auto space_reg = cc.newInt32(); auto space_reg = cc.newInt32();
jh.cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL)); jh.cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL));
auto ret_reg = cc.newInt32(); auto ret_reg = cc.newInt32();
InvokeNode* invokeNode; InvokeNode* invokeNode;
switch(length) {
if(val.isGpb()) { case 1:
cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>()); cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>());
} else if(val.isGpw()) {
cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>());
} else if(val.isGpd()) {
cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>());
} else if(val.isGpq()) {
cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>());
} else
throw std::runtime_error("Invalid register size in gen_write_mem");
break;
case 2:
cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>());
break;
case 4:
cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>());
break;
case 8:
cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>());
break;
default:
throw std::runtime_error("Invalid register size in gen_ext");
}
invokeNode->setRet(0, ret_reg); invokeNode->setRet(0, ret_reg);
invokeNode->setArg(0, jh.arch_if_ptr); invokeNode->setArg(0, jh.arch_if_ptr);
invokeNode->setArg(1, space_reg); invokeNode->setArg(1, space_reg);
@ -515,16 +522,16 @@ inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp
cc.cmp(ret_reg, 0); cc.cmp(ret_reg, 0);
cc.jne(jh.trap_entry); cc.jne(jh.trap_entry);
} }
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val) { inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val, uint32_t length) {
auto addr_reg = jh.cc.newInt64(); auto addr_reg = jh.cc.newUInt64();
jh.cc.mov(addr_reg, addr); jh.cc.mov(addr_reg, addr);
gen_write_mem(jh, type, addr_reg, val); gen_write_mem(jh, type, addr_reg, val, length);
} }
inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val) { inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val, uint32_t length) {
auto val_reg = jh.cc.newInt64(); auto val_reg = get_reg_for(jh, length * 8, true);
jh.cc.mov(val_reg, val); jh.cc.mov(val_reg, val);
auto addr_reg = jh.cc.newInt64(); auto addr_reg = jh.cc.newUInt64();
jh.cc.mov(addr_reg, addr); jh.cc.mov(addr_reg, addr);
gen_write_mem(jh, type, addr_reg, val_reg); gen_write_mem(jh, type, addr_reg, val_reg, length);
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff