Compare commits
	
		
			4 Commits
		
	
	
		
			e48597b2b7
			...
			e6aa6e5842
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e6aa6e5842 | |||
| 4418fa7e4f | |||
| adaa7e1c04 | |||
| 0eb1db0e7e | 
| @@ -37,7 +37,7 @@ | |||||||
| #include <iss/asmjit/vm_base.h> | #include <iss/asmjit/vm_base.h> | ||||||
| #include <asmjit/asmjit.h> | #include <asmjit/asmjit.h> | ||||||
| #include <util/logging.h> | #include <util/logging.h> | ||||||
| #include <fp_functions.h> |  | ||||||
| #ifndef FMT_HEADER_ONLY | #ifndef FMT_HEADER_ONLY | ||||||
| #define FMT_HEADER_ONLY | #define FMT_HEADER_ONLY | ||||||
| #endif | #endif | ||||||
| @@ -92,7 +92,7 @@ protected: | |||||||
|         auto sign_mask = 1ULL<<(W-1); |         auto sign_mask = 1ULL<<(W-1); | ||||||
|         return (from & mask) | ((from & sign_mask) ? ~mask : 0); |         return (from & mask) | ((from & sign_mask) ? ~mask : 0); | ||||||
|     }  |     }  | ||||||
| #include "helper_func.h" | #include <vm/asmjit/helper_func.h> | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     /**************************************************************************** |     /**************************************************************************** | ||||||
|   | |||||||
| @@ -320,6 +320,8 @@ protected: | |||||||
|  |  | ||||||
|         unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } |         unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } | ||||||
|  |  | ||||||
|  |         unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; } | ||||||
|  |  | ||||||
|         riscv_hart_m_p<BASE, FEAT>& arch; |         riscv_hart_m_p<BASE, FEAT>& arch; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -415,7 +417,7 @@ protected: | |||||||
|     std::vector<std::function<mem_write_f>> memfn_write; |     std::vector<std::function<mem_write_f>> memfn_write; | ||||||
|     void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>); |     void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>); | ||||||
|     feature_config cfg; |     feature_config cfg; | ||||||
|     uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16}; |     unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U,static_cast<unsigned>(traits<BASE>::CLIC_NUM_IRQ)) : 16U}; | ||||||
|     inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } |     inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } | ||||||
|     std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd, |     std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd, | ||||||
|                                                                                         std::function<mem_write_f> wr) { |                                                                                         std::function<mem_write_f> wr) { | ||||||
| @@ -822,7 +824,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc | |||||||
|                 x |= 0x80; // set pll lock upon writing |                 x |= 0x80; // set pll lock upon writing | ||||||
|                 return iss::Ok; |                 return iss::Ok; | ||||||
|             } break; |             } break; | ||||||
|             default: {} |             default: { | ||||||
|  |             } | ||||||
|             } |             } | ||||||
|         } break; |         } break; | ||||||
|         case traits<BASE>::CSR: { |         case traits<BASE>::CSR: { | ||||||
|   | |||||||
| @@ -371,6 +371,8 @@ protected: | |||||||
|  |  | ||||||
|         unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } |         unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } | ||||||
|  |  | ||||||
|  |         unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; } | ||||||
|  |  | ||||||
|         riscv_hart_msu_vp<BASE>& arch; |         riscv_hart_msu_vp<BASE>& arch; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -802,7 +804,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | |||||||
|                 x |= 0x80; // set pll lock upon writing |                 x |= 0x80; // set pll lock upon writing | ||||||
|                 return iss::Ok; |                 return iss::Ok; | ||||||
|             } break; |             } break; | ||||||
|             default: {} |             default: { | ||||||
|  |             } | ||||||
|             } |             } | ||||||
|         } break; |         } break; | ||||||
|         case traits<BASE>::CSR: { |         case traits<BASE>::CSR: { | ||||||
|   | |||||||
| @@ -347,6 +347,8 @@ protected: | |||||||
|  |  | ||||||
|         unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } |         unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; } | ||||||
|  |  | ||||||
|  |         unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; } | ||||||
|  |  | ||||||
|         riscv_hart_mu_p<BASE, FEAT>& arch; |         riscv_hart_mu_p<BASE, FEAT>& arch; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -445,7 +447,7 @@ protected: | |||||||
|     std::vector<std::function<mem_write_f>> memfn_write; |     std::vector<std::function<mem_write_f>> memfn_write; | ||||||
|     void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>); |     void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>); | ||||||
|     feature_config cfg; |     feature_config cfg; | ||||||
|     uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16}; |     unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U,static_cast<unsigned>(traits<BASE>::CLIC_NUM_IRQ)) : 16U}; | ||||||
|     inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } |     inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } | ||||||
|  |  | ||||||
|     std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd, |     std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd, | ||||||
| @@ -1005,7 +1007,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac | |||||||
|                 x |= 0x80; // set pll lock upon writing |                 x |= 0x80; // set pll lock upon writing | ||||||
|                 return iss::Ok; |                 return iss::Ok; | ||||||
|             } break; |             } break; | ||||||
|             default: {} |             default: { | ||||||
|  |             } | ||||||
|             } |             } | ||||||
|         } break; |         } break; | ||||||
|         case traits<BASE>::CSR: { |         case traits<BASE>::CSR: { | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ template <> struct traits<tgc5c> { | |||||||
|     static constexpr std::array<const char*, 36> reg_aliases{ |     static constexpr std::array<const char*, 36> reg_aliases{ | ||||||
|         {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; |         {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; | ||||||
|  |  | ||||||
|     enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; |     enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, CLIC_NUM_IRQ=0ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; | ||||||
|  |  | ||||||
|     constexpr static unsigned FP_REGS_SIZE = 0; |     constexpr static unsigned FP_REGS_SIZE = 0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| x86::Gp get_reg_for(jit_holder& jh, unsigned idx) { | x86::Gp get_reg_for(jit_holder& jh, unsigned idx) { | ||||||
|     // can check for regs in jh and return them instead of creating new ones |     // TODO can check for regs in jh and return them instead of creating new ones | ||||||
|     switch(traits::reg_bit_widths[idx]) { |     switch(traits::reg_bit_widths[idx]) { | ||||||
|     case 8: |     case 8: | ||||||
|         return jh.cc.newInt8(); |         return jh.cc.newInt8(); | ||||||
| @@ -82,7 +82,9 @@ void gen_instr_prologue(jit_holder& jh, addr_t pc) { | |||||||
|     cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc); |     cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc); | ||||||
|  |  | ||||||
|     cc.comment("\n//*trap_state=*pending_trap;"); |     cc.comment("\n//*trap_state=*pending_trap;"); | ||||||
|     cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), jh.trap_state); |     x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE); | ||||||
|  |     cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE)); | ||||||
|  |     cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), current_trap_state); | ||||||
|  |  | ||||||
|     cc.comment("\n//increment *next_pc"); |     cc.comment("\n//increment *next_pc"); | ||||||
|     cc.mov(jh.next_pc, pc); |     cc.mov(jh.next_pc, pc); | ||||||
| @@ -91,20 +93,20 @@ void gen_instr_epilogue(jit_holder& jh) { | |||||||
|     auto& cc = jh.cc; |     auto& cc = jh.cc; | ||||||
|  |  | ||||||
|     cc.comment("\n//if(*trap_state!=0) goto trap_entry;"); |     cc.comment("\n//if(*trap_state!=0) goto trap_entry;"); | ||||||
|     cc.test(jh.trap_state, jh.trap_state); |     x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE); | ||||||
|     cc.jnz(jh.trap_entry); |     cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE)); | ||||||
|  |     cc.cmp(current_trap_state, 0); | ||||||
|  |     cc.jne(jh.trap_entry); | ||||||
|  |  | ||||||
|     // Does this need to be done after every single instruction? |     // TODO: Does not need to be done for every instruction, only when needed | ||||||
|     cc.comment("\n//write back regs to mem"); |     cc.comment("\n//write back regs to mem"); | ||||||
|     write_reg_to_mem(jh, jh.pc, traits::PC); |     write_reg_to_mem(jh, jh.pc, traits::PC); | ||||||
|     write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC); |     write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC); | ||||||
|     write_reg_to_mem(jh, jh.trap_state, traits::TRAP_STATE); |  | ||||||
| } | } | ||||||
| void gen_block_prologue(jit_holder& jh) override { | void gen_block_prologue(jit_holder& jh) override { | ||||||
|  |  | ||||||
|     jh.pc = load_reg_from_mem(jh, traits::PC); |     jh.pc = load_reg_from_mem(jh, traits::PC); | ||||||
|     jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC); |     jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC); | ||||||
|     jh.trap_state = load_reg_from_mem(jh, traits::TRAP_STATE); |  | ||||||
| } | } | ||||||
| void gen_block_epilogue(jit_holder& jh) override { | void gen_block_epilogue(jit_holder& jh) override { | ||||||
|     x86::Compiler& cc = jh.cc; |     x86::Compiler& cc = jh.cc; | ||||||
| @@ -112,7 +114,12 @@ void gen_block_epilogue(jit_holder& jh) override { | |||||||
|     cc.ret(jh.next_pc); |     cc.ret(jh.next_pc); | ||||||
|  |  | ||||||
|     cc.bind(jh.trap_entry); |     cc.bind(jh.trap_entry); | ||||||
|     cc.comment("\n//enter_trap(core_ptr, *trap_state, *pc, 0);"); |     cc.comment("\n//Prepare for enter_trap;"); | ||||||
|  |     // Make sure cached values are written back | ||||||
|  |     cc.comment("\n//write back regs to mem"); | ||||||
|  |     write_reg_to_mem(jh, jh.pc, traits::PC); | ||||||
|  |     write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC); | ||||||
|  |     this->gen_sync(jh, POST_SYNC, -1); | ||||||
|  |  | ||||||
|     x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE); |     x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE); | ||||||
|     cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE)); |     cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE)); | ||||||
| @@ -121,23 +128,43 @@ void gen_block_epilogue(jit_holder& jh) override { | |||||||
|     cc.mov(current_pc, get_reg_ptr(jh, traits::PC)); |     cc.mov(current_pc, get_reg_ptr(jh, traits::PC)); | ||||||
|  |  | ||||||
|     x86::Gp instr = cc.newInt32("instr"); |     x86::Gp instr = cc.newInt32("instr"); | ||||||
|     cc.mov(instr, 0); |     cc.mov(instr, 0); // this is not correct | ||||||
|  |     cc.comment("\n//enter trap call;"); | ||||||
|     InvokeNode* call_enter_trap; |     InvokeNode* call_enter_trap; | ||||||
|     cc.invoke(&call_enter_trap, &enter_trap, FuncSignatureT<uint64_t, void*, uint64_t, uint64_t, uint64_t>()); |     cc.invoke(&call_enter_trap, &enter_trap, FuncSignatureT<uint64_t, void*, uint64_t, uint64_t, uint64_t>()); | ||||||
|     call_enter_trap->setArg(0, jh.arch_if_ptr); |     call_enter_trap->setArg(0, jh.arch_if_ptr); | ||||||
|     call_enter_trap->setArg(1, current_trap_state); |     call_enter_trap->setArg(1, current_trap_state); | ||||||
|     call_enter_trap->setArg(2, current_pc); |     call_enter_trap->setArg(2, current_pc); | ||||||
|     call_enter_trap->setArg(3, instr); |     call_enter_trap->setArg(3, instr); | ||||||
|  |  | ||||||
|  |     x86::Gp current_next_pc = get_reg_for(jh, traits::NEXT_PC); | ||||||
|  |     cc.mov(current_next_pc, get_reg_ptr(jh, traits::NEXT_PC)); | ||||||
|  |     cc.mov(jh.next_pc, current_next_pc); | ||||||
|  |  | ||||||
|     cc.comment("\n//*last_branch = std::numeric_limits<uint32_t>::max();"); |     cc.comment("\n//*last_branch = std::numeric_limits<uint32_t>::max();"); | ||||||
|     cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max()); |     cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max()); | ||||||
|     cc.comment("\n//return *next_pc;"); |     cc.comment("\n//return *next_pc;"); | ||||||
|     cc.ret(jh.next_pc); |     cc.ret(jh.next_pc); | ||||||
| } | } | ||||||
| // TODO implement | /* | ||||||
|  |     inline void raise(uint16_t trap_id, uint16_t cause){ | ||||||
| void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { jh.cc.comment("//gen_raise"); } |         auto trap_val =  0x80ULL << 24 | (cause << 16) | trap_id; | ||||||
| void gen_wait(jit_holder& jh, unsigned type) { jh.cc.comment("//gen_wait"); } |         this->core.reg.trap_state = trap_val; | ||||||
| void gen_leave(jit_holder& jh, unsigned lvl) { jh.cc.comment("//gen_leave"); } |         this->template get_reg<uint32_t>(traits::NEXT_PC) = std::numeric_limits<uint32_t>::max(); | ||||||
|  |     } | ||||||
|  | */ | ||||||
|  | inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { | ||||||
|  |     auto& cc = jh.cc; | ||||||
|  |     cc.comment("//gen_raise"); | ||||||
|  |     auto tmp1 = get_reg_for(jh, traits::TRAP_STATE); | ||||||
|  |     cc.mov(tmp1, 0x80ULL << 24 | (cause << 16) | trap_id); | ||||||
|  |     cc.mov(get_reg_ptr(jh, traits::TRAP_STATE), tmp1); | ||||||
|  |     auto tmp2 = get_reg_for(jh, traits::NEXT_PC); | ||||||
|  |     cc.mov(tmp2, std::numeric_limits<uint32_t>::max()); | ||||||
|  |     cc.mov(get_reg_ptr(jh, traits::NEXT_PC), tmp2); | ||||||
|  | } | ||||||
|  | inline void gen_wait(jit_holder& jh, unsigned type) { jh.cc.comment("//gen_wait"); } | ||||||
|  | inline void gen_leave(jit_holder& jh, unsigned lvl) { jh.cc.comment("//gen_leave"); } | ||||||
|  |  | ||||||
| enum operation { add, sub, band, bor, bxor, shl, sar, shr }; | enum operation { add, sub, band, bor, bxor, shl, sar, shr }; | ||||||
|  |  | ||||||
| @@ -342,24 +369,12 @@ x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a) { | |||||||
|     return a; |     return a; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* template <typename T> |  | ||||||
| inline typename std::enable_if_t<std::is_unsigned<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool |  | ||||||
| is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg, |  | ||||||
| val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename std::enable_if_t<std::is_signed<T>::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool |  | ||||||
| is_signed) const { auto val_reg = get_reg_for(jh, sizeof(val)*8); auto tmp = get_reg_for(jh, size); jh.cc.mov(val_reg, |  | ||||||
| val); if(is_signed) jh.cc.movsx(tmp, val_reg); else jh.cc.movzx(tmp,val_reg); return tmp; |  | ||||||
| } */ |  | ||||||
| template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> | template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> | ||||||
| inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) { | inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) { | ||||||
|     auto val_reg = get_reg_for(jh, sizeof(val) * 8); |     auto val_reg = get_reg_for(jh, sizeof(val) * 8, is_signed); | ||||||
|     jh.cc.mov(val_reg, val); |     jh.cc.mov(val_reg, val); | ||||||
|     return gen_ext(jh, val_reg, size, is_signed); |     return gen_ext(jh, val_reg, size, is_signed); | ||||||
| } | } | ||||||
| // explicit Gp size cast |  | ||||||
| inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) { | inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) { | ||||||
|     auto& cc = jh.cc; |     auto& cc = jh.cc; | ||||||
|     if(is_signed) { |     if(is_signed) { | ||||||
| @@ -398,7 +413,6 @@ inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signe | |||||||
|         throw std::runtime_error("Invalid size in gen_ext"); |         throw std::runtime_error("Invalid size in gen_ext"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint32_t length) { | inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint32_t length) { | ||||||
|     x86::Compiler& cc = jh.cc; |     x86::Compiler& cc = jh.cc; | ||||||
|     auto ret_reg = cc.newInt32(); |     auto ret_reg = cc.newInt32(); | ||||||
| @@ -447,31 +461,18 @@ inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint3 | |||||||
|     invokeNode->setArg(2, mem_type_reg); |     invokeNode->setArg(2, mem_type_reg); | ||||||
|     invokeNode->setArg(3, addr); |     invokeNode->setArg(3, addr); | ||||||
|     invokeNode->setArg(4, val_ptr); |     invokeNode->setArg(4, val_ptr); | ||||||
|  |     cc.cmp(ret_reg, 0); | ||||||
|  |     cc.jne(jh.trap_entry); | ||||||
|  |  | ||||||
|     cc.mov(val_reg, x86::ptr_64(val_ptr)); |     cc.mov(val_reg, x86::ptr_64(val_ptr)); | ||||||
|     cc.and_(val_reg, mask); |     cc.and_(val_reg, mask); | ||||||
|     cc.cmp(ret_reg, 0); |  | ||||||
|     cc.jne(jh.trap_entry); |  | ||||||
|     return val_reg; |     return val_reg; | ||||||
| } | } | ||||||
| inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length) { | inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length) { | ||||||
|     uint32_t length_val = 0; |     throw std::runtime_error("Invalid gen_read_mem"); | ||||||
|     auto length_ptr = jh.cc.newIntPtr(); |  | ||||||
|     jh.cc.mov(length_ptr, &length_val); |  | ||||||
|     jh.cc.mov(x86::ptr_32(length_ptr), length); |  | ||||||
|  |  | ||||||
|     return gen_read_mem(jh, type, addr, length); |  | ||||||
| } | } | ||||||
| inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length) { | inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length) { | ||||||
|     auto addr_reg = jh.cc.newInt64(); |     throw std::runtime_error("Invalid gen_read_mem"); | ||||||
|     jh.cc.mov(addr_reg, addr); |  | ||||||
|  |  | ||||||
|     uint32_t length_val = 0; |  | ||||||
|     auto length_ptr = jh.cc.newIntPtr(); |  | ||||||
|     jh.cc.mov(length_ptr, &length_val); |  | ||||||
|     jh.cc.mov(x86::ptr_32(length_ptr), length); |  | ||||||
|  |  | ||||||
|     return gen_read_mem(jh, type, addr_reg, length_val); |  | ||||||
| } | } | ||||||
| inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint32_t length) { | inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint32_t length) { | ||||||
|     auto addr_reg = jh.cc.newInt64(); |     auto addr_reg = jh.cc.newInt64(); | ||||||
| @@ -479,32 +480,38 @@ inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint | |||||||
|  |  | ||||||
|     return gen_read_mem(jh, type, addr_reg, length); |     return gen_read_mem(jh, type, addr_reg, length); | ||||||
| } | } | ||||||
| inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t val) { | inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t val, uint32_t length) { | ||||||
|     auto val_reg = jh.cc.newInt64(); |     auto val_reg = get_reg_for(jh, length * 8, true); | ||||||
|     jh.cc.mov(val_reg, val); |     jh.cc.mov(val_reg, val); | ||||||
|     gen_write_mem(jh, type, addr, val_reg); |     gen_write_mem(jh, type, addr, val_reg, length); | ||||||
| } | } | ||||||
| inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val) { | inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val, uint32_t length) { | ||||||
|     x86::Compiler& cc = jh.cc; |     x86::Compiler& cc = jh.cc; | ||||||
|  |     assert(val.size() == length); | ||||||
|     auto mem_type_reg = cc.newInt32(); |     auto mem_type_reg = cc.newInt32(); | ||||||
|     jh.cc.mov(mem_type_reg, type); |     jh.cc.mov(mem_type_reg, type); | ||||||
|     auto space_reg = cc.newInt32(); |     auto space_reg = cc.newInt32(); | ||||||
|     jh.cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL)); |     jh.cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL)); | ||||||
|     auto ret_reg = cc.newInt32(); |     auto ret_reg = cc.newInt32(); | ||||||
|     InvokeNode* invokeNode; |     InvokeNode* invokeNode; | ||||||
|  |     switch(length) { | ||||||
|     if(val.isGpb()) { |     case 1: | ||||||
|         cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>()); |         cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>()); | ||||||
|     } else if(val.isGpw()) { |  | ||||||
|         cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>()); |  | ||||||
|     } else if(val.isGpd()) { |  | ||||||
|         cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>()); |  | ||||||
|     } else if(val.isGpq()) { |  | ||||||
|         cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>()); |  | ||||||
|     } else |  | ||||||
|         throw std::runtime_error("Invalid register size in gen_write_mem"); |  | ||||||
|  |  | ||||||
|  |         break; | ||||||
|  |     case 2: | ||||||
|  |         cc.invoke(&invokeNode, &write_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint16_t>()); | ||||||
|  |         break; | ||||||
|  |     case 4: | ||||||
|  |         cc.invoke(&invokeNode, &write_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint32_t>()); | ||||||
|  |         break; | ||||||
|  |     case 8: | ||||||
|  |         cc.invoke(&invokeNode, &write_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>()); | ||||||
|  |  | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         throw std::runtime_error("Invalid register size in gen_ext"); | ||||||
|  |     } | ||||||
|     invokeNode->setRet(0, ret_reg); |     invokeNode->setRet(0, ret_reg); | ||||||
|     invokeNode->setArg(0, jh.arch_if_ptr); |     invokeNode->setArg(0, jh.arch_if_ptr); | ||||||
|     invokeNode->setArg(1, space_reg); |     invokeNode->setArg(1, space_reg); | ||||||
| @@ -515,16 +522,16 @@ inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp | |||||||
|     cc.cmp(ret_reg, 0); |     cc.cmp(ret_reg, 0); | ||||||
|     cc.jne(jh.trap_entry); |     cc.jne(jh.trap_entry); | ||||||
| } | } | ||||||
| inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val) { | inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val, uint32_t length) { | ||||||
|     auto addr_reg = jh.cc.newInt64(); |     auto addr_reg = jh.cc.newUInt64(); | ||||||
|     jh.cc.mov(addr_reg, addr); |     jh.cc.mov(addr_reg, addr); | ||||||
|     gen_write_mem(jh, type, addr_reg, val); |     gen_write_mem(jh, type, addr_reg, val, length); | ||||||
| } | } | ||||||
| inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val) { | inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val, uint32_t length) { | ||||||
|     auto val_reg = jh.cc.newInt64(); |     auto val_reg = get_reg_for(jh, length * 8, true); | ||||||
|     jh.cc.mov(val_reg, val); |     jh.cc.mov(val_reg, val); | ||||||
|  |  | ||||||
|     auto addr_reg = jh.cc.newInt64(); |     auto addr_reg = jh.cc.newUInt64(); | ||||||
|     jh.cc.mov(addr_reg, addr); |     jh.cc.mov(addr_reg, addr); | ||||||
|     gen_write_mem(jh, type, addr_reg, val_reg); |     gen_write_mem(jh, type, addr_reg, val_reg, length); | ||||||
| } | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user