#include #include #include #include #include #include #include #include #include "debug.h" #include "types.h" #include "decode.h" #include "arch.h" #include "instr.h" using namespace vortex; struct InstTableEntry_t { bool controlFlow; InstType iType; }; static const std::unordered_map sc_instTable = { {Opcode::NOP, {false, InstType::N_TYPE}}, {Opcode::R_INST, {false, InstType::R_TYPE}}, {Opcode::L_INST, {false, InstType::I_TYPE}}, {Opcode::I_INST, {false, InstType::I_TYPE}}, {Opcode::S_INST, {false, InstType::S_TYPE}}, {Opcode::B_INST, {true , InstType::B_TYPE}}, {Opcode::LUI_INST, {false, InstType::U_TYPE}}, {Opcode::AUIPC_INST, {false, InstType::U_TYPE}}, {Opcode::JAL_INST, {true , InstType::J_TYPE}}, {Opcode::JALR_INST, {true , InstType::I_TYPE}}, {Opcode::SYS_INST, {true , InstType::I_TYPE}}, {Opcode::FENCE, {true , InstType::I_TYPE}}, {Opcode::FL, {false, InstType::I_TYPE}}, {Opcode::FS, {false, InstType::S_TYPE}}, {Opcode::FCI, {false, InstType::R_TYPE}}, {Opcode::FMADD, {false, InstType::R4_TYPE}}, {Opcode::FMSUB, {false, InstType::R4_TYPE}}, {Opcode::FMNMADD, {false, InstType::R4_TYPE}}, {Opcode::FMNMSUB, {false, InstType::R4_TYPE}}, {Opcode::VSET, {false, InstType::V_TYPE}}, {Opcode::EXT1, {false, InstType::R_TYPE}}, {Opcode::EXT2, {false, InstType::R4_TYPE}}, {Opcode::R_INST_W, {false, InstType::R_TYPE}}, {Opcode::I_INST_W, {false, InstType::I_TYPE}}, }; enum Constants { width_opcode= 7, width_reg = 5, width_func2 = 2, width_func3 = 3, width_func6 = 6, width_func7 = 7, width_mop = 3, width_vmask = 1, width_i_imm = 12, width_j_imm = 20, width_v_imm = 11, shift_opcode= 0, shift_rd = width_opcode, shift_func3 = shift_rd + width_reg, shift_rs1 = shift_func3 + width_func3, shift_rs2 = shift_rs1 + width_reg, shift_func2 = shift_rs2 + width_reg, shift_func7 = shift_rs2 + width_reg, shift_rs3 = shift_func7 + width_func2, shift_vmop = shift_func7 + width_vmask, shift_vnf = shift_vmop + width_mop, shift_func6 = shift_func7 + width_vmask, shift_vset = shift_func7 + width_func6, mask_opcode = (1<second.iType; if (op == Opcode::FL || op == Opcode::FS) { if (func3 != 0x2 && func3 != 0x3) { iType = InstType::V_TYPE; } } switch (iType) { case InstType::N_TYPE: break; case InstType::R_TYPE: if (op == Opcode::FCI) { switch (func7) { case 0x50: // FLE.S, FLT.S, FEQ.S case 0x51: // FLE.D, FLT.D, FEQ.D instr->setDestReg(rd, RegType::Integer); instr->setSrcReg(rs1, RegType::Float); instr->setSrcReg(rs2, RegType::Float); break; case 0x60: // FCVT.W.D, FCVT.WU.D, FCVT.L.D, FCVT.LU.D case 0x61: // FCVT.WU.S, FCVT.W.S, FCVT.L.S, FCVT.LU.S instr->setDestReg(rd, RegType::Integer); instr->setSrcReg(rs1, RegType::Float); instr->setSrcReg(rs2, RegType::Integer); break; case 0x68: // FCVT.S.W, FCVT.S.WU, FCVT.S.L, FCVT.S.LU case 0x69: // FCVT.D.W, FCVT.D.WU, FCVT.D.L, FCVT.D.LU instr->setDestReg(rd, RegType::Float); instr->setSrcReg(rs1, RegType::Integer); instr->setSrcReg(rs2, RegType::Integer); break; case 0x70: // FCLASS.S, FMV.X.W case 0x71: // FCLASS.D, FMV.X.D instr->setDestReg(rd, RegType::Integer); instr->setSrcReg(rs1, RegType::Float); break; case 0x78: // FMV.W.X case 0x79: // FMV.D.X instr->setDestReg(rd, RegType::Float); instr->setSrcReg(rs1, RegType::Integer); break; default: instr->setDestReg(rd, RegType::Float); instr->setSrcReg(rs1, RegType::Float); instr->setSrcReg(rs2, RegType::Float); break; } } else { instr->setDestReg(rd, RegType::Integer); instr->setSrcReg(rs1, RegType::Integer); instr->setSrcReg(rs2, RegType::Integer); } instr->setFunc3(func3); instr->setFunc7(func7); break; case InstType::I_TYPE: { instr->setSrcReg(rs1, RegType::Integer); if (op == Opcode::FL) { instr->setDestReg(rd, RegType::Float); } else { instr->setDestReg(rd, RegType::Integer); } instr->setFunc3(func3); instr->setFunc7(func7); switch (op) { case Opcode::SYS_INST: if (func3 != 0) { // RV32I: CSR* instr->setDestReg(rd, RegType::Integer); } // uint12 instr->setImm(code >> shift_rs2); break; case Opcode::FENCE: // uint12 instr->setImm(code >> shift_rs2); break; case Opcode::I_INST: case Opcode::I_INST_W: if (func3 == 0x1 || func3 == 0x5) { auto shamt = rs2; // uint5 #if (XLEN == 64) if (op == Opcode::I_INST) { // uint6 shamt |= ((func7 & 0x1) << 5); } #endif instr->setImm(shamt); } else { // int12 auto imm = code >> shift_rs2; instr->setImm(sext(imm, width_i_imm)); } break; default: // int12 auto imm = code >> shift_rs2; instr->setImm(sext(imm, width_i_imm)); break; } } break; case InstType::S_TYPE: { instr->setSrcReg(rs1, RegType::Integer); if (op == Opcode::FS) { instr->setSrcReg(rs2, RegType::Float); } else { instr->setSrcReg(rs2, RegType::Integer); } instr->setFunc3(func3); auto imm = (func7 << width_reg) | rd; instr->setImm(sext(imm, width_i_imm)); } break; case InstType::B_TYPE: { instr->setSrcReg(rs1, RegType::Integer); instr->setSrcReg(rs2, RegType::Integer); instr->setFunc3(func3); auto bit_11 = rd & 0x1; auto bits_4_1 = rd >> 1; auto bit_10_5 = func7 & 0x3f; auto bit_12 = func7 >> 6; auto imm = (bits_4_1 << 1) | (bit_10_5 << 5) | (bit_11 << 11) | (bit_12 << 12); instr->setImm(sext(imm, width_i_imm+1)); } break; case InstType::U_TYPE: { instr->setDestReg(rd, RegType::Integer); auto imm = code >> shift_func3; instr->setImm(sext(imm, width_j_imm)); } break; case InstType::J_TYPE: { instr->setDestReg(rd, RegType::Integer); auto unordered = code >> shift_func3; auto bits_19_12 = unordered & 0xff; auto bit_11 = (unordered >> 8) & 0x1; auto bits_10_1 = (unordered >> 9) & 0x3ff; auto bit_20 = (unordered >> 19) & 0x1; auto imm = (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20); instr->setImm(sext(imm, width_j_imm+1)); } break; case InstType::V_TYPE: switch (op) { case Opcode::VSET: { instr->setDestVReg(rd); instr->setSrcVReg(rs1); instr->setFunc3(func3); if (func3 == 7) { instr->setImm(!(code >> shift_vset)); if (instr->getImm()) { auto immed = (code >> shift_rs2) & mask_v_imm; instr->setImm(immed); instr->setVlmul(immed & 0x3); instr->setVediv((immed >> 4) & 0x3); instr->setVsew((immed >> 2) & 0x3); } else { instr->setSrcVReg(rs2); } } else { instr->setSrcVReg(rs2); instr->setVmask((code >> shift_func7) & 0x1); instr->setFunc6(func6); } } break; case Opcode::FL: instr->setDestVReg(rd); instr->setSrcVReg(rs1); instr->setVlsWidth(func3); instr->setSrcVReg(rs2); instr->setVmask(code >> shift_func7); instr->setVmop((code >> shift_vmop) & mask_func3); instr->setVnf((code >> shift_vnf) & mask_func3); break; case Opcode::FS: instr->setVs3(rd); instr->setSrcVReg(rs1); instr->setVlsWidth(func3); instr->setSrcVReg(rs2); instr->setVmask(code >> shift_func7); instr->setVmop((code >> shift_vmop) & mask_func3); instr->setVnf((code >> shift_vnf) & mask_func3); break; default: std::abort(); } break; case R4_TYPE: if (op == Opcode::EXT2) { instr->setDestReg(rd, RegType::Integer); instr->setSrcReg(rs1, RegType::Integer); instr->setSrcReg(rs2, RegType::Integer); instr->setSrcReg(rs3, RegType::Integer); } else { instr->setDestReg(rd, RegType::Float); instr->setSrcReg(rs1, RegType::Float); instr->setSrcReg(rs2, RegType::Float); instr->setSrcReg(rs3, RegType::Float); } instr->setFunc2(func2); instr->setFunc3(func3); break; default: std::abort(); } return instr; }