Compare commits
	
		
			15 Commits
		
	
	
		
			651897e1e4
			...
			develop
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 937253f7aa | |||
| 98df7d2a74 | |||
| f57f9f9177 | |||
| 6f08f4010c | |||
| c9c47673d9 | |||
| c1aed64a41 | |||
| d5d195845c | |||
| 9fcbeb478b | |||
| a768bde7f2 | |||
| cd866fd74d | |||
| 67f364049c | |||
| 047e2e12b0 | |||
| fe3ed49519 | |||
| 1afd77a942 | |||
| cdf5038e59 | 
@@ -40,7 +40,11 @@
 | 
				
			|||||||
#include <iss/instruction_decoder.h>
 | 
					#include <iss/instruction_decoder.h>
 | 
				
			||||||
<%def fcsr = registers.find {it.name=='FCSR'}
 | 
					<%def fcsr = registers.find {it.name=='FCSR'}
 | 
				
			||||||
if(fcsr != null) {%>
 | 
					if(fcsr != null) {%>
 | 
				
			||||||
#include <vm/fp_functions.h><%}%>
 | 
					#include <vm/fp_functions.h><%}
 | 
				
			||||||
 | 
					def aes = functions.find { it.contains('aes') }
 | 
				
			||||||
 | 
					if(aes != null) {%>
 | 
				
			||||||
 | 
					#include <vm/aes_sbox.h>
 | 
				
			||||||
 | 
					<%}%>
 | 
				
			||||||
#ifndef FMT_HEADER_ONLY
 | 
					#ifndef FMT_HEADER_ONLY
 | 
				
			||||||
#define FMT_HEADER_ONLY
 | 
					#define FMT_HEADER_ONLY
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -49,6 +53,22 @@ if(fcsr != null) {%>
 | 
				
			|||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <iss/debugger/riscv_target_adapter.h>
 | 
					#include <iss/debugger/riscv_target_adapter.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _MSC_VER
 | 
				
			||||||
 | 
					using int128_t = __int128;
 | 
				
			||||||
 | 
					using uint128_t = unsigned __int128;
 | 
				
			||||||
 | 
					namespace std {
 | 
				
			||||||
 | 
					template <> struct make_unsigned<__int128> { typedef unsigned __int128 type; };
 | 
				
			||||||
 | 
					template <> class __make_unsigned_selector<__int128 unsigned, false, false> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    typedef unsigned __int128 __type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template <> struct is_signed<int128_t> { static constexpr bool value = true; };
 | 
				
			||||||
 | 
					template <> struct is_signed<uint128_t> { static constexpr bool value = false; };
 | 
				
			||||||
 | 
					template <> struct is_unsigned<int128_t> { static constexpr bool value = false; };
 | 
				
			||||||
 | 
					template <> struct is_unsigned<uint128_t> { static constexpr bool value = true; };
 | 
				
			||||||
 | 
					} // namespace std
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace iss {
 | 
					namespace iss {
 | 
				
			||||||
namespace asmjit {
 | 
					namespace asmjit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -116,38 +136,14 @@ 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);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    inline void raise(uint16_t trap_id, uint16_t cause){
 | 
				
			||||||
 | 
					        auto trap_val =  0x80ULL << 24 | (cause << 16) | trap_id;
 | 
				
			||||||
 | 
					        this->core.reg.trap_state = trap_val;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<%functions.each{ it.eachLine { %>
 | 
					<%functions.each{ it.eachLine { %>
 | 
				
			||||||
    ${it}<%}
 | 
					    ${it}<%}
 | 
				
			||||||
}
 | 
					}%>
 | 
				
			||||||
if(fcsr != null) {%>
 | 
					 | 
				
			||||||
    x86_reg_t NaNBox16(jit_holder& jh , x86_reg_t NaNBox16_val){
 | 
					 | 
				
			||||||
        x86::Compiler& cc = jh.cc;
 | 
					 | 
				
			||||||
        if(static_cast<uint32_t>(traits::FLEN) == 16)
 | 
					 | 
				
			||||||
            return gen_ext(cc, NaNBox16_val, traits::FLEN, false);
 | 
					 | 
				
			||||||
        else {         
 | 
					 | 
				
			||||||
            auto box = gen_operation(cc, bnot, (gen_ext(cc, 0, traits::FLEN, false)));
 | 
					 | 
				
			||||||
            return gen_ext(cc, (gen_operation(jh.cc, bor, gen_ext(jh.cc, gen_operation(jh.cc, shl, box, 16), traits::FLEN, false), gen_ext(jh.cc, NaNBox16_val, traits::FLEN, false))), traits::FLEN, false);
 | 
					 | 
				
			||||||
        } 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    x86_reg_t NaNBox32(jit_holder& jh , x86_reg_t NaNBox32_val){
 | 
					 | 
				
			||||||
        x86::Compiler& cc = jh.cc;
 | 
					 | 
				
			||||||
        if(static_cast<uint32_t>(traits::FLEN) == 32)
 | 
					 | 
				
			||||||
            return gen_ext(cc, NaNBox32_val, traits::FLEN, false);
 | 
					 | 
				
			||||||
        else {         
 | 
					 | 
				
			||||||
            auto box = gen_operation(cc, bnot, (gen_ext(cc, 0, /* we need to shift for 32 so need larger dt*/ 64, false)));
 | 
					 | 
				
			||||||
            return gen_ext(cc, (gen_operation(jh.cc, bor, gen_ext(jh.cc, gen_operation(jh.cc, shl, box, 32), traits::FLEN, false), gen_ext(jh.cc, NaNBox32_val, traits::FLEN, false))), traits::FLEN, false);
 | 
					 | 
				
			||||||
        } 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    x86_reg_t NaNBox64(jit_holder& jh , x86_reg_t NaNBox64_val){
 | 
					 | 
				
			||||||
        x86::Compiler& cc = jh.cc;
 | 
					 | 
				
			||||||
        if(static_cast<uint32_t>(traits::FLEN) == 64)
 | 
					 | 
				
			||||||
            return gen_ext(cc, NaNBox64_val, traits::FLEN, false);
 | 
					 | 
				
			||||||
        else {         
 | 
					 | 
				
			||||||
            auto box = gen_operation(cc, bnot, (gen_ext(cc, 0, /* we need to shift for 32 so need larger dt*/ 128, false)));
 | 
					 | 
				
			||||||
            return gen_ext(cc, (gen_operation(jh.cc, bor, gen_ext(jh.cc, gen_operation(jh.cc, shl, box, 64), traits::FLEN, false), gen_ext(jh.cc, NaNBox64_val, traits::FLEN, false))), traits::FLEN, false);
 | 
					 | 
				
			||||||
        } 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
<%}%>
 | 
					 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    /****************************************************************************
 | 
					    /****************************************************************************
 | 
				
			||||||
     * start opcode definitions
 | 
					     * start opcode definitions
 | 
				
			||||||
@@ -195,7 +191,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        <%instr.behavior.eachLine{%>${it}
 | 
					        <%instr.behavior.eachLine{%>${it}
 | 
				
			||||||
        <%}%>
 | 
					        <%}%>
 | 
				
			||||||
@@ -226,7 +221,6 @@ private:
 | 
				
			|||||||
        pc = pc + ((instr & 3) == 3 ? 4 : 2);
 | 
					        pc = pc + ((instr & 3) == 3 ? 4 : 2);
 | 
				
			||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        gen_raise(jh, 0, 2);
 | 
					        gen_raise(jh, 0, 2);
 | 
				
			||||||
        gen_sync(jh, POST_SYNC, instr_descr.size());
 | 
					        gen_sync(jh, POST_SYNC, instr_descr.size());
 | 
				
			||||||
        gen_instr_epilogue(jh);
 | 
					        gen_instr_epilogue(jh);
 | 
				
			||||||
@@ -272,24 +266,25 @@ template <typename ARCH>
 | 
				
			|||||||
void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
 | 
					void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
 | 
				
			||||||
    auto& cc = jh.cc;
 | 
					    auto& cc = jh.cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.comment("//gen_instr_prologue");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
					    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
				
			||||||
    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
					    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
				
			||||||
    mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
 | 
					    mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
 | 
				
			||||||
 | 
					    cc.comment("//Instruction prologue end");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
 | 
					void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
 | 
				
			||||||
    auto& cc = jh.cc;
 | 
					    auto& cc = jh.cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.comment("//gen_instr_epilogue");
 | 
					    cc.comment("//Instruction epilogue begin");
 | 
				
			||||||
    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
					    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
				
			||||||
    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
					    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
				
			||||||
    cmp(cc, current_trap_state, 0);
 | 
					    cmp(cc, current_trap_state, 0);
 | 
				
			||||||
    cc.jne(jh.trap_entry);
 | 
					    cc.jne(jh.trap_entry);
 | 
				
			||||||
    cc.inc(get_ptr_for(jh, traits::ICOUNT));
 | 
					    cc.inc(get_ptr_for(jh, traits::ICOUNT));
 | 
				
			||||||
    cc.inc(get_ptr_for(jh, traits::CYCLE));
 | 
					    cc.inc(get_ptr_for(jh, traits::CYCLE));
 | 
				
			||||||
 | 
					    cc.comment("//Instruction epilogue end");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
 | 
					void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
 | 
				
			||||||
@@ -301,7 +296,7 @@ void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
 | 
				
			|||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
					void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
				
			||||||
    x86::Compiler& cc = jh.cc;
 | 
					    x86::Compiler& cc = jh.cc;
 | 
				
			||||||
    cc.comment("//gen_block_epilogue");
 | 
					    cc.comment("//block epilogue begin");
 | 
				
			||||||
    cc.ret(jh.next_pc);
 | 
					    cc.ret(jh.next_pc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.bind(jh.trap_entry);
 | 
					    cc.bind(jh.trap_entry);
 | 
				
			||||||
@@ -313,7 +308,6 @@ void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
				
			|||||||
    x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC);
 | 
					    x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC);
 | 
				
			||||||
    mov(cc, current_pc, get_ptr_for(jh, traits::PC));
 | 
					    mov(cc, current_pc, get_ptr_for(jh, traits::PC));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.comment("//enter trap call;");
 | 
					 | 
				
			||||||
    InvokeNode* call_enter_trap;
 | 
					    InvokeNode* call_enter_trap;
 | 
				
			||||||
    cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
 | 
					    cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<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);
 | 
				
			||||||
@@ -331,7 +325,6 @@ void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
				
			|||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
 | 
					inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
 | 
				
			||||||
    auto& cc = jh.cc;
 | 
					    auto& cc = jh.cc;
 | 
				
			||||||
    cc.comment("//gen_raise");
 | 
					 | 
				
			||||||
    auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
 | 
					    auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
 | 
				
			||||||
    mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
 | 
					    mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
 | 
				
			||||||
    mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
 | 
					    mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -962,6 +962,74 @@ if(vector != null) {%>
 | 
				
			|||||||
                throw new std::runtime_error("Unsupported sew bit value");
 | 
					                throw new std::runtime_error("Unsupported sew bit value");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_unary_op(uint8_t* V, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t sew_val){
 | 
				
			||||||
 | 
					        switch(sew_val){
 | 
				
			||||||
 | 
					            case 0b000:
 | 
				
			||||||
 | 
					                return softvector::vector_unary_op<${vlen}, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
 | 
				
			||||||
 | 
					            case 0b001:
 | 
				
			||||||
 | 
					                return softvector::vector_unary_op<${vlen}, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
 | 
				
			||||||
 | 
					            case 0b010:
 | 
				
			||||||
 | 
					                return softvector::vector_unary_op<${vlen}, uint32_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
 | 
				
			||||||
 | 
					            case 0b011:
 | 
				
			||||||
 | 
					                return softvector::vector_unary_op<${vlen}, uint64_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
 | 
				
			||||||
 | 
					            default: 
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported sew_val");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_vector_crypto(uint8_t* V, uint8_t funct6, uint64_t eg_len, uint64_t eg_start, softvector::vtype_t vtype, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t egs){
 | 
				
			||||||
 | 
					        switch(egs){
 | 
				
			||||||
 | 
					            case 4:
 | 
				
			||||||
 | 
					                return softvector::vector_vector_crypto<${vlen}, 4>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					            case 8:
 | 
				
			||||||
 | 
					                return softvector::vector_vector_crypto<${vlen}, 8>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					            default: 
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported egs");
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_scalar_crypto(uint8_t* V, uint8_t funct6, uint64_t eg_len, uint64_t eg_start, softvector::vtype_t vtype, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t egs){
 | 
				
			||||||
 | 
					        switch(egs){
 | 
				
			||||||
 | 
					            case 4:
 | 
				
			||||||
 | 
					                return softvector::vector_scalar_crypto<${vlen}, 4>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					            case 8:
 | 
				
			||||||
 | 
					                return softvector::vector_scalar_crypto<${vlen}, 8>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					            default: 
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported egs");
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_imm_crypto(uint8_t* V, uint8_t funct6, uint64_t eg_len, uint64_t eg_start, softvector::vtype_t vtype, uint8_t vd, uint8_t vs2, uint8_t imm, uint8_t egs){
 | 
				
			||||||
 | 
					        switch(egs){
 | 
				
			||||||
 | 
					            case 4:
 | 
				
			||||||
 | 
					                return softvector::vector_imm_crypto<${vlen}, 4>(V, funct6, eg_len, eg_start, vtype, vd, vs2, imm);
 | 
				
			||||||
 | 
					            case 8:
 | 
				
			||||||
 | 
					                return softvector::vector_imm_crypto<${vlen}, 8>(V, funct6, eg_len, eg_start, vtype, vd, vs2, imm);
 | 
				
			||||||
 | 
					            default: 
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported egs");
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_crypto(uint8_t* V, uint8_t funct6, uint64_t eg_len, uint64_t eg_start, softvector::vtype_t vtype, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t egs, uint8_t sew){
 | 
				
			||||||
 | 
					        switch(egs){
 | 
				
			||||||
 | 
					            case 4:
 | 
				
			||||||
 | 
					                switch(sew){
 | 
				
			||||||
 | 
					                    case 32:
 | 
				
			||||||
 | 
					                        return softvector::vector_crypto<${vlen}, 4, uint32_t>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					                    case 64:
 | 
				
			||||||
 | 
					                        return softvector::vector_crypto<${vlen}, 4, uint64_t>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					                    default: 
 | 
				
			||||||
 | 
					                        throw new std::runtime_error("Unsupported sew");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            case 8:
 | 
				
			||||||
 | 
					                switch(sew){
 | 
				
			||||||
 | 
					                    case 32:
 | 
				
			||||||
 | 
					                        return softvector::vector_crypto<${vlen}, 8, uint32_t>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					                    case 64:
 | 
				
			||||||
 | 
					                        return softvector::vector_crypto<${vlen}, 8, uint64_t>(V, funct6, eg_len, eg_start, vtype, vd, vs2, vs1);
 | 
				
			||||||
 | 
					                    default: 
 | 
				
			||||||
 | 
					                        throw new std::runtime_error("Unsupported sew");
 | 
				
			||||||
 | 
					                }            
 | 
				
			||||||
 | 
					            default: 
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported egs");
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
<%}%>
 | 
					<%}%>
 | 
				
			||||||
    uint64_t fetch_count{0};
 | 
					    uint64_t fetch_count{0};
 | 
				
			||||||
    uint64_t tval{0};
 | 
					    uint64_t tval{0};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,12 +31,14 @@
 | 
				
			|||||||
 *******************************************************************************/
 | 
					 *******************************************************************************/
 | 
				
			||||||
// clang-format off
 | 
					// clang-format off
 | 
				
			||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
 | 
					#include <iss/arch/${coreDef.name.toLowerCase()}.h>
 | 
				
			||||||
 | 
					// vm_base needs to be included before gdb_session as termios.h (via boost and gdb_server) has a define which clashes with a variable
 | 
				
			||||||
 | 
					// name in ConstantRange.h
 | 
				
			||||||
 | 
					#include <iss/llvm/vm_base.h>
 | 
				
			||||||
 | 
					#include <iss/iss.h>
 | 
				
			||||||
#include <iss/debugger/gdb_session.h>
 | 
					#include <iss/debugger/gdb_session.h>
 | 
				
			||||||
#include <iss/debugger/server.h>
 | 
					#include <iss/debugger/server.h>
 | 
				
			||||||
#include <iss/iss.h>
 | 
					 | 
				
			||||||
#include <iss/llvm/vm_base.h>
 | 
					 | 
				
			||||||
#include <util/logging.h>
 | 
					 | 
				
			||||||
#include <iss/instruction_decoder.h>
 | 
					#include <iss/instruction_decoder.h>
 | 
				
			||||||
 | 
					#include <util/logging.h>
 | 
				
			||||||
<%def fcsr = registers.find {it.name=='FCSR'}
 | 
					<%def fcsr = registers.find {it.name=='FCSR'}
 | 
				
			||||||
if(fcsr != null) {%>
 | 
					if(fcsr != null) {%>
 | 
				
			||||||
#include <vm/fp_functions.h><%}%>
 | 
					#include <vm/fp_functions.h><%}%>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -230,11 +230,6 @@ public:
 | 
				
			|||||||
    trap_load_access_fault(uint64_t badaddr)
 | 
					    trap_load_access_fault(uint64_t badaddr)
 | 
				
			||||||
    : trap_access(5 << 16, badaddr) {}
 | 
					    : trap_access(5 << 16, badaddr) {}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
class illegal_instruction_fault : public trap_access {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    illegal_instruction_fault(uint64_t badaddr)
 | 
					 | 
				
			||||||
    : trap_access(2 << 16, badaddr) {}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
class trap_instruction_page_fault : public trap_access {
 | 
					class trap_instruction_page_fault : public trap_access {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    trap_instruction_page_fault(uint64_t badaddr)
 | 
					    trap_instruction_page_fault(uint64_t badaddr)
 | 
				
			||||||
@@ -523,10 +518,10 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
 | 
				
			|||||||
            return iss::Err;
 | 
					            return iss::Err;
 | 
				
			||||||
        auto req_priv_lvl = (addr >> 8) & 0x3;
 | 
					        auto req_priv_lvl = (addr >> 8) & 0x3;
 | 
				
			||||||
        if(this->reg.PRIV < req_priv_lvl) // not having required privileges
 | 
					        if(this->reg.PRIV < req_priv_lvl) // not having required privileges
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        auto it = csr_rd_cb.find(addr);
 | 
					        auto it = csr_rd_cb.find(addr);
 | 
				
			||||||
        if(it == csr_rd_cb.end() || !it->second) // non existent register
 | 
					        if(it == csr_rd_cb.end() || !it->second) // non existent register
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        return it->second(addr, val);
 | 
					        return it->second(addr, val);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -535,12 +530,12 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
 | 
				
			|||||||
            return iss::Err;
 | 
					            return iss::Err;
 | 
				
			||||||
        auto req_priv_lvl = (addr >> 8) & 0x3;
 | 
					        auto req_priv_lvl = (addr >> 8) & 0x3;
 | 
				
			||||||
        if(this->reg.PRIV < req_priv_lvl) // not having required privileges
 | 
					        if(this->reg.PRIV < req_priv_lvl) // not having required privileges
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        if((addr & 0xc00) == 0xc00) // writing to read-only region
 | 
					        if((addr & 0xc00) == 0xc00) // writing to read-only region
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        auto it = csr_wr_cb.find(addr);
 | 
					        auto it = csr_wr_cb.find(addr);
 | 
				
			||||||
        if(it == csr_wr_cb.end() || !it->second) // non existent register
 | 
					        if(it == csr_wr_cb.end() || !it->second) // non existent register
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        return it->second(addr, val);
 | 
					        return it->second(addr, val);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -637,7 +632,7 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    iss::status write_dcsr(unsigned addr, reg_t val) {
 | 
					    iss::status write_dcsr(unsigned addr, reg_t val) {
 | 
				
			||||||
        if(!debug_mode_active())
 | 
					        if(!debug_mode_active())
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        //                  +-------------- ebreakm
 | 
					        //                  +-------------- ebreakm
 | 
				
			||||||
        //                  |   +---------- stepi
 | 
					        //                  |   +---------- stepi
 | 
				
			||||||
        //                  |   |  +++----- cause
 | 
					        //                  |   |  +++----- cause
 | 
				
			||||||
@@ -648,28 +643,28 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    iss::status read_debug(unsigned addr, reg_t& val) {
 | 
					    iss::status read_debug(unsigned addr, reg_t& val) {
 | 
				
			||||||
        if(!debug_mode_active())
 | 
					        if(!debug_mode_active())
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        val = csr[addr];
 | 
					        val = csr[addr];
 | 
				
			||||||
        return iss::Ok;
 | 
					        return iss::Ok;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iss::status write_dscratch(unsigned addr, reg_t val) {
 | 
					    iss::status write_dscratch(unsigned addr, reg_t val) {
 | 
				
			||||||
        if(!debug_mode_active())
 | 
					        if(!debug_mode_active())
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        csr[addr] = val;
 | 
					        csr[addr] = val;
 | 
				
			||||||
        return iss::Ok;
 | 
					        return iss::Ok;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iss::status read_dpc(unsigned addr, reg_t& val) {
 | 
					    iss::status read_dpc(unsigned addr, reg_t& val) {
 | 
				
			||||||
        if(!debug_mode_active())
 | 
					        if(!debug_mode_active())
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        val = this->reg.DPC;
 | 
					        val = this->reg.DPC;
 | 
				
			||||||
        return iss::Ok;
 | 
					        return iss::Ok;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iss::status write_dpc(unsigned addr, reg_t val) {
 | 
					    iss::status write_dpc(unsigned addr, reg_t val) {
 | 
				
			||||||
        if(!debug_mode_active())
 | 
					        if(!debug_mode_active())
 | 
				
			||||||
            throw illegal_instruction_fault(this->fault_data);
 | 
					            return iss::Err;
 | 
				
			||||||
        this->reg.DPC = val;
 | 
					        this->reg.DPC = val;
 | 
				
			||||||
        return iss::Ok;
 | 
					        return iss::Ok;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -889,8 +884,7 @@ protected:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    instrumentation_if* get_instrumentation_if() override { return &instr_if; };
 | 
					    instrumentation_if* get_instrumentation_if() override { return &instr_if; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
 | 
					    using csr_type = std::array<typename traits<BASE>::reg_t, 1ULL << 12>;
 | 
				
			||||||
    using csr_page_type = typename csr_type::page_type;
 | 
					 | 
				
			||||||
    csr_type csr;
 | 
					    csr_type csr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
 | 
					    std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,6 @@
 | 
				
			|||||||
#include <iss/iss.h>
 | 
					#include <iss/iss.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <memory>
 | 
					 | 
				
			||||||
#ifndef FMT_HEADER_ONLY
 | 
					#ifndef FMT_HEADER_ONLY
 | 
				
			||||||
#define FMT_HEADER_ONLY
 | 
					#define FMT_HEADER_ONLY
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -250,7 +250,7 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc
 | 
				
			|||||||
        T cmd_addr = sh_read_field<T>(arch_if_ptr, *parameter);
 | 
					        T cmd_addr = sh_read_field<T>(arch_if_ptr, *parameter);
 | 
				
			||||||
        T cmd_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 1);
 | 
					        T cmd_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 1);
 | 
				
			||||||
        std::string cmd = sh_read_string<T>(arch_if_ptr, cmd_addr, cmd_len);
 | 
					        std::string cmd = sh_read_string<T>(arch_if_ptr, cmd_addr, cmd_len);
 | 
				
			||||||
        system(cmd.c_str());
 | 
					        auto val = system(cmd.c_str());
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case semihosting_syscalls::SYS_TICKFREQ: {
 | 
					    case semihosting_syscalls::SYS_TICKFREQ: {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,14 +99,18 @@ int main(int argc, char* argv[]) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    LOGGER(DEFAULT)::print_time() = false;
 | 
					    LOGGER(DEFAULT)::print_time() = false;
 | 
				
			||||||
    LOGGER(connection)::print_time() = false;
 | 
					    LOGGER(connection)::print_time() = false;
 | 
				
			||||||
 | 
					    LOGGER(dbt_rise_iss)::print_time() = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto l = logging::as_log_level(clim["verbose"].as<int>());
 | 
					    auto l = logging::as_log_level(clim["verbose"].as<int>());
 | 
				
			||||||
    LOGGER(DEFAULT)::reporting_level() = l;
 | 
					    LOGGER(DEFAULT)::reporting_level() = l;
 | 
				
			||||||
    LOGGER(connection)::reporting_level() = l;
 | 
					    LOGGER(connection)::reporting_level() = l;
 | 
				
			||||||
 | 
					    LOGGER(dbt_rise_iss)::reporting_level() = l;
 | 
				
			||||||
    if(clim.count("logfile")) {
 | 
					    if(clim.count("logfile")) {
 | 
				
			||||||
        // configure the connection logger
 | 
					        // configure the connection logger
 | 
				
			||||||
        auto f = fopen(clim["logfile"].as<std::string>().c_str(), "w");
 | 
					        auto f = fopen(clim["logfile"].as<std::string>().c_str(), "w");
 | 
				
			||||||
        LOG_OUTPUT(DEFAULT)::stream() = f;
 | 
					        LOG_OUTPUT(DEFAULT)::stream() = f;
 | 
				
			||||||
        LOG_OUTPUT(connection)::stream() = f;
 | 
					        LOG_OUTPUT(connection)::stream() = f;
 | 
				
			||||||
 | 
					        LOG_OUTPUT(dbt_rise_iss)::stream() = f;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<iss::vm_plugin*> plugin_list;
 | 
					    std::vector<iss::vm_plugin*> plugin_list;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,11 +45,10 @@
 | 
				
			|||||||
#include <scc/report.h>
 | 
					#include <scc/report.h>
 | 
				
			||||||
#include <util/ities.h>
 | 
					#include <util/ities.h>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <sstream>
 | 
					 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <numeric>
 | 
					 | 
				
			||||||
#include <iss/plugin/cycle_estimate.h>
 | 
					#include <iss/plugin/cycle_estimate.h>
 | 
				
			||||||
#include <iss/plugin/instruction_count.h>
 | 
					#include <iss/plugin/instruction_count.h>
 | 
				
			||||||
 | 
					#include <util/ities.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// clang-format on
 | 
					// clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -267,7 +266,10 @@ template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::before_end_of_elab
 | 
				
			|||||||
    cpu = new core_wrapper(this);
 | 
					    cpu = new core_wrapper(this);
 | 
				
			||||||
    cpu->create_cpu(GET_PROP_VALUE(core_type), GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid));
 | 
					    cpu->create_cpu(GET_PROP_VALUE(core_type), GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid));
 | 
				
			||||||
    sc_assert(cpu->vm != nullptr);
 | 
					    sc_assert(cpu->vm != nullptr);
 | 
				
			||||||
    cpu->vm->setDisassEnabled(GET_PROP_VALUE(enable_disass) || trc->m_db != nullptr);
 | 
					    auto disass = GET_PROP_VALUE(enable_disass);
 | 
				
			||||||
 | 
					    if(disass && trc->m_db)
 | 
				
			||||||
 | 
					        SCCINFO(SCMOD) << "Disasssembly will only be in transaction trace database!";
 | 
				
			||||||
 | 
					    cpu->vm->setDisassEnabled(disass || trc->m_db != nullptr);
 | 
				
			||||||
    if(GET_PROP_VALUE(plugins).length()) {
 | 
					    if(GET_PROP_VALUE(plugins).length()) {
 | 
				
			||||||
        auto p = util::split(GET_PROP_VALUE(plugins), ';');
 | 
					        auto p = util::split(GET_PROP_VALUE(plugins), ';');
 | 
				
			||||||
        for(std::string const& opt_val : p) {
 | 
					        for(std::string const& opt_val : p) {
 | 
				
			||||||
@@ -305,19 +307,22 @@ template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::before_end_of_elab
 | 
				
			|||||||
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::start_of_simulation() {
 | 
					template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::start_of_simulation() {
 | 
				
			||||||
    // quantum_keeper.reset();
 | 
					    // quantum_keeper.reset();
 | 
				
			||||||
    if(GET_PROP_VALUE(elf_file).size() > 0) {
 | 
					    if(GET_PROP_VALUE(elf_file).size() > 0) {
 | 
				
			||||||
        istringstream is(GET_PROP_VALUE(elf_file));
 | 
					        auto file_names = util::split(GET_PROP_VALUE(elf_file), ',');
 | 
				
			||||||
        string s;
 | 
					        for(auto& s : file_names) {
 | 
				
			||||||
        while(getline(is, s, ',')) {
 | 
					            std::pair<uint64_t, bool> load_result = cpu->load_file(s);
 | 
				
			||||||
            std::pair<uint64_t, bool> start_addr = cpu->load_file(s);
 | 
					            if(!std::get<1>(load_result)) {
 | 
				
			||||||
 | 
					                SCCWARN(SCMOD) << "Could not load FW file " << s;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
#ifndef CWR_SYSTEMC
 | 
					#ifndef CWR_SYSTEMC
 | 
				
			||||||
            if(reset_address.is_default_value() && start_addr.second == true)
 | 
					                if(reset_address.is_default_value())
 | 
				
			||||||
                reset_address.set_value(start_addr.first);
 | 
					                    reset_address.set_value(load_result.first);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
                if(start_addr.second == true)
 | 
					                if(start_addr.second == true)
 | 
				
			||||||
                    reset_address = start_addr.first;
 | 
					                    reset_address = start_addr.first;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if(trc->m_db != nullptr && trc->stream_handle == nullptr) {
 | 
					    if(trc->m_db != nullptr && trc->stream_handle == nullptr) {
 | 
				
			||||||
        string basename(this->name());
 | 
					        string basename(this->name());
 | 
				
			||||||
        trc->stream_handle = new scv_tr_stream((basename + ".instr").c_str(), "TRANSACTOR", trc->m_db);
 | 
					        trc->stream_handle = new scv_tr_stream((basename + ".instr").c_str(), "TRANSACTOR", trc->m_db);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@
 | 
				
			|||||||
#ifndef _VM_AES_SBOX_H_
 | 
					#ifndef _VM_AES_SBOX_H_
 | 
				
			||||||
#define _VM_AES_SBOX_H_
 | 
					#define _VM_AES_SBOX_H_
 | 
				
			||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
const uint8_t AES_ENC_SBOX[] = {
 | 
					const uint8_t AES_ENC_SBOX[] = {
 | 
				
			||||||
    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59,
 | 
					    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59,
 | 
				
			||||||
    0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1,
 | 
					    0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1,
 | 
				
			||||||
@@ -65,5 +65,6 @@ const uint8_t AES_DEC_SBOX[] = {
 | 
				
			|||||||
    0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B,
 | 
					    0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B,
 | 
				
			||||||
    0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D};
 | 
					    0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D};
 | 
				
			||||||
uint8_t inline aes_sbox_inv(uint8_t index) { return AES_DEC_SBOX[index]; }
 | 
					uint8_t inline aes_sbox_inv(uint8_t index) { return AES_DEC_SBOX[index]; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _VM_AES_SBOX_H_ */
 | 
					#endif /* _VM_AES_SBOX_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,22 @@
 | 
				
			|||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <iss/debugger/riscv_target_adapter.h>
 | 
					#include <iss/debugger/riscv_target_adapter.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _MSC_VER
 | 
				
			||||||
 | 
					using int128_t = __int128;
 | 
				
			||||||
 | 
					using uint128_t = unsigned __int128;
 | 
				
			||||||
 | 
					namespace std {
 | 
				
			||||||
 | 
					template <> struct make_unsigned<__int128> { typedef unsigned __int128 type; };
 | 
				
			||||||
 | 
					template <> class __make_unsigned_selector<__int128 unsigned, false, false> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    typedef unsigned __int128 __type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template <> struct is_signed<int128_t> { static constexpr bool value = true; };
 | 
				
			||||||
 | 
					template <> struct is_signed<uint128_t> { static constexpr bool value = false; };
 | 
				
			||||||
 | 
					template <> struct is_unsigned<int128_t> { static constexpr bool value = false; };
 | 
				
			||||||
 | 
					template <> struct is_unsigned<uint128_t> { static constexpr bool value = true; };
 | 
				
			||||||
 | 
					} // namespace std
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace iss {
 | 
					namespace iss {
 | 
				
			||||||
namespace asmjit {
 | 
					namespace asmjit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -112,6 +128,11 @@ 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);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    inline void raise(uint16_t trap_id, uint16_t cause){
 | 
				
			||||||
 | 
					        auto trap_val =  0x80ULL << 24 | (cause << 16) | trap_id;
 | 
				
			||||||
 | 
					        this->core.reg.trap_state = trap_val;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    /****************************************************************************
 | 
					    /****************************************************************************
 | 
				
			||||||
@@ -335,7 +356,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -382,7 +402,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -429,7 +448,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -488,7 +506,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -561,7 +578,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -625,7 +641,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -689,7 +704,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -755,7 +769,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -821,7 +834,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -885,7 +897,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -949,7 +960,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1003,7 +1013,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1057,7 +1066,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1111,7 +1119,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1164,7 +1171,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1217,7 +1223,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1266,7 +1271,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1315,7 +1319,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1364,7 +1367,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1414,7 +1416,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1475,7 +1476,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1535,7 +1535,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1584,7 +1583,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1633,7 +1631,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1682,7 +1679,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1731,7 +1727,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1780,7 +1775,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1831,7 +1825,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1881,7 +1874,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1931,7 +1923,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -1981,7 +1972,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2043,7 +2033,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2103,7 +2092,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2152,7 +2140,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2202,7 +2189,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2254,7 +2240,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2303,7 +2288,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2354,7 +2338,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        gen_write_mem(jh, traits::FENCE, static_cast<uint32_t>(traits::fence), (uint8_t)pred<<4|succ, 4);
 | 
					        gen_write_mem(jh, traits::FENCE, static_cast<uint32_t>(traits::fence), (uint8_t)pred<<4|succ, 4);
 | 
				
			||||||
        auto returnValue = CONT;
 | 
					        auto returnValue = CONT;
 | 
				
			||||||
@@ -2390,7 +2373,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        gen_raise(jh, 0, 11);
 | 
					        gen_raise(jh, 0, 11);
 | 
				
			||||||
@@ -2427,7 +2409,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        gen_raise(jh, 0, 3);
 | 
					        gen_raise(jh, 0, 3);
 | 
				
			||||||
@@ -2464,7 +2445,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        gen_leave(jh, 3);
 | 
					        gen_leave(jh, 3);
 | 
				
			||||||
@@ -2501,10 +2481,8 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        InvokeNode* call_wait_5;
 | 
					        InvokeNode* call_wait_5;
 | 
				
			||||||
        jh.cc.comment("//call_wait");
 | 
					 | 
				
			||||||
        jh.cc.invoke(&call_wait_5,  &wait, FuncSignature::build<void, uint32_t>());
 | 
					        jh.cc.invoke(&call_wait_5,  &wait, FuncSignature::build<void, uint32_t>());
 | 
				
			||||||
        setArg(call_wait_5, 0, 1);
 | 
					        setArg(call_wait_5, 0, 1);
 | 
				
			||||||
        auto returnValue = CONT;
 | 
					        auto returnValue = CONT;
 | 
				
			||||||
@@ -2544,7 +2522,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2598,7 +2575,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2652,7 +2628,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2706,7 +2681,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2756,7 +2730,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2809,7 +2782,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2862,7 +2834,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        gen_write_mem(jh, traits::FENCE, static_cast<uint32_t>(traits::fencei), imm, 4);
 | 
					        gen_write_mem(jh, traits::FENCE, static_cast<uint32_t>(traits::fencei), imm, 4);
 | 
				
			||||||
        auto returnValue = FLUSH;
 | 
					        auto returnValue = FLUSH;
 | 
				
			||||||
@@ -2902,7 +2873,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -2955,7 +2925,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3009,7 +2978,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3062,7 +3030,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3114,7 +3081,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3203,7 +3169,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3270,7 +3235,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3363,7 +3327,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rs1>=static_cast<uint32_t>(traits::RFS)||rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3429,7 +3392,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(imm){
 | 
					        if(imm){
 | 
				
			||||||
            mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
					            mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
				
			||||||
@@ -3477,7 +3439,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        auto offs = gen_ext(cc, 
 | 
					        auto offs = gen_ext(cc, 
 | 
				
			||||||
            (gen_operation(cc, add, load_reg_from_mem(jh, traits::X0 + rs1+8), uimm)
 | 
					            (gen_operation(cc, add, load_reg_from_mem(jh, traits::X0 + rs1+8), uimm)
 | 
				
			||||||
@@ -3523,7 +3484,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        auto offs = gen_ext(cc, 
 | 
					        auto offs = gen_ext(cc, 
 | 
				
			||||||
            (gen_operation(cc, add, load_reg_from_mem(jh, traits::X0 + rs1+8), uimm)
 | 
					            (gen_operation(cc, add, load_reg_from_mem(jh, traits::X0 + rs1+8), uimm)
 | 
				
			||||||
@@ -3566,7 +3526,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3613,7 +3572,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        auto returnValue = CONT;
 | 
					        auto returnValue = CONT;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@@ -3650,7 +3608,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        mov(cc, get_ptr_for(jh, traits::X0+ 1),
 | 
					        mov(cc, get_ptr_for(jh, traits::X0+ 1),
 | 
				
			||||||
@@ -3694,7 +3651,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3741,7 +3697,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(imm==0||rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(imm==0||rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -3785,7 +3740,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(nzimm){
 | 
					        if(nzimm){
 | 
				
			||||||
            mov(cc, get_ptr_for(jh, traits::X0+ 2),
 | 
					            mov(cc, get_ptr_for(jh, traits::X0+ 2),
 | 
				
			||||||
@@ -3830,7 +3784,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					        gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
        auto returnValue = CONT;
 | 
					        auto returnValue = CONT;
 | 
				
			||||||
@@ -3869,7 +3822,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(cc, get_ptr_for(jh, traits::X0+ rs1+8),
 | 
					        mov(cc, get_ptr_for(jh, traits::X0+ rs1+8),
 | 
				
			||||||
              gen_operation(cc, shr, load_reg_from_mem(jh, traits::X0 + rs1+8), shamt)
 | 
					              gen_operation(cc, shr, load_reg_from_mem(jh, traits::X0 + rs1+8), shamt)
 | 
				
			||||||
@@ -3910,7 +3862,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(shamt){
 | 
					        if(shamt){
 | 
				
			||||||
            mov(cc, get_ptr_for(jh, traits::X0+ rs1+8),
 | 
					            mov(cc, get_ptr_for(jh, traits::X0+ rs1+8),
 | 
				
			||||||
@@ -3964,7 +3915,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(cc, get_ptr_for(jh, traits::X0+ rs1+8),
 | 
					        mov(cc, get_ptr_for(jh, traits::X0+ rs1+8),
 | 
				
			||||||
              gen_ext(cc, 
 | 
					              gen_ext(cc, 
 | 
				
			||||||
@@ -4006,7 +3956,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
					        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
				
			||||||
              gen_ext(cc, 
 | 
					              gen_ext(cc, 
 | 
				
			||||||
@@ -4048,7 +3997,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
					        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
				
			||||||
              gen_operation(cc, bxor, load_reg_from_mem(jh, traits::X0 + rd+8), load_reg_from_mem(jh, traits::X0 + rs2+8))
 | 
					              gen_operation(cc, bxor, load_reg_from_mem(jh, traits::X0 + rd+8), load_reg_from_mem(jh, traits::X0 + rs2+8))
 | 
				
			||||||
@@ -4089,7 +4037,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
					        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
				
			||||||
              gen_operation(cc, bor, load_reg_from_mem(jh, traits::X0 + rd+8), load_reg_from_mem(jh, traits::X0 + rs2+8))
 | 
					              gen_operation(cc, bor, load_reg_from_mem(jh, traits::X0 + rd+8), load_reg_from_mem(jh, traits::X0 + rs2+8))
 | 
				
			||||||
@@ -4130,7 +4077,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
					        mov(cc, get_ptr_for(jh, traits::X0+ rd+8),
 | 
				
			||||||
              gen_operation(cc, band, load_reg_from_mem(jh, traits::X0 + rd+8), load_reg_from_mem(jh, traits::X0 + rs2+8))
 | 
					              gen_operation(cc, band, load_reg_from_mem(jh, traits::X0 + rd+8), load_reg_from_mem(jh, traits::X0 + rs2+8))
 | 
				
			||||||
@@ -4170,7 +4116,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm));
 | 
					        auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm));
 | 
				
			||||||
@@ -4212,7 +4157,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -4263,7 +4207,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -4314,7 +4257,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -4362,7 +4304,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)||rd==0){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)||rd==0){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -4412,7 +4353,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -4458,7 +4398,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs1&&rs1<static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs1&&rs1<static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -4504,7 +4443,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        gen_raise(jh, 0, 2);
 | 
					        gen_raise(jh, 0, 2);
 | 
				
			||||||
        auto returnValue = CONT;
 | 
					        auto returnValue = CONT;
 | 
				
			||||||
@@ -4543,7 +4481,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rd>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -4591,7 +4528,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
					        mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
 | 
				
			||||||
        if(rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs1>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
@@ -4640,7 +4576,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        gen_raise(jh, 0, 3);
 | 
					        gen_raise(jh, 0, 3);
 | 
				
			||||||
        auto returnValue = CONT;
 | 
					        auto returnValue = CONT;
 | 
				
			||||||
@@ -4679,7 +4614,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        if(rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
					        if(rs2>=static_cast<uint32_t>(traits::RFS)){
 | 
				
			||||||
            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					            gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
@@ -4724,7 +4658,6 @@ private:
 | 
				
			|||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        /*generate behavior*/
 | 
					        /*generate behavior*/
 | 
				
			||||||
        gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
					        gen_raise(jh, 0, static_cast<uint32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
 | 
				
			||||||
        auto returnValue = CONT;
 | 
					        auto returnValue = CONT;
 | 
				
			||||||
@@ -4756,7 +4689,6 @@ private:
 | 
				
			|||||||
        pc = pc + ((instr & 3) == 3 ? 4 : 2);
 | 
					        pc = pc + ((instr & 3) == 3 ? 4 : 2);
 | 
				
			||||||
        mov(cc, jh.next_pc, pc.val);
 | 
					        mov(cc, jh.next_pc, pc.val);
 | 
				
			||||||
        gen_instr_prologue(jh);
 | 
					        gen_instr_prologue(jh);
 | 
				
			||||||
        cc.comment("//behavior:");
 | 
					 | 
				
			||||||
        gen_raise(jh, 0, 2);
 | 
					        gen_raise(jh, 0, 2);
 | 
				
			||||||
        gen_sync(jh, POST_SYNC, instr_descr.size());
 | 
					        gen_sync(jh, POST_SYNC, instr_descr.size());
 | 
				
			||||||
        gen_instr_epilogue(jh);
 | 
					        gen_instr_epilogue(jh);
 | 
				
			||||||
@@ -4802,24 +4734,25 @@ template <typename ARCH>
 | 
				
			|||||||
void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
 | 
					void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
 | 
				
			||||||
    auto& cc = jh.cc;
 | 
					    auto& cc = jh.cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.comment("//gen_instr_prologue");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
					    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
				
			||||||
    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
					    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
				
			||||||
    mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
 | 
					    mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
 | 
				
			||||||
 | 
					    cc.comment("//Instruction prologue end");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
 | 
					void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
 | 
				
			||||||
    auto& cc = jh.cc;
 | 
					    auto& cc = jh.cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.comment("//gen_instr_epilogue");
 | 
					    cc.comment("//Instruction epilogue begin");
 | 
				
			||||||
    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
					    x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
 | 
				
			||||||
    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
					    mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
 | 
				
			||||||
    cmp(cc, current_trap_state, 0);
 | 
					    cmp(cc, current_trap_state, 0);
 | 
				
			||||||
    cc.jne(jh.trap_entry);
 | 
					    cc.jne(jh.trap_entry);
 | 
				
			||||||
    cc.inc(get_ptr_for(jh, traits::ICOUNT));
 | 
					    cc.inc(get_ptr_for(jh, traits::ICOUNT));
 | 
				
			||||||
    cc.inc(get_ptr_for(jh, traits::CYCLE));
 | 
					    cc.inc(get_ptr_for(jh, traits::CYCLE));
 | 
				
			||||||
 | 
					    cc.comment("//Instruction epilogue end");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
 | 
					void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
 | 
				
			||||||
@@ -4831,7 +4764,7 @@ void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
 | 
				
			|||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
					void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
				
			||||||
    x86::Compiler& cc = jh.cc;
 | 
					    x86::Compiler& cc = jh.cc;
 | 
				
			||||||
    cc.comment("//gen_block_epilogue");
 | 
					    cc.comment("//block epilogue begin");
 | 
				
			||||||
    cc.ret(jh.next_pc);
 | 
					    cc.ret(jh.next_pc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.bind(jh.trap_entry);
 | 
					    cc.bind(jh.trap_entry);
 | 
				
			||||||
@@ -4843,7 +4776,6 @@ void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
				
			|||||||
    x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC);
 | 
					    x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC);
 | 
				
			||||||
    mov(cc, current_pc, get_ptr_for(jh, traits::PC));
 | 
					    mov(cc, current_pc, get_ptr_for(jh, traits::PC));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cc.comment("//enter trap call;");
 | 
					 | 
				
			||||||
    InvokeNode* call_enter_trap;
 | 
					    InvokeNode* call_enter_trap;
 | 
				
			||||||
    cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
 | 
					    cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<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);
 | 
				
			||||||
@@ -4861,7 +4793,6 @@ void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
 | 
				
			|||||||
template <typename ARCH>
 | 
					template <typename ARCH>
 | 
				
			||||||
inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
 | 
					inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
 | 
				
			||||||
    auto& cc = jh.cc;
 | 
					    auto& cc = jh.cc;
 | 
				
			||||||
    cc.comment("//gen_raise");
 | 
					 | 
				
			||||||
    auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
 | 
					    auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
 | 
				
			||||||
    mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
 | 
					    mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
 | 
				
			||||||
    mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
 | 
					    mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,6 +102,7 @@ void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
 | 
				
			|||||||
        FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
 | 
					        FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
 | 
				
			||||||
        FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
 | 
					        FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
 | 
				
			||||||
        FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32));
 | 
					        FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32));
 | 
				
			||||||
 | 
					        FDECL(unbox_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(64)); // technically the first arg is only 8 bits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FDECL(f32toi32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
 | 
					        FDECL(f32toi32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
 | 
				
			||||||
        FDECL(f32toui32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
 | 
					        FDECL(f32toui32, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
 | 
				
			||||||
@@ -112,7 +113,6 @@ void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
 | 
				
			|||||||
        FDECL(i64tof32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
					        FDECL(i64tof32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
				
			||||||
        FDECL(ui64tof32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
					        FDECL(ui64tof32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
				
			||||||
        if(flen > 32) {
 | 
					        if(flen > 32) {
 | 
				
			||||||
            FDECL(unbox_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(64)); // technically the first arg is only 8 bits
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
 | 
					            FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
 | 
				
			||||||
            FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
 | 
					            FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
 | 
				
			||||||
@@ -134,6 +134,8 @@ void add_fp_functions_2_module(Module* mod, uint32_t flen, uint32_t xlen) {
 | 
				
			|||||||
            FDECL(ui32tof64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
 | 
					            FDECL(ui32tof64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
 | 
				
			||||||
            FDECL(f64toi32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
					            FDECL(f64toi32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
				
			||||||
            FDECL(f64toui32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
					            FDECL(f64toui32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            FDECL(unbox_d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(64)); // technically the first arg is only 8 bits
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,10 +31,12 @@
 | 
				
			|||||||
 *******************************************************************************/
 | 
					 *******************************************************************************/
 | 
				
			||||||
// clang-format off
 | 
					// clang-format off
 | 
				
			||||||
#include <iss/arch/tgc5c.h>
 | 
					#include <iss/arch/tgc5c.h>
 | 
				
			||||||
 | 
					// vm_base needs to be included before gdb_session as termios.h (via boost and gdb_server) has a define which clashes with a variable
 | 
				
			||||||
 | 
					// name in ConstantRange.h
 | 
				
			||||||
 | 
					#include <iss/llvm/vm_base.h>
 | 
				
			||||||
#include <iss/debugger/gdb_session.h>
 | 
					#include <iss/debugger/gdb_session.h>
 | 
				
			||||||
#include <iss/debugger/server.h>
 | 
					#include <iss/debugger/server.h>
 | 
				
			||||||
#include <iss/iss.h>
 | 
					#include <iss/iss.h>
 | 
				
			||||||
#include <iss/llvm/vm_base.h>
 | 
					 | 
				
			||||||
#include <util/logging.h>
 | 
					#include <util/logging.h>
 | 
				
			||||||
#include <iss/instruction_decoder.h>
 | 
					#include <iss/instruction_decoder.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "vector_functions.h"
 | 
					#include "vector_functions.h"
 | 
				
			||||||
#include "iss/vm_types.h"
 | 
					#include "iss/vm_types.h"
 | 
				
			||||||
 | 
					#include "vm/aes_sbox.h"
 | 
				
			||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
#include <cstddef>
 | 
					#include <cstddef>
 | 
				
			||||||
@@ -98,4 +99,309 @@ vmask_view read_vmask(uint8_t* V, uint16_t VLEN, uint16_t elem_count, uint8_t re
 | 
				
			|||||||
    assert(mask_start + elem_count / 8 <= V + VLEN * RFS / 8);
 | 
					    assert(mask_start + elem_count / 8 <= V + VLEN * RFS / 8);
 | 
				
			||||||
    return {mask_start, elem_count};
 | 
					    return {mask_start, elem_count};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					uint8_t xt2(uint8_t x) { return (x << 1) ^ (bit_sub<7, 1>(x) ? 27 : 0); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t xt3(uint8_t x) { return x ^ xt2(x); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t gfmul(uint8_t x, uint8_t y) {
 | 
				
			||||||
 | 
					    return (bit_sub<0, 1>(y) ? x : 0) ^ (bit_sub<1, 1>(y) ? xt2(x) : 0) ^ (bit_sub<2, 1>(y) ? xt2(xt2(x)) : 0) ^
 | 
				
			||||||
 | 
					           (bit_sub<3, 1>(y) ? xt2(xt2(xt2(x))) : 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_mixcolumn_byte_fwd(uint8_t so) {
 | 
				
			||||||
 | 
					    return ((uint32_t)gfmul(so, 3) << 24) | ((uint32_t)so << 16) | ((uint32_t)so << 8) | gfmul(so, 2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_mixcolumn_byte_inv(uint8_t so) {
 | 
				
			||||||
 | 
					    return ((uint32_t)gfmul(so, 11) << 24) | ((uint32_t)gfmul(so, 13) << 16) | ((uint32_t)gfmul(so, 9) << 8) | gfmul(so, 14);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_mixcolumn_fwd(uint32_t x) {
 | 
				
			||||||
 | 
					    uint8_t s0 = bit_sub<0, 7 - 0 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t s1 = bit_sub<8, 15 - 8 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t s2 = bit_sub<16, 23 - 16 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t s3 = bit_sub<24, 31 - 24 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t b0 = xt2(s0) ^ xt3(s1) ^ (s2) ^ (s3);
 | 
				
			||||||
 | 
					    uint8_t b1 = (s0) ^ xt2(s1) ^ xt3(s2) ^ (s3);
 | 
				
			||||||
 | 
					    uint8_t b2 = (s0) ^ (s1) ^ xt2(s2) ^ xt3(s3);
 | 
				
			||||||
 | 
					    uint8_t b3 = xt3(s0) ^ (s1) ^ (s2) ^ xt2(s3);
 | 
				
			||||||
 | 
					    return ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_mixcolumn_inv(uint32_t x) {
 | 
				
			||||||
 | 
					    uint8_t s0 = bit_sub<0, 7 - 0 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t s1 = bit_sub<8, 15 - 8 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t s2 = bit_sub<16, 23 - 16 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t s3 = bit_sub<24, 31 - 24 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t b0 = gfmul(s0, 14) ^ gfmul(s1, 11) ^ gfmul(s2, 13) ^ gfmul(s3, 9);
 | 
				
			||||||
 | 
					    uint8_t b1 = gfmul(s0, 9) ^ gfmul(s1, 14) ^ gfmul(s2, 11) ^ gfmul(s3, 13);
 | 
				
			||||||
 | 
					    uint8_t b2 = gfmul(s0, 13) ^ gfmul(s1, 9) ^ gfmul(s2, 14) ^ gfmul(s3, 11);
 | 
				
			||||||
 | 
					    uint8_t b3 = gfmul(s0, 11) ^ gfmul(s1, 13) ^ gfmul(s2, 9) ^ gfmul(s3, 14);
 | 
				
			||||||
 | 
					    return ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_decode_rcon(uint8_t r) {
 | 
				
			||||||
 | 
					    switch(r) {
 | 
				
			||||||
 | 
					    case 0:
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    case 1:
 | 
				
			||||||
 | 
					        return 2;
 | 
				
			||||||
 | 
					    case 2:
 | 
				
			||||||
 | 
					        return 4;
 | 
				
			||||||
 | 
					    case 3:
 | 
				
			||||||
 | 
					        return 8;
 | 
				
			||||||
 | 
					    case 4:
 | 
				
			||||||
 | 
					        return 16;
 | 
				
			||||||
 | 
					    case 5:
 | 
				
			||||||
 | 
					        return 32;
 | 
				
			||||||
 | 
					    case 6:
 | 
				
			||||||
 | 
					        return 64;
 | 
				
			||||||
 | 
					    case 7:
 | 
				
			||||||
 | 
					        return 128;
 | 
				
			||||||
 | 
					    case 8:
 | 
				
			||||||
 | 
					        return 27;
 | 
				
			||||||
 | 
					    case 9:
 | 
				
			||||||
 | 
					        return 54;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_subword_fwd(uint32_t x) {
 | 
				
			||||||
 | 
					    return ((uint32_t)aes_sbox_fwd(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint32_t)aes_sbox_fwd(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
 | 
				
			||||||
 | 
					           ((uint32_t)aes_sbox_fwd(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_fwd(bit_sub<0, 7 - 0 + 1>(x));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_subword_inv(uint32_t x) {
 | 
				
			||||||
 | 
					    return ((uint32_t)aes_sbox_inv(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint32_t)aes_sbox_inv(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
 | 
				
			||||||
 | 
					           ((uint32_t)aes_sbox_inv(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_inv(bit_sub<0, 7 - 0 + 1>(x));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_get_column(__uint128_t state, unsigned c) {
 | 
				
			||||||
 | 
					    assert(c < 4);
 | 
				
			||||||
 | 
					    return static_cast<uint32_t>(state >> (32 * c));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t aes_apply_fwd_sbox_to_each_byte(uint64_t x) {
 | 
				
			||||||
 | 
					    return ((uint64_t)aes_sbox_fwd(bit_sub<56, 63 - 56 + 1>(x)) << 56) | ((uint64_t)aes_sbox_fwd(bit_sub<48, 55 - 48 + 1>(x)) << 48) |
 | 
				
			||||||
 | 
					           ((uint64_t)aes_sbox_fwd(bit_sub<40, 47 - 40 + 1>(x)) << 40) | ((uint64_t)aes_sbox_fwd(bit_sub<32, 39 - 32 + 1>(x)) << 32) |
 | 
				
			||||||
 | 
					           ((uint64_t)aes_sbox_fwd(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint64_t)aes_sbox_fwd(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
 | 
				
			||||||
 | 
					           ((uint64_t)aes_sbox_fwd(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_fwd(bit_sub<0, 7 - 0 + 1>(x));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t aes_apply_inv_sbox_to_each_byte(uint64_t x) {
 | 
				
			||||||
 | 
					    return ((uint64_t)aes_sbox_inv(bit_sub<56, 63 - 56 + 1>(x)) << 56) | ((uint64_t)aes_sbox_inv(bit_sub<48, 55 - 48 + 1>(x)) << 48) |
 | 
				
			||||||
 | 
					           ((uint64_t)aes_sbox_inv(bit_sub<40, 47 - 40 + 1>(x)) << 40) | ((uint64_t)aes_sbox_inv(bit_sub<32, 39 - 32 + 1>(x)) << 32) |
 | 
				
			||||||
 | 
					           ((uint64_t)aes_sbox_inv(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint64_t)aes_sbox_inv(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
 | 
				
			||||||
 | 
					           ((uint64_t)aes_sbox_inv(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_inv(bit_sub<0, 7 - 0 + 1>(x));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t aes_rv64_shiftrows_fwd(uint64_t rs2, uint64_t rs1) {
 | 
				
			||||||
 | 
					    return ((uint64_t)bit_sub<24, 31 - 24 + 1>(rs1) << 56) | ((uint64_t)bit_sub<48, 55 - 48 + 1>(rs2) << 48) |
 | 
				
			||||||
 | 
					           ((uint64_t)bit_sub<8, 15 - 8 + 1>(rs2) << 40) | ((uint64_t)bit_sub<32, 39 - 32 + 1>(rs1) << 32) |
 | 
				
			||||||
 | 
					           ((uint64_t)bit_sub<56, 63 - 56 + 1>(rs2) << 24) | ((uint64_t)bit_sub<16, 23 - 16 + 1>(rs2) << 16) |
 | 
				
			||||||
 | 
					           ((uint64_t)bit_sub<40, 47 - 40 + 1>(rs1) << 8) | bit_sub<0, 7 - 0 + 1>(rs1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t aes_rv64_shiftrows_inv(uint64_t rs2, uint64_t rs1) {
 | 
				
			||||||
 | 
					    return ((uint64_t)bit_sub<24, 31 - 24 + 1>(rs2) << 56) | ((uint64_t)bit_sub<48, 55 - 48 + 1>(rs2) << 48) |
 | 
				
			||||||
 | 
					           ((uint64_t)bit_sub<8, 15 - 8 + 1>(rs1) << 40) | ((uint64_t)bit_sub<32, 39 - 32 + 1>(rs1) << 32) |
 | 
				
			||||||
 | 
					           ((uint64_t)bit_sub<56, 63 - 56 + 1>(rs1) << 24) | ((uint64_t)bit_sub<16, 23 - 16 + 1>(rs2) << 16) |
 | 
				
			||||||
 | 
					           ((uint64_t)bit_sub<40, 47 - 40 + 1>(rs2) << 8) | bit_sub<0, 7 - 0 + 1>(rs1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint128_t aes_shift_rows_fwd(uint128_t x) {
 | 
				
			||||||
 | 
					    uint32_t ic3 = aes_get_column(x, 3);
 | 
				
			||||||
 | 
					    uint32_t ic2 = aes_get_column(x, 2);
 | 
				
			||||||
 | 
					    uint32_t ic1 = aes_get_column(x, 1);
 | 
				
			||||||
 | 
					    uint32_t ic0 = aes_get_column(x, 0);
 | 
				
			||||||
 | 
					    uint32_t oc0 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic3) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic2) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic1) << 8) | bit_sub<0, 7 - 0 + 1>(ic0);
 | 
				
			||||||
 | 
					    uint32_t oc1 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic0) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic3) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic2) << 8) | bit_sub<0, 7 - 0 + 1>(ic1);
 | 
				
			||||||
 | 
					    uint32_t oc2 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic1) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic0) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic3) << 8) | bit_sub<0, 7 - 0 + 1>(ic2);
 | 
				
			||||||
 | 
					    uint32_t oc3 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic2) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic1) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic0) << 8) | bit_sub<0, 7 - 0 + 1>(ic3);
 | 
				
			||||||
 | 
					    return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint128_t aes_shift_rows_inv(uint128_t x) {
 | 
				
			||||||
 | 
					    uint32_t ic3 = aes_get_column(x, 3);
 | 
				
			||||||
 | 
					    uint32_t ic2 = aes_get_column(x, 2);
 | 
				
			||||||
 | 
					    uint32_t ic1 = aes_get_column(x, 1);
 | 
				
			||||||
 | 
					    uint32_t ic0 = aes_get_column(x, 0);
 | 
				
			||||||
 | 
					    uint32_t oc0 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic1) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic2) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic3) << 8) | bit_sub<0, 7 - 0 + 1>(ic0);
 | 
				
			||||||
 | 
					    uint32_t oc1 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic2) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic3) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic0) << 8) | bit_sub<0, 7 - 0 + 1>(ic1);
 | 
				
			||||||
 | 
					    uint32_t oc2 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic3) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic0) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic1) << 8) | bit_sub<0, 7 - 0 + 1>(ic2);
 | 
				
			||||||
 | 
					    uint32_t oc3 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic0) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic1) << 16) |
 | 
				
			||||||
 | 
					                   ((uint32_t)bit_sub<8, 15 - 8 + 1>(ic2) << 8) | bit_sub<0, 7 - 0 + 1>(ic3);
 | 
				
			||||||
 | 
					    return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint128_t aes_subbytes_fwd(uint128_t x) {
 | 
				
			||||||
 | 
					    uint32_t oc0 = aes_subword_fwd(aes_get_column(x, 0));
 | 
				
			||||||
 | 
					    uint32_t oc1 = aes_subword_fwd(aes_get_column(x, 1));
 | 
				
			||||||
 | 
					    uint32_t oc2 = aes_subword_fwd(aes_get_column(x, 2));
 | 
				
			||||||
 | 
					    uint32_t oc3 = aes_subword_fwd(aes_get_column(x, 3));
 | 
				
			||||||
 | 
					    return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint128_t aes_subbytes_inv(uint128_t x) {
 | 
				
			||||||
 | 
					    uint32_t oc0 = aes_subword_inv(aes_get_column(x, 0));
 | 
				
			||||||
 | 
					    uint32_t oc1 = aes_subword_inv(aes_get_column(x, 1));
 | 
				
			||||||
 | 
					    uint32_t oc2 = aes_subword_inv(aes_get_column(x, 2));
 | 
				
			||||||
 | 
					    uint32_t oc3 = aes_subword_inv(aes_get_column(x, 3));
 | 
				
			||||||
 | 
					    return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint128_t aes_mixcolumns_fwd(uint128_t x) {
 | 
				
			||||||
 | 
					    uint32_t oc0 = aes_mixcolumn_fwd(aes_get_column(x, 0));
 | 
				
			||||||
 | 
					    uint32_t oc1 = aes_mixcolumn_fwd(aes_get_column(x, 1));
 | 
				
			||||||
 | 
					    uint32_t oc2 = aes_mixcolumn_fwd(aes_get_column(x, 2));
 | 
				
			||||||
 | 
					    uint32_t oc3 = aes_mixcolumn_fwd(aes_get_column(x, 3));
 | 
				
			||||||
 | 
					    return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint128_t aes_mixcolumns_inv(uint128_t x) {
 | 
				
			||||||
 | 
					    uint32_t oc0 = aes_mixcolumn_inv(aes_get_column(x, 0));
 | 
				
			||||||
 | 
					    uint32_t oc1 = aes_mixcolumn_inv(aes_get_column(x, 1));
 | 
				
			||||||
 | 
					    uint32_t oc2 = aes_mixcolumn_inv(aes_get_column(x, 2));
 | 
				
			||||||
 | 
					    uint32_t oc3 = aes_mixcolumn_inv(aes_get_column(x, 3));
 | 
				
			||||||
 | 
					    return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t aes_rotword(uint32_t x) {
 | 
				
			||||||
 | 
					    uint8_t a0 = bit_sub<0, 7 - 0 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t a1 = bit_sub<8, 15 - 8 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t a2 = bit_sub<16, 23 - 16 + 1>(x);
 | 
				
			||||||
 | 
					    uint8_t a3 = bit_sub<24, 31 - 24 + 1>(x);
 | 
				
			||||||
 | 
					    return ((uint32_t)a0 << 24) | ((uint32_t)a3 << 16) | ((uint32_t)a2 << 8) | a1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::function<uint128_t(uint128_t, uint128_t, uint128_t)> get_crypto_funct(unsigned funct6, unsigned vs1) {
 | 
				
			||||||
 | 
					    switch(funct6) {
 | 
				
			||||||
 | 
					    case 0b101000: // VAES.VV
 | 
				
			||||||
 | 
					    case 0b101001: // VAES.VS
 | 
				
			||||||
 | 
					        switch(vs1) {
 | 
				
			||||||
 | 
					        case 0b00000: // VAESDM
 | 
				
			||||||
 | 
					            return [](uint128_t state, uint128_t rkey, uint128_t) {
 | 
				
			||||||
 | 
					                uint128_t sr = aes_shift_rows_inv(state);
 | 
				
			||||||
 | 
					                uint128_t sb = aes_subbytes_inv(sr);
 | 
				
			||||||
 | 
					                uint128_t ark = sb ^ rkey;
 | 
				
			||||||
 | 
					                uint128_t mix = aes_mixcolumns_inv(ark);
 | 
				
			||||||
 | 
					                return mix;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b00001: // VAESDF
 | 
				
			||||||
 | 
					            return [](uint128_t state, uint128_t rkey, uint128_t) {
 | 
				
			||||||
 | 
					                uint128_t sr = aes_shift_rows_inv(state);
 | 
				
			||||||
 | 
					                uint128_t sb = aes_subbytes_inv(sr);
 | 
				
			||||||
 | 
					                uint128_t ark = sb ^ rkey;
 | 
				
			||||||
 | 
					                return ark;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b00010: // VAESEM
 | 
				
			||||||
 | 
					            return [](uint128_t state, uint128_t rkey, uint128_t) {
 | 
				
			||||||
 | 
					                uint128_t sb = aes_subbytes_fwd(state);
 | 
				
			||||||
 | 
					                uint128_t sr = aes_shift_rows_fwd(sb);
 | 
				
			||||||
 | 
					                uint128_t mix = aes_mixcolumns_fwd(sr);
 | 
				
			||||||
 | 
					                uint128_t ark = mix ^ rkey;
 | 
				
			||||||
 | 
					                return ark;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b00011: // VAESEF
 | 
				
			||||||
 | 
					            return [](uint128_t state, uint128_t rkey, uint128_t) {
 | 
				
			||||||
 | 
					                uint128_t sb = aes_subbytes_fwd(state);
 | 
				
			||||||
 | 
					                uint128_t sr = aes_shift_rows_fwd(sb);
 | 
				
			||||||
 | 
					                uint128_t ark = sr ^ rkey;
 | 
				
			||||||
 | 
					                return ark;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b00111: // VAESZ
 | 
				
			||||||
 | 
					            return [](uint128_t state, uint128_t rkey, uint128_t) {
 | 
				
			||||||
 | 
					                uint128_t ark = state ^ rkey;
 | 
				
			||||||
 | 
					                return ark;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b10000: // VSM4R
 | 
				
			||||||
 | 
					            throw new std::runtime_error("Unsupported operation in get_crypto_funct");
 | 
				
			||||||
 | 
					        case 0b10001: // VGMUL
 | 
				
			||||||
 | 
					            return [](uint128_t vd, uint128_t vs2, uint128_t) {
 | 
				
			||||||
 | 
					                uint128_t Y = brev8<uint128_t>(vd);
 | 
				
			||||||
 | 
					                uint128_t H = brev8<uint128_t>(vs2);
 | 
				
			||||||
 | 
					                uint128_t Z = 0;
 | 
				
			||||||
 | 
					                for(size_t bit = 0; bit < 128; bit++) {
 | 
				
			||||||
 | 
					                    if((Y >> bit) & 1)
 | 
				
			||||||
 | 
					                        Z ^= H;
 | 
				
			||||||
 | 
					                    bool reduce = (H >> 127) & 1;
 | 
				
			||||||
 | 
					                    H = H << 1;
 | 
				
			||||||
 | 
					                    if(reduce)
 | 
				
			||||||
 | 
					                        H ^= 0x87;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                uint128_t result = brev8<uint128_t>(Z);
 | 
				
			||||||
 | 
					                return result;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            throw new std::runtime_error("Unsupported operation in get_crypto_funct");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    case 0b100000: // VSM3ME
 | 
				
			||||||
 | 
					    case 0b100001: // VSM4K
 | 
				
			||||||
 | 
					        throw new std::runtime_error("Unsupported operation in get_crypto_funct");
 | 
				
			||||||
 | 
					    case 0b100010: // VAESKF1
 | 
				
			||||||
 | 
					        return [](uint128_t vd, uint128_t vs2, uint128_t r) {
 | 
				
			||||||
 | 
					            auto extract_word = [](const uint128_t& value, int index) -> uint32_t {
 | 
				
			||||||
 | 
					                return static_cast<uint32_t>((value >> (32 * index)) & std::numeric_limits<uint32_t>::max());
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uint32_t k0 = (vs2 >> 32 * 0) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t k1 = (vs2 >> 32 * 1) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t k2 = (vs2 >> 32 * 2) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t k3 = (vs2 >> 32 * 3) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t w0 = aes_subword_fwd(aes_rotword(k3)) ^ aes_decode_rcon(r) ^ k0;
 | 
				
			||||||
 | 
					            uint32_t w1 = w0 ^ k1;
 | 
				
			||||||
 | 
					            uint32_t w2 = w1 ^ k2;
 | 
				
			||||||
 | 
					            uint32_t w3 = w2 ^ k3;
 | 
				
			||||||
 | 
					            uint128_t result = (uint128_t(w3) << 96) | (uint128_t(w2) << 64) | (uint128_t(w1) << 32) | (uint128_t(w0));
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b101010: // VAESKF2
 | 
				
			||||||
 | 
					        return [](uint128_t vd, uint128_t vs2, uint128_t r) {
 | 
				
			||||||
 | 
					            uint32_t k0 = (vs2 >> 32 * 0) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t k1 = (vs2 >> 32 * 1) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t k2 = (vs2 >> 32 * 2) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t k3 = (vs2 >> 32 * 3) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t rkb0 = (vd >> 32 * 0) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t rkb1 = (vd >> 32 * 1) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t rkb2 = (vd >> 32 * 2) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t rkb3 = (vd >> 32 * 3) & std::numeric_limits<uint32_t>::max();
 | 
				
			||||||
 | 
					            uint32_t w0 = r & 1 ? aes_subword_fwd(k3) ^ rkb0 : aes_subword_fwd(aes_rotword(k3)) ^ aes_decode_rcon((r >> 1) - 1) ^ rkb0;
 | 
				
			||||||
 | 
					            uint32_t w1 = w0 ^ rkb1;
 | 
				
			||||||
 | 
					            uint32_t w2 = w1 ^ rkb2;
 | 
				
			||||||
 | 
					            uint32_t w3 = w2 ^ rkb3;
 | 
				
			||||||
 | 
					            uint128_t result = (uint128_t(w3) << 96) | (uint128_t(w2) << 64) | (uint128_t(w1) << 32) | (uint128_t(w0));
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b101011: // VSM3C
 | 
				
			||||||
 | 
					        throw new std::runtime_error("Unsupported operation in get_crypto_funct");
 | 
				
			||||||
 | 
					    case 0b101100: // VGHSH
 | 
				
			||||||
 | 
					        return [](uint128_t Y, uint128_t vs2, uint128_t X) {
 | 
				
			||||||
 | 
					            auto H = brev8<uint128_t>(vs2);
 | 
				
			||||||
 | 
					            uint128_t Z = 0;
 | 
				
			||||||
 | 
					            uint128_t S = brev8<uint128_t>(Y ^ X);
 | 
				
			||||||
 | 
					            for(size_t bit = 0; bit < 128; bit++) {
 | 
				
			||||||
 | 
					                if((S >> bit) & 1)
 | 
				
			||||||
 | 
					                    Z ^= H;
 | 
				
			||||||
 | 
					                bool reduce = (H >> 127) & 1;
 | 
				
			||||||
 | 
					                H = H << 1;
 | 
				
			||||||
 | 
					                if(reduce)
 | 
				
			||||||
 | 
					                    H ^= 0x87;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            uint128_t result = brev8<uint128_t>(Z);
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b101101: // VSHA2MS
 | 
				
			||||||
 | 
					    case 0b101110: // VSHA2CH
 | 
				
			||||||
 | 
					    case 0b101111: // VSHA2CL
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        throw new std::runtime_error("Unknown funct6 in get_crypto_funct");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
} // namespace softvector
 | 
					} // namespace softvector
 | 
				
			||||||
@@ -41,6 +41,10 @@
 | 
				
			|||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
namespace softvector {
 | 
					namespace softvector {
 | 
				
			||||||
 | 
					#ifndef _MSC_VER
 | 
				
			||||||
 | 
					using int128_t = __int128;
 | 
				
			||||||
 | 
					using uint128_t = unsigned __int128;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
const unsigned RFS = 32;
 | 
					const unsigned RFS = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct vtype_t {
 | 
					struct vtype_t {
 | 
				
			||||||
@@ -70,9 +74,14 @@ struct vmask_view {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
vmask_view read_vmask(uint8_t* V, uint16_t VLEN, uint16_t elem_count, uint8_t reg_idx = 0);
 | 
					vmask_view read_vmask(uint8_t* V, uint16_t VLEN, uint16_t elem_count, uint8_t reg_idx = 0);
 | 
				
			||||||
template <unsigned VLEN> vmask_view read_vmask(uint8_t* V, uint16_t elem_count, uint8_t reg_idx = 0);
 | 
					template <unsigned VLEN> vmask_view read_vmask(uint8_t* V, uint16_t elem_count, uint8_t reg_idx = 0);
 | 
				
			||||||
 | 
					std::function<uint128_t(uint128_t, uint128_t, uint128_t)> get_crypto_funct(unsigned funct6, unsigned vs1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename dest_elem_t, typename src_elem_t = dest_elem_t> dest_elem_t brev(src_elem_t vs2);
 | 
				
			||||||
 | 
					template <typename dest_elem_t, typename src_elem_t = dest_elem_t> dest_elem_t brev8(src_elem_t vs2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool softvec_read(void* core, uint64_t addr, uint64_t length, uint8_t* data);
 | 
					bool softvec_read(void* core, uint64_t addr, uint64_t length, uint8_t* data);
 | 
				
			||||||
bool softvec_write(void* core, uint64_t addr, uint64_t length, uint8_t* data);
 | 
					bool softvec_write(void* core, uint64_t addr, uint64_t length, uint8_t* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <unsigned VLEN, typename eew_t>
 | 
					template <unsigned VLEN, typename eew_t>
 | 
				
			||||||
uint64_t vector_load_store(void* core, std::function<bool(void*, uint64_t, uint64_t, uint8_t*)> load_store_fn, uint8_t* V, uint64_t vl,
 | 
					uint64_t vector_load_store(void* core, std::function<bool(void*, uint64_t, uint64_t, uint8_t*)> load_store_fn, uint8_t* V, uint64_t vl,
 | 
				
			||||||
                           uint64_t vstart, vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1, uint8_t segment_size, int64_t stride = 0,
 | 
					                           uint64_t vstart, vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1, uint8_t segment_size, int64_t stride = 0,
 | 
				
			||||||
@@ -167,6 +176,17 @@ void mask_fp_vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t
 | 
				
			|||||||
template <unsigned VLEN, typename elem_t>
 | 
					template <unsigned VLEN, typename elem_t>
 | 
				
			||||||
void mask_fp_vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
 | 
					void mask_fp_vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
 | 
				
			||||||
                           elem_t imm, uint8_t rm);
 | 
					                           elem_t imm, uint8_t rm);
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS>
 | 
				
			||||||
 | 
					void vector_vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
 | 
				
			||||||
 | 
					                          unsigned vs1);
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS>
 | 
				
			||||||
 | 
					void vector_scalar_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
 | 
				
			||||||
 | 
					                          unsigned vs1);
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS>
 | 
				
			||||||
 | 
					void vector_imm_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
 | 
				
			||||||
 | 
					                       uint8_t imm);
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS, typename elem_type_t>
 | 
				
			||||||
 | 
					void vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2, unsigned vs1);
 | 
				
			||||||
} // namespace softvector
 | 
					} // namespace softvector
 | 
				
			||||||
#include "vm/vector_functions.hpp"
 | 
					#include "vm/vector_functions.hpp"
 | 
				
			||||||
#endif /* _VM_VECTOR_FUNCTIONS_H_ */
 | 
					#endif /* _VM_VECTOR_FUNCTIONS_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@
 | 
				
			|||||||
//       alex@minres.com - initial API and implementation
 | 
					//       alex@minres.com - initial API and implementation
 | 
				
			||||||
////////////////////////////////////////////////////////////////////////////////
 | 
					////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "iss/interp/vm_base.h"
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#include <softfloat.h>
 | 
					#include <softfloat.h>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -55,6 +56,14 @@ extern "C" {
 | 
				
			|||||||
#ifdef __SIZEOF_INT128__
 | 
					#ifdef __SIZEOF_INT128__
 | 
				
			||||||
template <> struct std::make_signed<__uint128_t> { using type = __int128_t; };
 | 
					template <> struct std::make_signed<__uint128_t> { using type = __int128_t; };
 | 
				
			||||||
template <> struct std::make_signed<__int128_t> { using type = __int128_t; };
 | 
					template <> struct std::make_signed<__int128_t> { using type = __int128_t; };
 | 
				
			||||||
 | 
					// helper struct to make calling twice<T> on 128-bit datatypes legal at compile time
 | 
				
			||||||
 | 
					struct poison128_t {
 | 
				
			||||||
 | 
					    poison128_t() { throw std::runtime_error("Attempt to use twice<__uint128_t>::type at runtime"); }
 | 
				
			||||||
 | 
					    poison128_t(const poison128_t&) { throw std::runtime_error("Copy of poison128_t is not allowed"); }
 | 
				
			||||||
 | 
					    template <typename U> poison128_t(U) { throw std::runtime_error("Conversion to poison128_t is not allowed"); }
 | 
				
			||||||
 | 
					    operator __uint128_t() const { throw std::runtime_error("Use of poison128_t as __uint128_t is not allowed"); }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template <> struct std::make_signed<poison128_t> { using type = poison128_t; };
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace softvector {
 | 
					namespace softvector {
 | 
				
			||||||
@@ -108,6 +117,10 @@ template <> struct twice<uint32_t> { using type = uint64_t; };
 | 
				
			|||||||
#ifdef __SIZEOF_INT128__
 | 
					#ifdef __SIZEOF_INT128__
 | 
				
			||||||
template <> struct twice<int64_t> { using type = __int128_t; };
 | 
					template <> struct twice<int64_t> { using type = __int128_t; };
 | 
				
			||||||
template <> struct twice<uint64_t> { using type = __uint128_t; };
 | 
					template <> struct twice<uint64_t> { using type = __uint128_t; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <> struct twice<__uint128_t> { using type = poison128_t; };
 | 
				
			||||||
 | 
					template <> struct twice<__int128_t> { using type = poison128_t; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
template <class T> using twice_t = typename twice<T>::type; // for convenience
 | 
					template <class T> using twice_t = typename twice<T>::type; // for convenience
 | 
				
			||||||
template <typename TO, typename FROM> constexpr TO sext(FROM val) {
 | 
					template <typename TO, typename FROM> constexpr TO sext(FROM val) {
 | 
				
			||||||
@@ -180,6 +193,8 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
 | 
				
			|||||||
        switch(funct6) {
 | 
					        switch(funct6) {
 | 
				
			||||||
        case 0b000000: // VADD
 | 
					        case 0b000000: // VADD
 | 
				
			||||||
            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 + vs1; };
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 + vs1; };
 | 
				
			||||||
 | 
					        case 0b000001: // VANDN
 | 
				
			||||||
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 & ~vs1; };
 | 
				
			||||||
        case 0b000010: // VSUB
 | 
					        case 0b000010: // VSUB
 | 
				
			||||||
            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 - vs1; };
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 - vs1; };
 | 
				
			||||||
        case 0b000011: // VRSUB
 | 
					        case 0b000011: // VRSUB
 | 
				
			||||||
@@ -205,6 +220,22 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
 | 
				
			|||||||
                return static_cast<std::make_signed_t<dest_elem_t>>(static_cast<std::make_signed_t<src2_elem_t>>(vs2) -
 | 
					                return static_cast<std::make_signed_t<dest_elem_t>>(static_cast<std::make_signed_t<src2_elem_t>>(vs2) -
 | 
				
			||||||
                                                                    static_cast<std::make_signed_t<src1_elem_t>>(vs1));
 | 
					                                                                    static_cast<std::make_signed_t<src1_elem_t>>(vs1));
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b010100: // VROR
 | 
				
			||||||
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
 | 
					                constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
 | 
				
			||||||
 | 
					                auto shamt = vs1 & shift_mask<src1_elem_t>();
 | 
				
			||||||
 | 
					                return (vs2 >> shamt) | (vs2 << (bits - shamt));
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b010101: { // VROL
 | 
				
			||||||
 | 
					            if(funct3 == OPIVI)
 | 
				
			||||||
 | 
					                return get_funct<dest_elem_t>(0b010100, funct3);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
 | 
					                    constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
 | 
				
			||||||
 | 
					                    auto shamt = vs1 & shift_mask<src1_elem_t>();
 | 
				
			||||||
 | 
					                    return (vs2 << shamt) | (vs2 >> (bits - shamt));
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        case 0b100101: // VSLL
 | 
					        case 0b100101: // VSLL
 | 
				
			||||||
            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 << (vs1 & shift_mask<src2_elem_t>()); };
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 << (vs1 & shift_mask<src2_elem_t>()); };
 | 
				
			||||||
        case 0b101000: // VSRL
 | 
					        case 0b101000: // VSRL
 | 
				
			||||||
@@ -219,6 +250,10 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
 | 
				
			|||||||
            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
                return static_cast<std::make_signed_t<src2_elem_t>>(vs2) >> (vs1 & shift_mask<src2_elem_t>());
 | 
					                return static_cast<std::make_signed_t<src2_elem_t>>(vs2) >> (vs1 & shift_mask<src2_elem_t>());
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b110101: // VWSLL
 | 
				
			||||||
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(vs2) << (vs1 & (shift_mask<dest_elem_t>()));
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            throw new std::runtime_error("Unknown funct6 in get_funct");
 | 
					            throw new std::runtime_error("Unknown funct6 in get_funct");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -328,6 +363,24 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
 | 
				
			|||||||
            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
                return sext<dest_elem_t>(vs1) * static_cast<dest_elem_t>(vs2) + vd;
 | 
					                return sext<dest_elem_t>(vs1) * static_cast<dest_elem_t>(vs2) + vd;
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b001100: // VCLMUL
 | 
				
			||||||
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
 | 
					                dest_elem_t output = 0;
 | 
				
			||||||
 | 
					                for(size_t i = 0; i <= sizeof(dest_elem_t) * 8 - 1; i++) {
 | 
				
			||||||
 | 
					                    if((vs2 >> i) & 1)
 | 
				
			||||||
 | 
					                        output = output ^ (vs1 << i);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return output;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        case 0b001101: // VCLMULH
 | 
				
			||||||
 | 
					            return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
 | 
					                dest_elem_t output = 0;
 | 
				
			||||||
 | 
					                for(size_t i = 1; i < sizeof(dest_elem_t) * 8; i++) {
 | 
				
			||||||
 | 
					                    if((vs2 >> i) & 1)
 | 
				
			||||||
 | 
					                        output = output ^ (vs1 >> (sizeof(dest_elem_t) * 8 - i));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return output;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            throw new std::runtime_error("Unknown funct6 in get_funct");
 | 
					            throw new std::runtime_error("Unknown funct6 in get_funct");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -364,11 +417,10 @@ void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, ui
 | 
				
			|||||||
    auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
 | 
					    auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
 | 
				
			||||||
    for(size_t idx = vstart; idx < vl; idx++) {
 | 
					    for(size_t idx = vstart; idx < vl; idx++) {
 | 
				
			||||||
        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
					        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
				
			||||||
        if(mask_active) {
 | 
					        if(mask_active)
 | 
				
			||||||
            vd_view[idx] = fn(vd_view[idx], vs2_view[idx], imm);
 | 
					            vd_view[idx] = fn(vd_view[idx], vs2_view[idx], imm);
 | 
				
			||||||
        } else {
 | 
					        else if(vtype.vma())
 | 
				
			||||||
            vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(vtype.vta())
 | 
					    if(vtype.vta())
 | 
				
			||||||
        for(size_t idx = vl; idx < vlmax; idx++)
 | 
					        for(size_t idx = vl; idx < vlmax; idx++)
 | 
				
			||||||
@@ -535,6 +587,79 @@ std::function<dest_elem_t(src2_elem_t)> get_unary_fn(unsigned unary_op) {
 | 
				
			|||||||
    case 0b00100: // VZEXT.VF4
 | 
					    case 0b00100: // VZEXT.VF4
 | 
				
			||||||
    case 0b00010: // VZEXT.VF8
 | 
					    case 0b00010: // VZEXT.VF8
 | 
				
			||||||
        return [](src2_elem_t vs2) { return vs2; };
 | 
					        return [](src2_elem_t vs2) { return vs2; };
 | 
				
			||||||
 | 
					    case 0b01000: // VBREV8
 | 
				
			||||||
 | 
					        return [](src2_elem_t vs2) { return brev8<dest_elem_t>(vs2); };
 | 
				
			||||||
 | 
					    case 0b01001: // VREV8
 | 
				
			||||||
 | 
					        return [](src2_elem_t vs2) {
 | 
				
			||||||
 | 
					            constexpr unsigned byte_count = sizeof(src2_elem_t);
 | 
				
			||||||
 | 
					            dest_elem_t result = 0;
 | 
				
			||||||
 | 
					            for(size_t i = 0; i < byte_count; ++i) {
 | 
				
			||||||
 | 
					                result <<= 8;
 | 
				
			||||||
 | 
					                result |= (vs2 & 0xFF);
 | 
				
			||||||
 | 
					                vs2 >>= 8;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b01010: // VBREV
 | 
				
			||||||
 | 
					        return [](src2_elem_t vs2) { return brev<dest_elem_t>(vs2); };
 | 
				
			||||||
 | 
					    case 0b01100: // VCLZ
 | 
				
			||||||
 | 
					        return [](src2_elem_t vs2) {
 | 
				
			||||||
 | 
					            if(std::is_same_v<src2_elem_t, unsigned int>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_clz(vs2));
 | 
				
			||||||
 | 
					            else if(std::is_same_v<src2_elem_t, unsigned long>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_clzl(vs2));
 | 
				
			||||||
 | 
					            else if(std::is_same_v<src2_elem_t, unsigned long long>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_clzll(vs2));
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
 | 
				
			||||||
 | 
					                if(vs2 == 0)
 | 
				
			||||||
 | 
					                    return bits;
 | 
				
			||||||
 | 
					                dest_elem_t count = 0;
 | 
				
			||||||
 | 
					                for(size_t i = bits - 1; i >= 0; --i) {
 | 
				
			||||||
 | 
					                    if((vs2 >> i) & 1)
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    ++count;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b01101: // VCTZ
 | 
				
			||||||
 | 
					        return [](src2_elem_t vs2) {
 | 
				
			||||||
 | 
					            if(std::is_same_v<src2_elem_t, unsigned int>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_ctz(vs2));
 | 
				
			||||||
 | 
					            else if(std::is_same_v<src2_elem_t, unsigned long>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_ctzl(vs2));
 | 
				
			||||||
 | 
					            else if(std::is_same_v<src2_elem_t, unsigned long long>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_ctzll(vs2));
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
 | 
				
			||||||
 | 
					                if(vs2 == 0)
 | 
				
			||||||
 | 
					                    return bits;
 | 
				
			||||||
 | 
					                dest_elem_t count = 0;
 | 
				
			||||||
 | 
					                while((vs2 & 1) == 0) {
 | 
				
			||||||
 | 
					                    ++count;
 | 
				
			||||||
 | 
					                    vs2 >>= 1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b01110: // VCPOP
 | 
				
			||||||
 | 
					        return [](src2_elem_t vs2) {
 | 
				
			||||||
 | 
					            if(std::is_same_v<src2_elem_t, unsigned int>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_popcount(vs2));
 | 
				
			||||||
 | 
					            else if(std::is_same_v<src2_elem_t, unsigned long>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_popcountl(vs2));
 | 
				
			||||||
 | 
					            else if(std::is_same_v<src2_elem_t, unsigned long long>)
 | 
				
			||||||
 | 
					                return static_cast<dest_elem_t>(__builtin_popcountll(vs2));
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                dest_elem_t count = 0;
 | 
				
			||||||
 | 
					                while(vs2) {
 | 
				
			||||||
 | 
					                    count += vs2 & 1;
 | 
				
			||||||
 | 
					                    vs2 >>= 1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        throw new std::runtime_error("Unknown funct in get_unary_fn");
 | 
					        throw new std::runtime_error("Unknown funct in get_unary_fn");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -550,8 +675,8 @@ void vector_unary_op(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart
 | 
				
			|||||||
        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
					        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
				
			||||||
        if(mask_active)
 | 
					        if(mask_active)
 | 
				
			||||||
            vd_view[idx] = fn(vs2_view[idx]);
 | 
					            vd_view[idx] = fn(vs2_view[idx]);
 | 
				
			||||||
        else
 | 
					        else if(vtype.vma())
 | 
				
			||||||
            vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(vtype.vta())
 | 
					    if(vtype.vta())
 | 
				
			||||||
        for(size_t idx = vl; idx < vlmax; idx++)
 | 
					        for(size_t idx = vl; idx < vlmax; idx++)
 | 
				
			||||||
@@ -774,11 +899,10 @@ bool sat_vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t
 | 
				
			|||||||
    auto fn = get_sat_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
 | 
					    auto fn = get_sat_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
 | 
				
			||||||
    for(size_t idx = vstart; idx < vl; idx++) {
 | 
					    for(size_t idx = vstart; idx < vl; idx++) {
 | 
				
			||||||
        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
					        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
				
			||||||
        if(mask_active) {
 | 
					        if(mask_active)
 | 
				
			||||||
            saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], vs1_view[idx]);
 | 
					            saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], vs1_view[idx]);
 | 
				
			||||||
        } else {
 | 
					        else if(vtype.vma())
 | 
				
			||||||
            vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(vtype.vta())
 | 
					    if(vtype.vta())
 | 
				
			||||||
        for(size_t idx = vl; idx < vlmax; idx++) {
 | 
					        for(size_t idx = vl; idx < vlmax; idx++) {
 | 
				
			||||||
@@ -797,11 +921,10 @@ bool sat_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl
 | 
				
			|||||||
    auto fn = get_sat_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
 | 
					    auto fn = get_sat_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
 | 
				
			||||||
    for(size_t idx = vstart; idx < vl; idx++) {
 | 
					    for(size_t idx = vstart; idx < vl; idx++) {
 | 
				
			||||||
        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
					        bool mask_active = vm ? 1 : mask_reg[idx];
 | 
				
			||||||
        if(mask_active) {
 | 
					        if(mask_active)
 | 
				
			||||||
            saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], imm);
 | 
					            saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], imm);
 | 
				
			||||||
        } else {
 | 
					        else if(vtype.vma())
 | 
				
			||||||
            vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(vtype.vta())
 | 
					    if(vtype.vta())
 | 
				
			||||||
        for(size_t idx = vl; idx < vlmax; idx++) {
 | 
					        for(size_t idx = vl; idx < vlmax; idx++) {
 | 
				
			||||||
@@ -1939,4 +2062,221 @@ template <unsigned VLEN> void vector_whole_move(uint8_t* V, unsigned vd, unsigne
 | 
				
			|||||||
    memcpy(vd_view.start, vs2_view.start, VLEN / 8 * count);
 | 
					    memcpy(vd_view.start, vs2_view.start, VLEN / 8 * count);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS>
 | 
				
			||||||
 | 
					void vector_vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
 | 
				
			||||||
 | 
					                          unsigned vs1) {
 | 
				
			||||||
 | 
					    uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew() * EGS);
 | 
				
			||||||
 | 
					    auto vs1_view = get_vreg<VLEN, uint128_t>(V, vs1, vlmax);
 | 
				
			||||||
 | 
					    auto vs2_view = get_vreg<VLEN, uint128_t>(V, vs2, vlmax);
 | 
				
			||||||
 | 
					    auto vd_view = get_vreg<VLEN, uint128_t>(V, vd, vlmax);
 | 
				
			||||||
 | 
					    auto fn = get_crypto_funct(funct6, vs1);
 | 
				
			||||||
 | 
					    for(size_t idx = eg_start; idx < eg_len; idx++) {
 | 
				
			||||||
 | 
					        vd_view[idx] = fn(vd_view[idx], vs2_view[idx], vs1_view[idx]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(vtype.vta())
 | 
				
			||||||
 | 
					        for(size_t idx = eg_len; idx < vlmax; idx++)
 | 
				
			||||||
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS>
 | 
				
			||||||
 | 
					void vector_scalar_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
 | 
				
			||||||
 | 
					                          unsigned vs1) {
 | 
				
			||||||
 | 
					    uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew() * EGS);
 | 
				
			||||||
 | 
					    auto vs2_val = get_vreg<VLEN, uint128_t>(V, vs2, vlmax)[0];
 | 
				
			||||||
 | 
					    auto vd_view = get_vreg<VLEN, uint128_t>(V, vd, vlmax);
 | 
				
			||||||
 | 
					    auto fn = get_crypto_funct(funct6, vs1);
 | 
				
			||||||
 | 
					    for(size_t idx = eg_start; idx < eg_len; idx++) {
 | 
				
			||||||
 | 
					        vd_view[idx] = fn(vd_view[idx], vs2_val, -1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(vtype.vta())
 | 
				
			||||||
 | 
					        for(size_t idx = eg_len; idx < vlmax; idx++)
 | 
				
			||||||
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS>
 | 
				
			||||||
 | 
					void vector_imm_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
 | 
				
			||||||
 | 
					                       uint8_t imm) {
 | 
				
			||||||
 | 
					    uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew() * EGS);
 | 
				
			||||||
 | 
					    auto vs2_view = get_vreg<VLEN, uint128_t>(V, vs2, vlmax);
 | 
				
			||||||
 | 
					    auto vd_view = get_vreg<VLEN, uint128_t>(V, vd, vlmax);
 | 
				
			||||||
 | 
					    auto fn = get_crypto_funct(funct6, -1);
 | 
				
			||||||
 | 
					    for(size_t idx = eg_start; idx < eg_len; idx++) {
 | 
				
			||||||
 | 
					        vd_view[idx] = fn(vd_view[idx], vs2_view[idx], imm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(vtype.vta())
 | 
				
			||||||
 | 
					        for(size_t idx = eg_len; idx < vlmax; idx++)
 | 
				
			||||||
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template <typename T> T rotr(T x, unsigned n) {
 | 
				
			||||||
 | 
					    assert(n < sizeof(T) * 8);
 | 
				
			||||||
 | 
					    return (x >> n) | (x << (sizeof(T) * 8 - n));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template <typename T> T shr(T x, unsigned n) {
 | 
				
			||||||
 | 
					    assert(n < sizeof(T) * 8);
 | 
				
			||||||
 | 
					    return (x >> n);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template <typename T> T sum0(T);
 | 
				
			||||||
 | 
					template <> inline uint32_t sum0(uint32_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
 | 
				
			||||||
 | 
					template <> inline uint64_t sum0(uint64_t x) { return rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39); }
 | 
				
			||||||
 | 
					template <typename T> T sum1(T);
 | 
				
			||||||
 | 
					template <> inline uint32_t sum1(uint32_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
 | 
				
			||||||
 | 
					template <> inline uint64_t sum1(uint64_t x) { return rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41); }
 | 
				
			||||||
 | 
					template <typename T> T ch(T x, T y, T z) { return ((x & y) ^ ((~x) & z)); }
 | 
				
			||||||
 | 
					template <typename T> T maj(T x, T y, T z) { return ((x & y) ^ (x & z) ^ (y & z)); }
 | 
				
			||||||
 | 
					template <typename T> T sig0(T);
 | 
				
			||||||
 | 
					template <> inline uint32_t sig0(uint32_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
 | 
				
			||||||
 | 
					template <> inline uint64_t sig0(uint64_t x) { return rotr(x, 1) ^ rotr(x, 8) ^ shr(x, 7); }
 | 
				
			||||||
 | 
					template <typename T> T sig1(T);
 | 
				
			||||||
 | 
					template <> inline uint32_t sig1(uint32_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
 | 
				
			||||||
 | 
					template <> inline uint64_t sig1(uint64_t x) { return rotr(x, 19) ^ rotr(x, 61) ^ shr(x, 6); }
 | 
				
			||||||
 | 
					template <typename T> std::function<void(vreg_view<T>&, vreg_view<T>&, vreg_view<T>&)> get_crypto_funct(unsigned int funct6) {
 | 
				
			||||||
 | 
					    switch(funct6) {
 | 
				
			||||||
 | 
					    case 0b101110: // VSHA2CH
 | 
				
			||||||
 | 
					        return [](vreg_view<T>& vd_view, vreg_view<T>& vs2_view, vreg_view<T>& vs1_view) {
 | 
				
			||||||
 | 
					            T a = vs2_view[3];
 | 
				
			||||||
 | 
					            T b = vs2_view[2];
 | 
				
			||||||
 | 
					            T c = vd_view[3];
 | 
				
			||||||
 | 
					            T d = vd_view[2];
 | 
				
			||||||
 | 
					            T e = vs2_view[1];
 | 
				
			||||||
 | 
					            T f = vs2_view[0];
 | 
				
			||||||
 | 
					            T g = vd_view[1];
 | 
				
			||||||
 | 
					            T h = vd_view[0];
 | 
				
			||||||
 | 
					            T W0 = vs1_view[2];
 | 
				
			||||||
 | 
					            T W1 = vs1_view[3];
 | 
				
			||||||
 | 
					            T T1 = h + sum1(e) + ch(e, f, g) + W0;
 | 
				
			||||||
 | 
					            T T2 = sum0(a) + maj(a, b, c);
 | 
				
			||||||
 | 
					            h = g;
 | 
				
			||||||
 | 
					            g = f;
 | 
				
			||||||
 | 
					            f = e;
 | 
				
			||||||
 | 
					            e = d + T1;
 | 
				
			||||||
 | 
					            d = c;
 | 
				
			||||||
 | 
					            c = b;
 | 
				
			||||||
 | 
					            b = a;
 | 
				
			||||||
 | 
					            a = T1 + T2;
 | 
				
			||||||
 | 
					            T1 = h + sum1(e) + ch(e, f, g) + W1;
 | 
				
			||||||
 | 
					            T2 = sum0(a) + maj(a, b, c);
 | 
				
			||||||
 | 
					            h = g;
 | 
				
			||||||
 | 
					            g = f;
 | 
				
			||||||
 | 
					            f = e;
 | 
				
			||||||
 | 
					            e = d + T1;
 | 
				
			||||||
 | 
					            d = c;
 | 
				
			||||||
 | 
					            c = b;
 | 
				
			||||||
 | 
					            b = a;
 | 
				
			||||||
 | 
					            a = T1 + T2;
 | 
				
			||||||
 | 
					            vd_view[0] = f;
 | 
				
			||||||
 | 
					            vd_view[1] = e;
 | 
				
			||||||
 | 
					            vd_view[2] = b;
 | 
				
			||||||
 | 
					            vd_view[3] = a;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b101111: // VSHA2CL
 | 
				
			||||||
 | 
					        return [](vreg_view<T>& vd_view, vreg_view<T>& vs2_view, vreg_view<T>& vs1_view) {
 | 
				
			||||||
 | 
					            T a = vs2_view[3];
 | 
				
			||||||
 | 
					            T b = vs2_view[2];
 | 
				
			||||||
 | 
					            T c = vd_view[3];
 | 
				
			||||||
 | 
					            T d = vd_view[2];
 | 
				
			||||||
 | 
					            T e = vs2_view[1];
 | 
				
			||||||
 | 
					            T f = vs2_view[0];
 | 
				
			||||||
 | 
					            T g = vd_view[1];
 | 
				
			||||||
 | 
					            T h = vd_view[0];
 | 
				
			||||||
 | 
					            T W0 = vs1_view[0];
 | 
				
			||||||
 | 
					            T W1 = vs1_view[1];
 | 
				
			||||||
 | 
					            T T1 = h + sum1(e) + ch(e, f, g) + W0;
 | 
				
			||||||
 | 
					            T T2 = sum0(a) + maj(a, b, c);
 | 
				
			||||||
 | 
					            h = g;
 | 
				
			||||||
 | 
					            g = f;
 | 
				
			||||||
 | 
					            f = e;
 | 
				
			||||||
 | 
					            e = d + T1;
 | 
				
			||||||
 | 
					            d = c;
 | 
				
			||||||
 | 
					            c = b;
 | 
				
			||||||
 | 
					            b = a;
 | 
				
			||||||
 | 
					            a = T1 + T2;
 | 
				
			||||||
 | 
					            T1 = h + sum1(e) + ch(e, f, g) + W1;
 | 
				
			||||||
 | 
					            T2 = sum0(a) + maj(a, b, c);
 | 
				
			||||||
 | 
					            h = g;
 | 
				
			||||||
 | 
					            g = f;
 | 
				
			||||||
 | 
					            f = e;
 | 
				
			||||||
 | 
					            e = d + T1;
 | 
				
			||||||
 | 
					            d = c;
 | 
				
			||||||
 | 
					            c = b;
 | 
				
			||||||
 | 
					            b = a;
 | 
				
			||||||
 | 
					            a = T1 + T2;
 | 
				
			||||||
 | 
					            vd_view[0] = f;
 | 
				
			||||||
 | 
					            vd_view[1] = e;
 | 
				
			||||||
 | 
					            vd_view[2] = b;
 | 
				
			||||||
 | 
					            vd_view[3] = a;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    case 0b101101: // VSHA2MS
 | 
				
			||||||
 | 
					        return [](vreg_view<T>& vd_view, vreg_view<T>& vs2_view, vreg_view<T>& vs1_view) {
 | 
				
			||||||
 | 
					            T W0 = vd_view[0];
 | 
				
			||||||
 | 
					            T W1 = vd_view[1];
 | 
				
			||||||
 | 
					            T W2 = vd_view[2];
 | 
				
			||||||
 | 
					            T W3 = vd_view[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            T W4 = vs2_view[0];
 | 
				
			||||||
 | 
					            T W9 = vs2_view[1];
 | 
				
			||||||
 | 
					            T W10 = vs2_view[2];
 | 
				
			||||||
 | 
					            T W11 = vs2_view[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            T W12 = vs1_view[0];
 | 
				
			||||||
 | 
					            T W13 = vs1_view[1];
 | 
				
			||||||
 | 
					            T W14 = vs1_view[2];
 | 
				
			||||||
 | 
					            T W15 = vs1_view[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            T W16 = sig1(W14) + W9 + sig0(W1) + W0;
 | 
				
			||||||
 | 
					            T W17 = sig1(W15) + W10 + sig0(W2) + W1;
 | 
				
			||||||
 | 
					            T W18 = sig1(W16) + W11 + sig0(W3) + W2;
 | 
				
			||||||
 | 
					            T W19 = sig1(W17) + W12 + sig0(W4) + W3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            vd_view[0] = W16;
 | 
				
			||||||
 | 
					            vd_view[1] = W17;
 | 
				
			||||||
 | 
					            vd_view[2] = W18;
 | 
				
			||||||
 | 
					            vd_view[3] = W19;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        throw new std::runtime_error("Unsupported operation in get_crypto_funct");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template <unsigned VLEN, unsigned EGS, typename elem_type_t>
 | 
				
			||||||
 | 
					void vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
 | 
				
			||||||
 | 
					                   unsigned vs1) {
 | 
				
			||||||
 | 
					    auto fn = get_crypto_funct<elem_type_t>(funct6);
 | 
				
			||||||
 | 
					    auto vd_view = get_vreg<VLEN, elem_type_t>(V, vd, EGS);
 | 
				
			||||||
 | 
					    auto vs2_view = get_vreg<VLEN, elem_type_t>(V, vs2, EGS);
 | 
				
			||||||
 | 
					    auto vs1_view = get_vreg<VLEN, elem_type_t>(V, vs1, EGS);
 | 
				
			||||||
 | 
					    for(size_t idx = eg_start; idx < eg_len; idx++) {
 | 
				
			||||||
 | 
					        fn(vd_view, vs2_view, vs1_view);
 | 
				
			||||||
 | 
					        // We cannot use views in case EGW < VLEN, as views can only address the start of a register
 | 
				
			||||||
 | 
					        vd_view.start += EGS * sizeof(elem_type_t);
 | 
				
			||||||
 | 
					        vs2_view.start += EGS * sizeof(elem_type_t);
 | 
				
			||||||
 | 
					        vs1_view.start += EGS * sizeof(elem_type_t);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(vtype.vta()) {
 | 
				
			||||||
 | 
					        uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew());
 | 
				
			||||||
 | 
					        auto vd_view = get_vreg<VLEN, elem_type_t>(V, vd, vlmax);
 | 
				
			||||||
 | 
					        for(size_t idx = eg_len * EGS; idx < vlmax; idx++)
 | 
				
			||||||
 | 
					            vd_view[idx] = agnostic_behavior(vd_view[idx]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename dest_elem_t, typename src_elem_t> dest_elem_t brev(src_elem_t vs2) {
 | 
				
			||||||
 | 
					    constexpr dest_elem_t bits = sizeof(src_elem_t) * 8;
 | 
				
			||||||
 | 
					    dest_elem_t result = 0;
 | 
				
			||||||
 | 
					    for(size_t i = 0; i < bits; ++i) {
 | 
				
			||||||
 | 
					        result <<= 1;
 | 
				
			||||||
 | 
					        result |= (vs2 & 1);
 | 
				
			||||||
 | 
					        vs2 >>= 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template <typename dest_elem_t, typename src_elem_t> dest_elem_t brev8(src_elem_t vs2) {
 | 
				
			||||||
 | 
					    constexpr unsigned byte_count = sizeof(src_elem_t);
 | 
				
			||||||
 | 
					    dest_elem_t result = 0;
 | 
				
			||||||
 | 
					    for(size_t i = 0; i < byte_count; ++i) {
 | 
				
			||||||
 | 
					        dest_elem_t byte = (vs2 >> (i * 8)) & 0xFF;
 | 
				
			||||||
 | 
					        byte = ((byte & 0xF0) >> 4) | ((byte & 0x0F) << 4);
 | 
				
			||||||
 | 
					        byte = ((byte & 0xCC) >> 2) | ((byte & 0x33) << 2);
 | 
				
			||||||
 | 
					        byte = ((byte & 0xAA) >> 1) | ((byte & 0x55) << 1);
 | 
				
			||||||
 | 
					        result |= byte << (i * 8);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
} // namespace softvector
 | 
					} // namespace softvector
 | 
				
			||||||
		Reference in New Issue
	
	Block a user