diff --git a/riscvm/opcodes.h b/riscvm/opcodes.h index 6e71d03..8d53421 100644 --- a/riscvm/opcodes.h +++ b/riscvm/opcodes.h @@ -62,7 +62,7 @@ enum RV64_Imm64 rv64_imm64_slti = 0b00010, rv64_imm64_sltiu = 0b00011, rv64_imm64_xori = 0b00100, - rv64_imm64_srli = 0b00101, + rv64_imm64_srxi = 0b00101, // srli/srai rv64_imm64_ori = 0b00110, rv64_imm64_andi = 0b00111, }; @@ -71,7 +71,7 @@ enum RV64_Imm32 { rv64_imm32_addiw = 0b00000, rv64_imm32_slliw = 0b00001, - rv64_imm32_srliw = 0b00101, + rv64_imm32_srxiw = 0b00101, // srliw/sraiw }; enum RV64_Load diff --git a/riscvm/opcodes.json b/riscvm/opcodes.json index 9d921d5..ed1d14a 100644 --- a/riscvm/opcodes.json +++ b/riscvm/opcodes.json @@ -59,7 +59,7 @@ "rv64_imm32": { "0": "addiw", "1": "slliw", - "5": "srliw" + "5": "srxiw" }, "rv64_imm64": { "0": "addi", @@ -67,7 +67,7 @@ "2": "slti", "3": "sltiu", "4": "xori", - "5": "srli", + "5": "srxi", "6": "ori", "7": "andi" }, diff --git a/riscvm/riscvm.cpp b/riscvm/riscvm.cpp index 72743c6..cd98a19 100644 --- a/riscvm/riscvm.cpp +++ b/riscvm/riscvm.cpp @@ -293,58 +293,6 @@ ALWAYS_INLINE static bool riscvm_handle_syscall(riscvm_ptr self, uint64_t code, return true; } -ALWAYS_INLINE static int64_t riscvm_shl_int64(int64_t a, int64_t b) -{ - if (LIKELY(b >= 0 && b < 64)) - { - return ((uint64_t)a) << b; - } - else if (UNLIKELY(b < 0 && b > -64)) - { - return (uint64_t)a >> -b; - } - else - { - return 0; - } -} - -ALWAYS_INLINE static int64_t riscvm_shr_int64(int64_t a, int64_t b) -{ - if (LIKELY(b >= 0 && b < 64)) - { - return (uint64_t)a >> b; - } - else if (UNLIKELY(b < 0 && b > -64)) - { - return (uint64_t)a << -b; - } - else - { - return 0; - } -} - -ALWAYS_INLINE static int64_t riscvm_asr_int64(int64_t a, int64_t b) -{ - if (LIKELY(b >= 0 && b < 64)) - { - return a >> b; - } - else if (UNLIKELY(b >= 64)) - { - return a < 0 ? -1 : 0; - } - else if (UNLIKELY(b < 0 && b > -64)) - { - return a << -b; - } - else - { - return 0; - } -} - ALWAYS_INLINE static __int128 riscvm_shr_int128(__int128 a, __int128 b) { if (LIKELY(b >= 0 && b < 128)) @@ -539,7 +487,7 @@ ALWAYS_INLINE static bool handler_rv64_imm64(riscvm_ptr self, Instruction inst) } case rv64_imm64_slli: { - val = riscvm_shl_int64(val, inst.rwtype.rs2); + val = val << (inst.itype.imm & 0b111111); break; } case rv64_imm64_slti: @@ -571,15 +519,17 @@ ALWAYS_INLINE static bool handler_rv64_imm64(riscvm_ptr self, Instruction inst) val = val ^ imm; break; } - case rv64_imm64_srli: + case rv64_imm64_srxi: { - if (inst.rwtype.shamt) + if ((inst.itype.imm >> 10) & 1) { - val = riscvm_asr_int64(val, inst.rwtype.rs2); + // srai + val = val >> (imm & 0b111111); } else { - val = riscvm_shr_int64(val, inst.rwtype.rs2); + // srli + val = (uint64_t)val >> (imm & 0b111111); } break; } @@ -619,18 +569,20 @@ ALWAYS_INLINE static bool handler_rv64_imm32(riscvm_ptr self, Instruction inst) } case rv64_imm32_slliw: { - val = (int64_t)(int32_t)riscvm_shl_int64(val, imm); + val = int32_t(val) << (imm & 0b11111); break; } - case rv64_imm32_srliw: + case rv64_imm32_srxiw: { - if (inst.rwtype.shamt) + if ((inst.itype.imm >> 10) & 1) { - val = (int64_t)(int32_t)riscvm_asr_int64(val, inst.rwtype.rs2); + // sraiw + val = int32_t(val) >> (imm & 0b11111); } else { - val = (int64_t)(int32_t)riscvm_shr_int64(val, inst.rwtype.rs2); + // srliw + val = int32_t(uint32_t(val) >> (imm & 0b11111)); } break; } @@ -666,7 +618,7 @@ ALWAYS_INLINE static bool handler_rv64_op64(riscvm_ptr self, Instruction inst) } case rv64_op64_sll: { - val = riscvm_shl_int64(val1, val2 & 0x1f); + val = val1 << (val2 & 0b111111); break; } case rv64_op64_slt: @@ -700,12 +652,12 @@ ALWAYS_INLINE static bool handler_rv64_op64(riscvm_ptr self, Instruction inst) } case rv64_op64_srl: { - val = riscvm_shr_int64(val1, val2 & 0x1f); + val = (uint64_t)val1 >> (val2 & 0b11111); break; } case rv64_op64_sra: { - val = riscvm_asr_int64(val1, val2 & 0x1f); + val = val1 >> (val2 & 0b11111); break; } case rv64_op64_or: @@ -829,12 +781,12 @@ ALWAYS_INLINE static bool handler_rv64_op32(riscvm_ptr self, Instruction inst) } case rv64_op32_sllw: { - val = (int64_t)(int32_t)riscvm_shl_int64(val1, (val2 & 0x1f)); + val = int32_t(val1 << (val2 & 0b11111)); break; } case rv64_op32_srlw: { - val = (int64_t)(int32_t)riscvm_shr_int64(val1, (val2 & 0x1f)); + val = int32_t(uint32_t(val1) >> (val2 & 0b11111)); break; } case rv64_op32_mulw: @@ -908,7 +860,7 @@ ALWAYS_INLINE static bool handler_rv64_op32(riscvm_ptr self, Instruction inst) } case rv64_op32_sraw: { - val = (int64_t)(int32_t)riscvm_asr_int64(val1, val2 & 0x1f); + val = int32_t(val1) >> (val2 & 0b11111); break; } case rv64_op32_subw: diff --git a/riscvm/shuffled_opcodes.h b/riscvm/shuffled_opcodes.h index f623f45..d794670 100644 --- a/riscvm/shuffled_opcodes.h +++ b/riscvm/shuffled_opcodes.h @@ -67,13 +67,13 @@ enum RV64_Imm64 rv64_imm64_andi = 0b00100, // original 0b00111 rv64_imm64_sltiu = 0b00101, // original 0b00011 rv64_imm64_addi = 0b00110, // original 0b00000 - rv64_imm64_srli = 0b00111, // original 0b00101 + rv64_imm64_srxi = 0b00111, // original 0b00101 rv64_imm64_invalid = 0b11111, // placeholder }; enum RV64_Imm32 { - rv64_imm32_srliw = 0b00000, // original 0b00101 + rv64_imm32_srxiw = 0b00000, // original 0b00101 rv64_imm32_slliw = 0b00001, // original 0b00001 rv64_imm32_addiw = 0b00010, // original 0b00000 rv64_imm32_invalid = 0b11111, // placeholder diff --git a/riscvm/trace.h b/riscvm/trace.h index 3a2ee75..a343384 100644 --- a/riscvm/trace.h +++ b/riscvm/trace.h @@ -109,8 +109,7 @@ void trace_imm64(riscvm_ptr self, Instruction inst, char* buffer) break; case rv64_imm64_slli: memnomic = "slli"; - imm = inst.rwtype.rs2; - val = rs1 << imm; + val = rs1 << (imm & 0b111111); break; case rv64_imm64_slti: memnomic = "slti"; @@ -124,10 +123,17 @@ void trace_imm64(riscvm_ptr self, Instruction inst, char* buffer) memnomic = "xori"; val = rs1 ^ imm; break; - case rv64_imm64_srli: - memnomic = "srli"; - imm = inst.rwtype.rs2; - val = rs1 >> imm; + case rv64_imm64_srxi: + if ((inst.itype.imm >> 10) & 1) + { + memnomic = "srai"; + val = rs1 >> (imm & 0b111111); + } + else + { + memnomic = "srli"; + val = (uint64_t)rs1 >> (imm & 0b111111); + } break; case rv64_imm64_ori: memnomic = "ori"; @@ -166,13 +172,19 @@ void trace_imm32(riscvm_ptr self, Instruction inst, char* buffer) break; case rv64_imm32_slliw: memnomic = "slliw"; - imm = inst.rwtype.rs2; - val = rs1 << imm; - break; - case rv64_imm32_srliw: - memnomic = "srliw"; - imm = inst.rwtype.rs2; - val = rs1 >> imm; + val = int32_t(rs1) << (imm & 0b11111); + break; + case rv64_imm32_srxiw: + if ((inst.itype.imm >> 10) & 1) + { + memnomic = "sraiw"; + val = int32_t(rs1) >> (imm & 0b11111); + } + else + { + memnomic = "srliw"; + val = int32_t(uint32_t(rs1) >> (imm & 0b11111)); + } break; default: memnomic = "unk(imm32)"; @@ -208,7 +220,7 @@ void trace_op64(riscvm_ptr self, Instruction inst, char* buffer) break; case rv64_op64_sll: memnomic = "sll"; - val = rs1 << rs2; + val = rs1 << (rs2 & 0b111111); break; case rv64_op64_slt: memnomic = "slt"; @@ -224,11 +236,11 @@ void trace_op64(riscvm_ptr self, Instruction inst, char* buffer) break; case rv64_op64_srl: memnomic = "srl"; - val = rs1 >> rs2; + val = (uint64_t)rs1 >> (rs2 & 0b11111); break; case rv64_op64_sra: memnomic = "sra"; - val = rs1 >> rs2; + val = rs1 >> (rs2 & 0b11111); break; case rv64_op64_or: memnomic = "or"; @@ -255,21 +267,73 @@ void trace_op64(riscvm_ptr self, Instruction inst, char* buffer) val = (__int128)(rs1 * rs2) >> 64; break; case rv64_op64_div: - memnomic = "div"; - val = rs1 / rs2; + { + memnomic = "div"; + int64_t dividend = rs1; + int64_t divisor = rs2; + if (UNLIKELY((dividend == (-9223372036854775807LL - 1)) && (divisor == -1))) + { + val = (-9223372036854775807LL - 1); + } + else if (UNLIKELY(divisor == 0)) + { + val = -1; + } + else + { + val = dividend / divisor; + } break; + } case rv64_op64_divu: - memnomic = "divu"; - val = rs1 / rs2; + { + memnomic = "divu"; + uint64_t dividend = (uint64_t)rs1; + uint64_t divisor = (uint64_t)rs2; + if (UNLIKELY(divisor == 0)) + { + val = -1; + } + else + { + val = (int64_t)(dividend / divisor); + } break; + } case rv64_op64_rem: - memnomic = "rem"; - val = rs1 % rs2; + { + memnomic = "rem"; + int64_t dividend = rs1; + int64_t divisor = rs2; + if (UNLIKELY((dividend == (-9223372036854775807LL - 1)) && (divisor == -1))) + { + val = 0; + } + else if (UNLIKELY(divisor == 0)) + { + val = dividend; + } + else + { + val = dividend % divisor; + } break; + } case rv64_op64_remu: - memnomic = "remu"; - val = rs1 % rs2; + { + memnomic = "remu"; + uint64_t dividend = (uint64_t)rs1; + uint64_t divisor = (uint64_t)rs2; + if (UNLIKELY(divisor == 0)) + { + val = (int64_t)dividend; + } + else + { + val = (int64_t)(dividend % divisor); + } break; + } default: memnomic = "unk(op64)"; break; @@ -302,35 +366,59 @@ void trace_op32(riscvm_ptr self, Instruction inst, char* buffer) break; case rv64_op32_sllw: memnomic = "sllw"; - val = rs1 << rs2; + val = int32_t(rs1 << (rs2 & 0b11111)); break; case rv64_op32_srlw: memnomic = "srlw"; - val = rs1 >> rs2; + val = rs1 >> (uint32_t(rs2) & 0b11111); break; case rv64_op32_sraw: memnomic = "sraw"; - val = rs1 >> rs2; + val = int32_t(rs1) >> (rs2 & 0b11111); break; case rv64_op32_mulw: memnomic = "mulw"; val = rs1 * rs2; break; case rv64_op32_divw: - memnomic = "divw"; - val = rs1 / rs2; + { + memnomic = "divw"; + int32_t dividend = (int32_t)rs1; + int32_t divisor = (int32_t)rs2; + if (UNLIKELY((dividend == (-2147483647 - 1)) && (divisor == -1))) + { + val = -2147483648LL; + } + else if (UNLIKELY(divisor == 0)) + { + val = -1; + } + else + { + val = (int64_t)(dividend / divisor); + } break; + } case rv64_op32_divuw: memnomic = "divuw"; - val = rs1 / rs2; + if (rs2 == 0) + val = -1; + else + val = rs1 / rs2; break; case rv64_op32_remw: memnomic = "remw"; - val = rs1 % rs2; + if (rs2 == 0) + val = rs1; + else + val = rs1 % rs2; break; case rv64_op32_remuw: memnomic = "remuw"; - val = rs1 % rs2; + if (rs2 == 0) + val = rs1; + else + val = rs1 % rs2; break; default: memnomic = "unk(op32)"; @@ -550,6 +638,11 @@ void trace_system(riscvm_ptr self, Instruction inst, char* buffer) void riscvm_trace(riscvm_ptr self, Instruction inst) { + if (inst.compressed_flags != 0b11) + { + panic("compressed instructions not supported!"); + } + char buffer[256]; int calldepth = g_calldepth;