Compare commits
No commits in common. "58fb815f329b92fc8cb71ebaa9ccbc0db8e23620" and "b76c5bf0d65b0d3a93e24d4c71dbf8ed220c6366" have entirely different histories.
58fb815f32
...
b76c5bf0d6
@ -174,17 +174,9 @@ private:
|
|||||||
* end opcode definitions
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
|
continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
cc.comment(fmt::format("illegal_intruction{:#x}:",pc.val).c_str());
|
|
||||||
this->gen_sync(jh, PRE_SYNC, instr_descr.size());
|
|
||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
|
||||||
gen_instr_prologue(jh);
|
|
||||||
cc.comment("//behavior:");
|
|
||||||
gen_instr_epilogue(jh);
|
|
||||||
this->gen_sync(jh, POST_SYNC, instr_descr.size());
|
|
||||||
return BRANCH;
|
return BRANCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
//decoding functionality
|
//decoding functionality
|
||||||
|
|
||||||
void populate_decoding_tree(decoding_tree_node* root){
|
void populate_decoding_tree(decoding_tree_node* root){
|
||||||
|
@ -99,11 +99,16 @@ protected:
|
|||||||
std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override;
|
std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override;
|
||||||
|
|
||||||
void gen_leave_behavior(BasicBlock *leave_blk) override;
|
void gen_leave_behavior(BasicBlock *leave_blk) override;
|
||||||
|
|
||||||
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
||||||
|
|
||||||
void gen_leave_trap(unsigned lvl);
|
void gen_leave_trap(unsigned lvl);
|
||||||
|
|
||||||
void gen_wait(unsigned type);
|
void gen_wait(unsigned type);
|
||||||
|
|
||||||
void gen_trap_behavior(BasicBlock *) override;
|
void gen_trap_behavior(BasicBlock *) override;
|
||||||
void gen_instr_epilogue(BasicBlock *bb);
|
|
||||||
|
void gen_trap_check(BasicBlock *bb);
|
||||||
|
|
||||||
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
||||||
return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false);
|
return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false);
|
||||||
@ -157,22 +162,20 @@ private:
|
|||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
|
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
|
||||||
|
bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val));
|
||||||
|
this->gen_sync(PRE_SYNC,${idx});
|
||||||
uint64_t PC = pc.val;
|
uint64_t PC = pc.val;
|
||||||
<%instr.fields.eachLine{%>${it}
|
<%instr.fields.eachLine{%>${it}
|
||||||
<%}%>if(this->disass_enabled){
|
<%}%>if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||||
${it}<%}%>
|
${it}<%}%>
|
||||||
}
|
}
|
||||||
bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val));
|
|
||||||
this->gen_sync(PRE_SYNC,${idx});
|
|
||||||
auto cur_pc_val = this->gen_const(32,pc.val);
|
auto cur_pc_val = this->gen_const(32,pc.val);
|
||||||
pc=pc+ ${instr.length/8};
|
pc=pc+ ${instr.length/8};
|
||||||
this->gen_set_pc(pc, traits::NEXT_PC);
|
this->gen_set_pc(pc, traits::NEXT_PC);
|
||||||
|
|
||||||
/*generate behavior*/
|
|
||||||
<%instr.behavior.eachLine{%>${it}
|
<%instr.behavior.eachLine{%>${it}
|
||||||
<%}%>
|
<%}%>
|
||||||
this->gen_instr_epilogue(bb);
|
this->gen_trap_check(bb);
|
||||||
this->gen_sync(POST_SYNC, ${idx});
|
this->gen_sync(POST_SYNC, ${idx});
|
||||||
this->builder.CreateBr(bb);
|
this->builder.CreateBr(bb);
|
||||||
return returnValue;
|
return returnValue;
|
||||||
@ -192,7 +195,7 @@ private:
|
|||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
this->gen_raise_trap(0, 2); // illegal instruction trap
|
this->gen_raise_trap(0, 2); // illegal instruction trap
|
||||||
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
||||||
this->gen_instr_epilogue(this->leave_blk);
|
this->gen_trap_check(this->leave_blk);
|
||||||
return std::make_tuple(BRANCH, nullptr);
|
return std::make_tuple(BRANCH, nullptr);
|
||||||
}
|
}
|
||||||
//decoding functionality
|
//decoding functionality
|
||||||
@ -298,21 +301,18 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
|||||||
return (this->*f)(pc, instr, this_block);
|
return (this->*f)(pc, instr, this_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
|
||||||
void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
|
|
||||||
this->builder.SetInsertPoint(leave_blk);
|
this->builder.SetInsertPoint(leave_blk);
|
||||||
this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false));
|
this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
||||||
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
|
||||||
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
|
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
|
||||||
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
|
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
|
||||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
|
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
||||||
void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
|
||||||
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
|
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
|
||||||
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
|
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
|
||||||
auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8);
|
auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8);
|
||||||
@ -320,14 +320,12 @@ void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
|||||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
|
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits::LAST_BRANCH), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
||||||
void vm_impl<ARCH>::gen_wait(unsigned type) {
|
|
||||||
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
|
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
|
||||||
this->builder.CreateCall(this->mod->getFunction("wait"), args);
|
this->builder.CreateCall(this->mod->getFunction("wait"), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
|
||||||
void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
|
|
||||||
this->builder.SetInsertPoint(trap_blk);
|
this->builder.SetInsertPoint(trap_blk);
|
||||||
this->gen_sync(POST_SYNC, -1); //TODO get right InstrId
|
this->gen_sync(POST_SYNC, -1); //TODO get right InstrId
|
||||||
auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
||||||
@ -340,8 +338,7 @@ void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
|
|||||||
this->builder.CreateRet(trap_addr_val);
|
this->builder.CreateRet(trap_addr_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
|
||||||
void vm_impl<ARCH>::gen_instr_epilogue(BasicBlock *bb) {
|
|
||||||
auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb);
|
auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb);
|
||||||
auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
|
||||||
this->gen_cond_branch(this->builder.CreateICmp(
|
this->gen_cond_branch(this->builder.CreateICmp(
|
||||||
|
@ -292,7 +292,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
|||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
|
||||||
tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id);
|
tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id);
|
||||||
tu.store(traits::NEXT_PC, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
|
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
|
||||||
|
@ -2826,11 +2826,11 @@ private:
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
auto res = gen_ext(jh,
|
auto res = gen_ext(jh,
|
||||||
(gen_operation(jh, imul, gen_ext(jh,
|
(gen_operation(jh, imul,
|
||||||
gen_ext(jh,
|
gen_ext(jh,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs1), 32, true), 64, true), gen_ext(jh,
|
gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 32, true), 64, true),
|
||||||
gen_ext(jh,
|
gen_ext(jh,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs2), 32, true), 64, true))
|
gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2), 32, true), 64, true))
|
||||||
), 64, true);
|
), 64, true);
|
||||||
if(rd!=0){
|
if(rd!=0){
|
||||||
cc.mov(get_ptr_for(jh, traits::X0+ rd),
|
cc.mov(get_ptr_for(jh, traits::X0+ rd),
|
||||||
@ -4340,7 +4340,7 @@ private:
|
|||||||
cc.comment("//behavior:");
|
cc.comment("//behavior:");
|
||||||
/*generate behavior*/
|
/*generate behavior*/
|
||||||
if(rs1&&rs1<static_cast<uint32_t>(traits::RFS)){
|
if(rs1&&rs1<static_cast<uint32_t>(traits::RFS)){
|
||||||
auto PC_val_v = gen_operation(jh, band, load_reg_from_mem(jh, traits::X0 + rs1%static_cast<uint32_t>(traits::RFS)), ~ 1)
|
auto PC_val_v = gen_operation(jh, band, load_reg_from_mem(jh, traits::X0 + rs1%static_cast<uint32_t>(traits::RFS)), ~ 0x1)
|
||||||
;
|
;
|
||||||
cc.mov(jh.next_pc, PC_val_v);
|
cc.mov(jh.next_pc, PC_val_v);
|
||||||
cc.mov(get_ptr_for(jh, traits::LAST_BRANCH), 32U);
|
cc.mov(get_ptr_for(jh, traits::LAST_BRANCH), 32U);
|
||||||
@ -4474,7 +4474,7 @@ private:
|
|||||||
auto new_pc = load_reg_from_mem(jh, traits::X0 + rs1);
|
auto new_pc = load_reg_from_mem(jh, traits::X0 + rs1);
|
||||||
cc.mov(get_ptr_for(jh, traits::X0+ 1),
|
cc.mov(get_ptr_for(jh, traits::X0+ 1),
|
||||||
(uint32_t)(PC+ 2));
|
(uint32_t)(PC+ 2));
|
||||||
auto PC_val_v = gen_operation(jh, band, new_pc, ~ 1)
|
auto PC_val_v = gen_operation(jh, band, new_pc, ~ 0x1)
|
||||||
;
|
;
|
||||||
cc.mov(jh.next_pc, PC_val_v);
|
cc.mov(jh.next_pc, PC_val_v);
|
||||||
cc.mov(get_ptr_for(jh, traits::LAST_BRANCH), 32U);
|
cc.mov(get_ptr_for(jh, traits::LAST_BRANCH), 32U);
|
||||||
@ -4607,14 +4607,7 @@ private:
|
|||||||
* end opcode definitions
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
|
continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
|
||||||
x86::Compiler& cc = jh.cc;
|
|
||||||
cc.comment(fmt::format("illegal_intruction{:#x}:",pc.val).c_str());
|
|
||||||
this->gen_sync(jh, PRE_SYNC, instr_descr.size());
|
|
||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
|
||||||
gen_instr_prologue(jh);
|
|
||||||
cc.comment("//behavior:");
|
|
||||||
gen_instr_epilogue(jh);
|
|
||||||
this->gen_sync(jh, POST_SYNC, instr_descr.size());
|
|
||||||
return BRANCH;
|
return BRANCH;
|
||||||
}
|
}
|
||||||
//decoding functionality
|
//decoding functionality
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2171,7 +2171,7 @@ private:
|
|||||||
gen_set_pc(tu, pc, traits::NEXT_PC);
|
gen_set_pc(tu, pc, traits::NEXT_PC);
|
||||||
tu.open_scope();
|
tu.open_scope();
|
||||||
tu.write_mem(traits::FENCE, static_cast<uint32_t>(traits:: fencei), tu.constant(imm,16));
|
tu.write_mem(traits::FENCE, static_cast<uint32_t>(traits:: fencei), tu.constant(imm,16));
|
||||||
auto returnValue = std::make_tuple(FLUSH);
|
auto returnValue = std::make_tuple(CONT);
|
||||||
|
|
||||||
tu.close_scope();
|
tu.close_scope();
|
||||||
gen_trap_check(tu);
|
gen_trap_check(tu);
|
||||||
@ -3303,9 +3303,10 @@ private:
|
|||||||
pc=pc+ 2;
|
pc=pc+ 2;
|
||||||
gen_set_pc(tu, pc, traits::NEXT_PC);
|
gen_set_pc(tu, pc, traits::NEXT_PC);
|
||||||
tu.open_scope();
|
tu.open_scope();
|
||||||
if(rs1&&rs1<static_cast<uint32_t>(traits:: RFS)){ auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(
|
if(rs1&&rs1<static_cast<uint32_t>(traits:: RFS)) {
|
||||||
|
auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(
|
||||||
tu.load(rs1%static_cast<uint32_t>(traits:: RFS)+ traits::X0, 0),
|
tu.load(rs1%static_cast<uint32_t>(traits:: RFS)+ traits::X0, 0),
|
||||||
tu.constant(~ 1,32)),32);
|
tu.constant(~ 0x1,8)),32);
|
||||||
tu.store(traits::NEXT_PC, PC_val_v);
|
tu.store(traits::NEXT_PC, PC_val_v);
|
||||||
tu.store(traits::LAST_BRANCH, tu.constant(2U, 2));
|
tu.store(traits::LAST_BRANCH, tu.constant(2U, 2));
|
||||||
}
|
}
|
||||||
@ -3405,7 +3406,7 @@ private:
|
|||||||
tu.constant((uint32_t)(PC+ 2),32));
|
tu.constant((uint32_t)(PC+ 2),32));
|
||||||
auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(
|
auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(
|
||||||
new_pc,
|
new_pc,
|
||||||
tu.constant(~ 1,32)),32);
|
tu.constant(~ 0x1,8)),32);
|
||||||
tu.store(traits::NEXT_PC, PC_val_v);
|
tu.store(traits::NEXT_PC, PC_val_v);
|
||||||
tu.store(traits::LAST_BRANCH, tu.constant(2U, 2));
|
tu.store(traits::LAST_BRANCH, tu.constant(2U, 2));
|
||||||
}
|
}
|
||||||
@ -3611,7 +3612,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
|||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
|
||||||
tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id);
|
tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id);
|
||||||
tu.store(traits::NEXT_PC, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
|
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
|
||||||
|
Loading…
Reference in New Issue
Block a user