Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop

This commit is contained in:
gabriel
2024-05-31 09:42:13 +02:00
18 changed files with 3310 additions and 2405 deletions

View File

@ -1,537 +0,0 @@
x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx) {
x86::Gp tmp_ptr = jh.cc.newUIntPtr("tmp_ptr");
jh.cc.mov(tmp_ptr, jh.regs_base_ptr);
jh.cc.add(tmp_ptr, traits::reg_byte_offsets[idx]);
switch(traits::reg_bit_widths[idx]) {
case 8:
return x86::ptr_8(tmp_ptr);
case 16:
return x86::ptr_16(tmp_ptr);
case 32:
return x86::ptr_32(tmp_ptr);
case 64:
return x86::ptr_64(tmp_ptr);
default:
throw std::runtime_error("Invalid reg size in get_reg_ptr");
}
}
x86::Gp get_reg_for(jit_holder& jh, unsigned idx) {
// TODO can check for regs in jh and return them instead of creating new ones
switch(traits::reg_bit_widths[idx]) {
case 8:
return jh.cc.newInt8();
case 16:
return jh.cc.newInt16();
case 32:
return jh.cc.newInt32();
case 64:
return jh.cc.newInt64();
default:
throw std::runtime_error("Invalid reg size in get_reg_ptr");
}
}
x86::Gp get_reg_for(jit_holder& jh, unsigned size, bool is_signed) {
if(is_signed)
switch(size) {
case 8:
return jh.cc.newInt8();
case 16:
return jh.cc.newInt16();
case 32:
return jh.cc.newInt32();
case 64:
return jh.cc.newInt64();
default:
throw std::runtime_error("Invalid reg size in get_reg_ptr");
}
else
switch(size) {
case 8:
return jh.cc.newUInt8();
case 16:
return jh.cc.newUInt16();
case 32:
return jh.cc.newUInt32();
case 64:
return jh.cc.newUInt64();
default:
throw std::runtime_error("Invalid reg size in get_reg_ptr");
}
}
inline x86::Gp load_reg_from_mem(jit_holder& jh, unsigned idx) {
auto ptr = get_reg_ptr(jh, idx);
auto reg = get_reg_for(jh, idx);
jh.cc.mov(reg, ptr);
return reg;
}
inline void write_reg_to_mem(jit_holder& jh, x86::Gp reg, unsigned idx) {
auto ptr = get_reg_ptr(jh, idx);
jh.cc.mov(ptr, reg);
}
void gen_instr_prologue(jit_holder& jh, addr_t pc) {
auto& cc = jh.cc;
cc.comment("\n//(*icount)++;");
cc.inc(get_reg_ptr(jh, traits::ICOUNT));
cc.comment("\n//*pc=*next_pc;");
cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc);
cc.comment("\n//*trap_state=*pending_trap;");
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.mov(jh.next_pc, pc);
}
void gen_instr_epilogue(jit_holder& jh) {
auto& cc = jh.cc;
cc.comment("\n//if(*trap_state!=0) goto trap_entry;");
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.cmp(current_trap_state, 0);
cc.jne(jh.trap_entry);
// TODO: Does not need to be done for every instruction, only when needed
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);
}
void gen_block_prologue(jit_holder& jh) override {
jh.pc = load_reg_from_mem(jh, traits::PC);
jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC);
}
void gen_block_epilogue(jit_holder& jh) override {
x86::Compiler& cc = jh.cc;
cc.comment("\n//return *next_pc;");
cc.ret(jh.next_pc);
cc.bind(jh.trap_entry);
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);
cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE));
x86::Gp current_pc = get_reg_for(jh, traits::PC);
cc.mov(current_pc, get_reg_ptr(jh, traits::PC));
x86::Gp instr = cc.newInt32("instr");
cc.mov(instr, 0); // this is not correct
cc.comment("\n//enter trap call;");
InvokeNode* call_enter_trap;
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(1, current_trap_state);
call_enter_trap->setArg(2, current_pc);
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.mov(get_reg_ptr(jh, traits::LAST_BRANCH), std::numeric_limits<uint32_t>::max());
cc.comment("\n//return *next_pc;");
cc.ret(jh.next_pc);
}
/*
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;
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 };
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value || std::is_same<T, x86::Gp>::value>>
x86::Gp gen_operation(jit_holder& jh, operation op, x86::Gp a, T b) {
x86::Compiler& cc = jh.cc;
switch(op) {
case add: {
cc.add(a, b);
break;
}
case sub: {
cc.sub(a, b);
break;
}
case band: {
cc.and_(a, b);
break;
}
case bor: {
cc.or_(a, b);
break;
}
case bxor: {
cc.xor_(a, b);
break;
}
case shl: {
cc.shl(a, b);
break;
}
case sar: {
cc.sar(a, b);
break;
}
case shr: {
cc.shr(a, b);
break;
}
default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (operation)", op));
}
return a;
}
enum three_operand_operation { imul, mul, idiv, div, srem, urem };
x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, x86::Gp b) {
x86::Compiler& cc = jh.cc;
switch(op) {
case imul: {
x86::Gp dummy = cc.newInt64();
cc.imul(dummy, a.r64(), b.r64());
return a;
}
case mul: {
x86::Gp dummy = cc.newInt64();
cc.mul(dummy, a.r64(), b.r64());
return a;
}
case idiv: {
x86::Gp dummy = cc.newInt64();
cc.mov(dummy, 0);
cc.idiv(dummy, a.r64(), b.r64());
return a;
}
case div: {
x86::Gp dummy = cc.newInt64();
cc.mov(dummy, 0);
cc.div(dummy, a.r64(), b.r64());
return a;
}
case srem: {
x86::Gp rem = cc.newInt32();
cc.mov(rem, 0);
auto a_reg = cc.newInt32();
cc.mov(a_reg, a.r32());
cc.idiv(rem, a_reg, b.r32());
return rem;
}
case urem: {
x86::Gp rem = cc.newInt32();
cc.mov(rem, 0);
auto a_reg = cc.newInt32();
cc.mov(a_reg, a.r32());
cc.div(rem, a_reg, b.r32());
return rem;
}
default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (three_operand)", op));
}
return a;
}
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, T b) {
x86::Gp b_reg = jh.cc.newInt32();
/* switch(a.size()){
case 1: b_reg = jh.cc.newInt8(); break;
case 2: b_reg = jh.cc.newInt16(); break;
case 4: b_reg = jh.cc.newInt32(); break;
case 8: b_reg = jh.cc.newInt64(); break;
default: throw std::runtime_error(fmt::format("Invalid size ({}) in gen operation", a.size()));
} */
jh.cc.mov(b_reg, b);
return gen_operation(jh, op, a, b_reg);
}
enum comparison_operation { land, lor, eq, ne, lt, ltu, gt, gtu, lte, lteu, gte, gteu };
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value || std::is_same<T, x86::Gp>::value>>
x86::Gp gen_operation(jit_holder& jh, comparison_operation op, x86::Gp a, T b) {
x86::Compiler& cc = jh.cc;
x86::Gp tmp = cc.newInt8();
cc.mov(tmp, 1);
Label label_then = cc.newLabel();
cc.cmp(a, b);
switch(op) {
case eq:
cc.je(label_then);
break;
case ne:
cc.jne(label_then);
break;
case lt:
cc.jl(label_then);
break;
case ltu:
cc.jb(label_then);
break;
case gt:
cc.jg(label_then);
break;
case gtu:
cc.ja(label_then);
break;
case lte:
cc.jle(label_then);
break;
case lteu:
cc.jbe(label_then);
break;
case gte:
cc.jge(label_then);
break;
case gteu:
cc.jae(label_then);
break;
case land: {
Label label_false = cc.newLabel();
cc.cmp(a, 0);
cc.je(label_false);
auto b_reg = cc.newInt8();
cc.mov(b_reg, b);
cc.cmp(b_reg, 0);
cc.je(label_false);
cc.jmp(label_then);
cc.bind(label_false);
break;
}
case lor: {
cc.cmp(a, 0);
cc.jne(label_then);
auto b_reg = cc.newInt8();
cc.mov(b_reg, b);
cc.cmp(b_reg, 0);
cc.jne(label_then);
break;
}
default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (comparison)", op));
}
cc.mov(tmp, 0);
cc.bind(label_then);
return tmp;
}
enum binary_operation { lnot, inc, dec, bnot, neg };
x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a) {
x86::Compiler& cc = jh.cc;
switch(op) {
case lnot:
throw std::runtime_error("Current operation not supported in gen_operation(lnot)");
case inc: {
cc.inc(a);
break;
}
case dec: {
cc.dec(a);
break;
}
case bnot: {
cc.not_(a);
break;
}
case neg: {
cc.neg(a);
break;
}
default:
throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (unary)", op));
}
return a;
}
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) {
auto val_reg = get_reg_for(jh, sizeof(val) * 8, is_signed);
jh.cc.mov(val_reg, val);
return gen_ext(jh, val_reg, size, is_signed);
}
inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) {
auto& cc = jh.cc;
if(is_signed) {
switch(val.size()) {
case 1:
cc.cbw(val);
break;
case 2:
cc.cwde(val);
break;
case 4:
cc.cdqe(val);
break;
case 8:
break;
default:
throw std::runtime_error("Invalid register size in gen_ext");
}
}
switch(size) {
case 8:
cc.and_(val, std::numeric_limits<uint8_t>::max());
return val.r8();
case 16:
cc.and_(val, std::numeric_limits<uint16_t>::max());
return val.r16();
case 32:
cc.and_(val, std::numeric_limits<uint32_t>::max());
return val.r32();
case 64:
cc.and_(val, std::numeric_limits<uint64_t>::max());
return val.r64();
case 128:
return val.r64();
default:
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) {
x86::Compiler& cc = jh.cc;
auto ret_reg = cc.newInt32();
auto mem_type_reg = cc.newInt32();
cc.mov(mem_type_reg, type);
auto space_reg = cc.newInt32();
cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL));
auto val_ptr = cc.newUIntPtr();
cc.mov(val_ptr, read_mem_buf);
InvokeNode* invokeNode;
uint64_t mask = 0;
x86::Gp val_reg = cc.newInt64();
switch(length) {
case 1: {
cc.invoke(&invokeNode, &read_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
mask = std::numeric_limits<uint8_t>::max();
break;
}
case 2: {
cc.invoke(&invokeNode, &read_mem2, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
mask = std::numeric_limits<uint16_t>::max();
break;
}
case 4: {
cc.invoke(&invokeNode, &read_mem4, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
mask = std::numeric_limits<uint32_t>::max();
break;
}
case 8: {
cc.invoke(&invokeNode, &read_mem8, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uintptr_t>());
mask = std::numeric_limits<uint64_t>::max();
break;
}
default:
throw std::runtime_error(fmt::format("Invalid length ({}) in gen_read_mem", length));
}
invokeNode->setRet(0, ret_reg);
invokeNode->setArg(0, jh.arch_if_ptr);
invokeNode->setArg(1, space_reg);
invokeNode->setArg(2, mem_type_reg);
invokeNode->setArg(3, addr);
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.and_(val_reg, mask);
return val_reg;
}
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length) {
throw std::runtime_error("Invalid gen_read_mem");
}
inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length) {
throw std::runtime_error("Invalid gen_read_mem");
}
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();
jh.cc.mov(addr_reg, addr);
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, uint32_t length) {
auto val_reg = get_reg_for(jh, length * 8, true);
jh.cc.mov(val_reg, val);
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, uint32_t length) {
x86::Compiler& cc = jh.cc;
assert(val.size() == length);
auto mem_type_reg = cc.newInt32();
jh.cc.mov(mem_type_reg, type);
auto space_reg = cc.newInt32();
jh.cc.mov(space_reg, static_cast<uint16_t>(iss::address_type::VIRTUAL));
auto ret_reg = cc.newInt32();
InvokeNode* invokeNode;
switch(length) {
case 1:
cc.invoke(&invokeNode, &write_mem1, FuncSignatureT<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, uint8_t>());
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->setArg(0, jh.arch_if_ptr);
invokeNode->setArg(1, space_reg);
invokeNode->setArg(2, mem_type_reg);
invokeNode->setArg(3, addr);
invokeNode->setArg(4, val);
cc.cmp(ret_reg, 0);
cc.jne(jh.trap_entry);
}
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.newUInt64();
jh.cc.mov(addr_reg, addr);
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, uint32_t length) {
auto val_reg = get_reg_for(jh, length * 8, true);
jh.cc.mov(val_reg, val);
auto addr_reg = jh.cc.newUInt64();
jh.cc.mov(addr_reg, addr);
gen_write_mem(jh, type, addr_reg, val_reg, length);
}

File diff suppressed because it is too large Load Diff

View File

@ -429,7 +429,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)(*PC + (int32_t)imm);
*(X+rd) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int32_t)imm ));
}
}
}
@ -459,9 +459,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)(*PC + 4);
*(X+rd) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 4 ));
}
*NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int32_t)sext<21>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -489,13 +489,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
uint32_t addr_mask = (uint32_t)- 2;
uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & addr_mask);
uint32_t new_pc = (uint32_t)(((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) )) & (int64_t)(addr_mask ));
if(new_pc % traits::INSTR_ALIGNMENT) {
raise(0, 0);
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)(*PC + 4);
*(X+rd) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 4 ));
}
*NEXT_PC = new_pc;
this->core.reg.last_branch = 1;
@ -525,11 +525,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(*(X+rs1) == *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) {
if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0);
}
else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -558,11 +558,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(*(X+rs1) != *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) {
if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0);
}
else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -591,11 +591,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) {
if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0);
}
else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -624,11 +624,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) {
if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0);
}
else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -657,11 +657,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(*(X+rs1) < *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) {
if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0);
}
else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -690,11 +690,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(*(X+rs1) >= *(X+rs2)) {
if(imm % traits::INSTR_ALIGNMENT) {
if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) {
raise(0, 0);
}
else {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -722,7 +722,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
int8_t res_27 = super::template read_mem<int8_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
int8_t res = (int8_t)res_27;
@ -753,7 +753,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
int16_t res_28 = super::template read_mem<int16_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
int16_t res = (int16_t)res_28;
@ -784,7 +784,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
int32_t res_29 = super::template read_mem<int32_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
int32_t res = (int32_t)res_29;
@ -815,7 +815,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
uint8_t res_30 = super::template read_mem<uint8_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
uint8_t res = res_30;
@ -846,7 +846,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t load_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
uint16_t res_31 = super::template read_mem<uint16_t>(traits::MEM, load_address);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
uint16_t res = res_31;
@ -877,7 +877,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t store_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
super::template write_mem<uint8_t>(traits::MEM, store_address, (uint8_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
}
@ -904,7 +904,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t store_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
super::template write_mem<uint16_t>(traits::MEM, store_address, (uint16_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
}
@ -931,7 +931,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
uint32_t store_address = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
super::template write_mem<uint32_t>(traits::MEM, store_address, (uint32_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
}
@ -959,7 +959,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm));
*(X+rd) = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) ));
}
}
}
@ -1202,7 +1202,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2));
*(X+rd) = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)(*(X+rs2) ));
}
}
}
@ -1229,7 +1229,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2));
*(X+rd) = (uint32_t)((uint64_t)(*(X+rs1) ) - (uint64_t)(*(X+rs2) ));
}
}
}
@ -1256,7 +1256,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1));
*(X+rd) = *(X+rs1) << ((uint64_t)(*(X+rs2) ) & ((uint64_t)(traits::XLEN ) - (uint64_t)( 1 )));
}
}
}
@ -1364,7 +1364,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1));
*(X+rd) = *(X+rs1) >> ((uint64_t)(*(X+rs2) ) & ((uint64_t)(traits::XLEN ) - (uint64_t)( 1 )));
}
}
}
@ -1391,7 +1391,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)));
*(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> ((uint64_t)(*(X+rs2) ) & ((uint64_t)(traits::XLEN ) - (uint64_t)( 1 ))));
}
}
}
@ -1772,7 +1772,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2));
int64_t res = (int64_t)((int32_t)*(X+rs1) ) * (int64_t)((int32_t)*(X+rs2) );
if(rd != 0) {
*(X+rd) = (uint32_t)res;
}
@ -1800,7 +1800,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2));
int64_t res = (int64_t)((int32_t)*(X+rs1) ) * (int64_t)((int32_t)*(X+rs2) );
if(rd != 0) {
*(X+rd) = (uint32_t)(res >> traits::XLEN);
}
@ -1828,7 +1828,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2));
int64_t res = (int64_t)((int32_t)*(X+rs1) ) * (int64_t)(*(X+rs2) );
if(rd != 0) {
*(X+rd) = (uint32_t)(res >> traits::XLEN);
}
@ -1856,7 +1856,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2));
uint64_t res = (uint64_t)(*(X+rs1) ) * (uint64_t)(*(X+rs2) );
if(rd != 0) {
*(X+rd) = (uint32_t)(res >> traits::XLEN);
}
@ -1888,7 +1888,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
int32_t divisor = (int32_t)*(X+rs2);
if(rd != 0) {
if(divisor != 0) {
uint32_t MMIN = ((uint32_t)1) << (traits::XLEN - 1);
uint32_t MMIN = ((uint32_t)1) << ((uint64_t)(traits::XLEN ) - (uint64_t)(1 ));
if(*(X+rs1) == MMIN && divisor == - 1) {
*(X+rd) = MMIN;
}
@ -1926,7 +1926,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
else {
if(*(X+rs2) != 0) {
if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rs1) / *(X+rs2));
*(X+rd) = *(X+rs1) / *(X+rs2);
}
}
else {
@ -1959,7 +1959,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(*(X+rs2) != 0) {
uint32_t MMIN = (uint32_t)1 << (traits::XLEN - 1);
uint32_t MMIN = (uint32_t)1 << ((uint64_t)(traits::XLEN ) - (uint64_t)(1 ));
if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) {
if(rd != 0) {
*(X+rd) = 0;
@ -1967,7 +1967,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2));
*(X+rd) = ((uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)));
}
}
}
@ -2030,7 +2030,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction
{
if(imm) {
*(X+rd + 8) = (uint32_t)(*(X+2) + imm);
*(X+rd + 8) = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)(imm ));
}
else {
raise(0, 2);
@ -2054,7 +2054,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2;
// execute instruction
{
uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm);
uint32_t offs = (uint32_t)((uint64_t)(*(X+rs1 + 8) ) + (uint64_t)(uimm ));
int32_t res_38 = super::template read_mem<int32_t>(traits::MEM, offs);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
*(X+rd + 8) = (uint32_t)(int32_t)res_38;
@ -2077,7 +2077,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2;
// execute instruction
{
uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm);
uint32_t offs = (uint32_t)((uint64_t)(*(X+rs1 + 8) ) + (uint64_t)(uimm ));
super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2 + 8));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
}
@ -2103,7 +2103,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rs1 != 0) {
*(X+rs1) = (uint32_t)(*(X+rs1) + (int8_t)sext<6>(imm));
*(X+rs1) = (uint32_t)((uint64_t)(*(X+rs1) ) + (uint64_t)((int8_t)sext<6>(imm) ));
}
}
}
@ -2136,8 +2136,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2;
// execute instruction
{
*(X+1) = (uint32_t)(*PC + 2);
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm));
*(X+1) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 2 ));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<12>(imm) ));
this->core.reg.last_branch = 1;
}
break;
@ -2207,7 +2207,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction
{
if(nzimm) {
*(X+2) = (uint32_t)(*(X+2) + (int16_t)sext<10>(nzimm));
*(X+2) = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)((int16_t)sext<10>(nzimm) ));
}
else {
raise(0, 2);
@ -2289,7 +2289,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2;
// execute instruction
{
*(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (int8_t)sext<6>(imm));
*(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (uint32_t)((int8_t)sext<6>(imm) ));
}
break;
}// @suppress("No break at end of case")
@ -2308,7 +2308,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2;
// execute instruction
{
*(X+rd + 8) = (uint32_t)(*(X+rd + 8) - *(X+rs2 + 8));
*(X+rd + 8) = (uint32_t)((uint64_t)(*(X+rd + 8) ) - (uint64_t)(*(X+rs2 + 8) ));
}
break;
}// @suppress("No break at end of case")
@ -2382,7 +2382,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 2;
// execute instruction
{
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<12>(imm) ));
this->core.reg.last_branch = 1;
}
break;
@ -2403,7 +2403,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction
{
if(*(X+rs1 + 8) == 0) {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<9>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -2425,7 +2425,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction
{
if(*(X+rs1 + 8) != 0) {
*NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm));
*NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<9>(imm) ));
this->core.reg.last_branch = 1;
}
}
@ -2476,7 +2476,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t offs = (uint32_t)(*(X+2) + uimm);
uint32_t offs = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)(uimm ));
int32_t res_39 = super::template read_mem<int32_t>(traits::MEM, offs);
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
*(X+rd) = (uint32_t)(int32_t)res_39;
@ -2525,7 +2525,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction
{
if(rs1 && rs1 < traits::RFS) {
*NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1;
*NEXT_PC = *(X+(uint32_t)(rs1 ) % traits::RFS) & (uint32_t)(~ 0x1 );
this->core.reg.last_branch = 1;
}
else {
@ -2567,7 +2567,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)(*(X+rd) + *(X+rs2));
*(X+rd) = (uint32_t)((uint64_t)(*(X+rd) ) + (uint64_t)(*(X+rs2) ));
}
}
}
@ -2592,8 +2592,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
}
else {
uint32_t new_pc = *(X+rs1);
*(X+1) = (uint32_t)(*PC + 2);
*NEXT_PC = new_pc & ~ 0x1;
*(X+1) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)( 2 ));
*NEXT_PC = new_pc & (uint32_t)(~ 0x1 );
this->core.reg.last_branch = 1;
}
}
@ -2631,7 +2631,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
raise(0, 2);
}
else {
uint32_t offs = (uint32_t)(*(X+2) + uimm);
uint32_t offs = (uint32_t)((uint64_t)(*(X+2) ) + (uint64_t)(uimm ));
super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2));
if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff