Vortex 2.0 changes:
+ Microarchitecture optimizations + 64-bit support + Xilinx FPGA support + LLVM-16 support + Refactoring and quality control fixes
This commit is contained in:
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
@@ -9,41 +22,36 @@
|
||||
#include "debug.h"
|
||||
#include "types.h"
|
||||
#include "decode.h"
|
||||
#include "archdef.h"
|
||||
#include "arch.h"
|
||||
#include "instr.h"
|
||||
|
||||
using namespace vortex;
|
||||
|
||||
struct InstTableEntry_t {
|
||||
bool controlFlow;
|
||||
InstType iType;
|
||||
};
|
||||
|
||||
static const std::unordered_map<Opcode, struct InstTableEntry_t> 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::GPGPU, {false, InstType::R_TYPE}},
|
||||
{Opcode::GPU, {false, InstType::R4_TYPE}},
|
||||
{Opcode::R_INST_W, {false, InstType::R_TYPE}},
|
||||
{Opcode::I_INST_W, {false, InstType::I_TYPE}},
|
||||
static const std::unordered_map<Opcode, InstType> sc_instTable = {
|
||||
{Opcode::R_INST, InstType::R_TYPE},
|
||||
{Opcode::L_INST, InstType::I_TYPE},
|
||||
{Opcode::I_INST, InstType::I_TYPE},
|
||||
{Opcode::S_INST, InstType::S_TYPE},
|
||||
{Opcode::B_INST, InstType::B_TYPE},
|
||||
{Opcode::LUI_INST, InstType::U_TYPE},
|
||||
{Opcode::AUIPC_INST, InstType::U_TYPE},
|
||||
{Opcode::JAL_INST, InstType::J_TYPE},
|
||||
{Opcode::JALR_INST, InstType::I_TYPE},
|
||||
{Opcode::SYS_INST, InstType::I_TYPE},
|
||||
{Opcode::FENCE, InstType::I_TYPE},
|
||||
{Opcode::AMO, InstType::R_TYPE},
|
||||
{Opcode::FL, InstType::I_TYPE},
|
||||
{Opcode::FS, InstType::S_TYPE},
|
||||
{Opcode::FCI, InstType::R_TYPE},
|
||||
{Opcode::FMADD, InstType::R4_TYPE},
|
||||
{Opcode::FMSUB, InstType::R4_TYPE},
|
||||
{Opcode::FMNMADD, InstType::R4_TYPE},
|
||||
{Opcode::FMNMSUB, InstType::R4_TYPE},
|
||||
{Opcode::VSET, InstType::V_TYPE},
|
||||
{Opcode::EXT1, InstType::R_TYPE},
|
||||
{Opcode::EXT2, InstType::R4_TYPE},
|
||||
{Opcode::R_INST_W, InstType::R_TYPE},
|
||||
{Opcode::I_INST_W, InstType::I_TYPE},
|
||||
};
|
||||
|
||||
enum Constants {
|
||||
@@ -58,6 +66,8 @@ enum Constants {
|
||||
width_i_imm = 12,
|
||||
width_j_imm = 20,
|
||||
width_v_imm = 11,
|
||||
width_aq = 1,
|
||||
width_rl = 1,
|
||||
|
||||
shift_opcode= 0,
|
||||
shift_rd = width_opcode,
|
||||
@@ -72,15 +82,15 @@ enum Constants {
|
||||
shift_func6 = shift_func7 + width_vmask,
|
||||
shift_vset = shift_func7 + width_func6,
|
||||
|
||||
mask_opcode = (1<<width_opcode)-1,
|
||||
mask_reg = (1<<width_reg)-1,
|
||||
mask_func2 = (1<<width_func2)-1,
|
||||
mask_func3 = (1<<width_func3)-1,
|
||||
mask_func6 = (1<<width_func6)-1,
|
||||
mask_func7 = (1<<width_func7)-1,
|
||||
mask_i_imm = (1<<width_i_imm)-1,
|
||||
mask_j_imm = (1<<width_j_imm)-1,
|
||||
mask_v_imm = (1<<width_v_imm)-1,
|
||||
mask_opcode = (1 << width_opcode) - 1,
|
||||
mask_reg = (1 << width_reg) - 1,
|
||||
mask_func2 = (1 << width_func2) - 1,
|
||||
mask_func3 = (1 << width_func3) - 1,
|
||||
mask_func6 = (1 << width_func6) - 1,
|
||||
mask_func7 = (1 << width_func7) - 1,
|
||||
mask_i_imm = (1 << width_i_imm) - 1,
|
||||
mask_j_imm = (1 << width_j_imm) - 1,
|
||||
mask_v_imm = (1 << width_v_imm) - 1,
|
||||
};
|
||||
|
||||
static const char* op_string(const Instr &instr) {
|
||||
@@ -92,7 +102,6 @@ static const char* op_string(const Instr &instr) {
|
||||
auto imm = instr.getImm();
|
||||
|
||||
switch (opcode) {
|
||||
case Opcode::NOP: return "NOP";
|
||||
case Opcode::LUI_INST: return "LUI";
|
||||
case Opcode::AUIPC_INST: return "AUIPC";
|
||||
case Opcode::R_INST:
|
||||
@@ -116,7 +125,7 @@ static const char* op_string(const Instr &instr) {
|
||||
case 2: return "SLT";
|
||||
case 3: return "SLTU";
|
||||
case 4: return "XOR";
|
||||
case 5: return func7 ? "SRA" : "SRL";
|
||||
case 5: return (func7 & 0x20) ? "SRA" : "SRL";
|
||||
case 6: return "OR";
|
||||
case 7: return "AND";
|
||||
default:
|
||||
@@ -130,7 +139,7 @@ static const char* op_string(const Instr &instr) {
|
||||
case 2: return "SLTI";
|
||||
case 3: return "SLTIU";
|
||||
case 4: return "XORI";
|
||||
case 5: return func7 ? "SRAI" : "SRLI";
|
||||
case 5: return (func7 & 0x20) ? "SRAI" : "SRLI";
|
||||
case 6: return "ORI";
|
||||
case 7: return "ANDI";
|
||||
default:
|
||||
@@ -151,8 +160,8 @@ static const char* op_string(const Instr &instr) {
|
||||
case Opcode::JALR_INST: return "JALR";
|
||||
case Opcode::L_INST:
|
||||
switch (func3) {
|
||||
case 0: return "LBI";
|
||||
case 1: return "LHI";
|
||||
case 0: return "LB";
|
||||
case 1: return "LH";
|
||||
case 2: return "LW";
|
||||
case 3: return "LD";
|
||||
case 4: return "LBU";
|
||||
@@ -192,11 +201,11 @@ static const char* op_string(const Instr &instr) {
|
||||
}
|
||||
case Opcode::I_INST_W:
|
||||
switch (func3) {
|
||||
case 0: return "ADDIW";
|
||||
case 1: return "SLLIW";
|
||||
case 5: return func7 ? "SRAIW" : "SRLIW";
|
||||
default:
|
||||
std::abort();
|
||||
case 0: return "ADDIW";
|
||||
case 1: return "SLLIW";
|
||||
case 5: return func7 ? "SRAIW" : "SRLIW";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
case Opcode::SYS_INST:
|
||||
switch (func3) {
|
||||
@@ -222,20 +231,59 @@ static const char* op_string(const Instr &instr) {
|
||||
case Opcode::FENCE: return "FENCE";
|
||||
case Opcode::FL:
|
||||
switch (func3) {
|
||||
case 0x1: return "VL";
|
||||
case 0x2: return "FLW";
|
||||
case 0x3: return "FLD";
|
||||
default:
|
||||
std::abort();
|
||||
case 0x1: return "VL";
|
||||
case 0x2: return "FLW";
|
||||
case 0x3: return "FLD";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
case Opcode::FS:
|
||||
switch (func3) {
|
||||
case 0x1: return "VS";
|
||||
case 0x2: return "FSW";
|
||||
case 0x3: return "FSD";
|
||||
case 0x1: return "VS";
|
||||
case 0x2: return "FSW";
|
||||
case 0x3: return "FSD";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
case Opcode::AMO: {
|
||||
auto amo_type = func7 >> 2;
|
||||
switch (func3) {
|
||||
case 0x2:
|
||||
switch (amo_type) {
|
||||
case 0x00: return "AMOADD.W";
|
||||
case 0x01: return "AMOSWAP.W";
|
||||
case 0x02: return "LR.W";
|
||||
case 0x03: return "SC.W";
|
||||
case 0x04: return "AMOXOR.W";
|
||||
case 0x08: return "AMOOR.W";
|
||||
case 0x0c: return "AMOAND.W";
|
||||
case 0x10: return "AMOMIN.W";
|
||||
case 0x14: return "AMOMAX.W";
|
||||
case 0x18: return "AMOMINU.W";
|
||||
case 0x1c: return "AMOMAXU.W";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
case 0x3:
|
||||
switch (amo_type) {
|
||||
case 0x00: return "AMOADD.D";
|
||||
case 0x01: return "AMOSWAP.D";
|
||||
case 0x02: return "LR.D";
|
||||
case 0x03: return "SC.D";
|
||||
case 0x04: return "AMOXOR.D";
|
||||
case 0x08: return "AMOOR.D";
|
||||
case 0x0c: return "AMOAND.D";
|
||||
case 0x10: return "AMOMIN.D";
|
||||
case 0x14: return "AMOMAX.D";
|
||||
case 0x18: return "AMOMINU.D";
|
||||
case 0x1c: return "AMOMAXU.D";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
case Opcode::FCI:
|
||||
switch (func7) {
|
||||
case 0x00: return "FADD.S";
|
||||
@@ -332,9 +380,9 @@ static const char* op_string(const Instr &instr) {
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
case 0x70: return func3 ? "FCLASS.S" : "FMV.X.W";
|
||||
case 0x70: return func3 ? "FCLASS.S" : "FMV.X.S";
|
||||
case 0x71: return func3 ? "FCLASS.D" : "FMV.X.D";
|
||||
case 0x78: return "FMV.W.X";
|
||||
case 0x78: return "FMV.S.X";
|
||||
case 0x79: return "FMV.D.X";
|
||||
default:
|
||||
std::abort();
|
||||
@@ -344,23 +392,36 @@ static const char* op_string(const Instr &instr) {
|
||||
case Opcode::FMNMADD: return func2 ? "FNMADD.D" : "FNMADD.S";
|
||||
case Opcode::FMNMSUB: return func2 ? "FNMSUB.D" : "FNMSUB.S";
|
||||
case Opcode::VSET: return "VSET";
|
||||
case Opcode::GPGPU:
|
||||
switch (func3) {
|
||||
case 0: return "TMC";
|
||||
case 1: return "WSPAWN";
|
||||
case 2: return "SPLIT";
|
||||
case 3: return "JOIN";
|
||||
case 4: return "BAR";
|
||||
case 5: return "PREFETCH";
|
||||
case Opcode::EXT1:
|
||||
switch (func7) {
|
||||
case 0:
|
||||
switch (func3) {
|
||||
case 0: return "TMC";
|
||||
case 1: return "WSPAWN";
|
||||
case 2: return "SPLIT";
|
||||
case 3: return "JOIN";
|
||||
case 4: return "BAR";
|
||||
case 5: return "PRED";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
case 1:
|
||||
switch (func3) {
|
||||
case 0: return "RASTER";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
case Opcode::GPU:
|
||||
case Opcode::EXT2:
|
||||
switch (func3) {
|
||||
case 0: return "TEX";
|
||||
case 0:
|
||||
return "TEX";
|
||||
case 1: {
|
||||
switch (func2) {
|
||||
case 0: return "CMOV";
|
||||
case 1: return "ROP";
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
@@ -375,43 +436,36 @@ static const char* op_string(const Instr &instr) {
|
||||
|
||||
namespace vortex {
|
||||
std::ostream &operator<<(std::ostream &os, const Instr &instr) {
|
||||
auto opcode = instr.getOpcode();
|
||||
auto func2 = instr.getFunc2();
|
||||
auto opcode = instr.getOpcode();
|
||||
auto func3 = instr.getFunc3();
|
||||
|
||||
os << op_string(instr) << ": ";
|
||||
|
||||
if (opcode == S_INST
|
||||
|| opcode == FS) {
|
||||
os << "M[r" << std::dec << instr.getRSrc(0) << " + 0x" << std::hex << instr.getImm() << "] <- ";
|
||||
os << instr.getRSType(1) << std::dec << instr.getRSrc(1);
|
||||
} else
|
||||
if (opcode == L_INST
|
||||
|| opcode == FL) {
|
||||
os << instr.getRDType() << std::dec << instr.getRDest() << " <- ";
|
||||
os << "M[r" << std::dec << instr.getRSrc(0) << " + 0x" << std::hex << instr.getImm() << "]";
|
||||
} else {
|
||||
if (instr.getRDType() != RegType::None) {
|
||||
os << instr.getRDType() << std::dec << instr.getRDest() << " <- ";
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for (; i < instr.getNRSrc(); ++i) {
|
||||
if (i) os << ", ";
|
||||
os << instr.getRSType(i) << std::dec << instr.getRSrc(i);
|
||||
}
|
||||
if (instr.hasImm()) {
|
||||
if (i) os << ", ";
|
||||
os << "imm=0x" << std::hex << instr.getImm();
|
||||
}
|
||||
if (opcode == GPU && func3 == 0) {
|
||||
os << ", unit=" << std::dec << func2;
|
||||
}
|
||||
os << op_string(instr);
|
||||
|
||||
int sep = 0;
|
||||
if (instr.getRDType() != RegType::None) {
|
||||
if (sep++ != 0) { os << ", "; } else { os << " "; }
|
||||
os << instr.getRDType() << std::dec << instr.getRDest();
|
||||
}
|
||||
for (uint32_t i = 0; i < instr.getNRSrc(); ++i) {
|
||||
if (instr.getRSType(i) == RegType::None)
|
||||
continue;
|
||||
if (sep++ != 0) { os << ", "; } else { os << " "; }
|
||||
os << instr.getRSType(i) << std::dec << instr.getRSrc(i);
|
||||
}
|
||||
if (instr.hasImm()) {
|
||||
if (sep++ != 0) { os << ", "; } else { os << " "; }
|
||||
os << "0x" << std::hex << instr.getImm();
|
||||
}
|
||||
if (opcode == Opcode::SYS_INST && func3 >= 5) {
|
||||
// CSRs with immediate values
|
||||
if (sep++ != 0) { os << ", "; } else { os << " "; }
|
||||
os << "0x" << std::hex << instr.getRSrc(0);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
Decoder::Decoder(const ArchDef&) {}
|
||||
Decoder::Decoder(const Arch&) {}
|
||||
|
||||
std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
auto instr = std::make_shared<Instr>();
|
||||
@@ -434,7 +488,7 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto iType = op_it->second.iType;
|
||||
auto iType = op_it->second;
|
||||
if (op == Opcode::FL || op == Opcode::FS) {
|
||||
if (func3 != 0x2 && func3 != 0x3) {
|
||||
iType = InstType::V_TYPE;
|
||||
@@ -442,57 +496,97 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
}
|
||||
|
||||
switch (iType) {
|
||||
case InstType::N_TYPE:
|
||||
break;
|
||||
|
||||
case InstType::R_TYPE:
|
||||
if (op == Opcode::FCI) {
|
||||
switch (func7) {
|
||||
switch (op) {
|
||||
case Opcode::FCI:
|
||||
switch (func7) {
|
||||
case 0x2c: // FSQRT.S
|
||||
case 0x2d: // FSQRT.D
|
||||
instr->setDestReg(rd, RegType::Float);
|
||||
instr->addSrcReg(rs1, RegType::Float);
|
||||
break;
|
||||
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);
|
||||
instr->addSrcReg(rs1, RegType::Float);
|
||||
instr->addSrcReg(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);
|
||||
instr->addSrcReg(rs1, RegType::Float);
|
||||
instr->addSrcReg(rs2, RegType::None);
|
||||
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);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs2, RegType::None);
|
||||
break;
|
||||
case 0x70: // FCLASS.S, FMV.X.W
|
||||
case 0x70: // FCLASS.S, FMV.X.S
|
||||
case 0x71: // FCLASS.D, FMV.X.D
|
||||
instr->setDestReg(rd, RegType::Integer);
|
||||
instr->setSrcReg(rs1, RegType::Float);
|
||||
instr->addSrcReg(rs1, RegType::Float);
|
||||
break;
|
||||
case 0x78: // FMV.W.X
|
||||
case 0x78: // FMV.S.X
|
||||
case 0x79: // FMV.D.X
|
||||
instr->setDestReg(rd, RegType::Float);
|
||||
instr->setSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
break;
|
||||
default:
|
||||
instr->setDestReg(rd, RegType::Float);
|
||||
instr->setSrcReg(rs1, RegType::Float);
|
||||
instr->setSrcReg(rs2, RegType::Float);
|
||||
instr->addSrcReg(rs1, RegType::Float);
|
||||
instr->addSrcReg(rs2, RegType::Float);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
case Opcode::EXT1:
|
||||
switch (func7) {
|
||||
case 0:
|
||||
switch (func3) {
|
||||
case 0: // TMC
|
||||
case 3: // JOIN
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
break;
|
||||
case 1: // WSPAWN
|
||||
case 4: // BAR
|
||||
case 5: // PRED
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs2, RegType::Integer);
|
||||
break;
|
||||
case 2: // SPLIT
|
||||
instr->setDestReg(rd, RegType::Integer);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
switch (func3) {
|
||||
case 0: // RASTER
|
||||
instr->setDestReg(rd, RegType::Integer);
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
instr->setDestReg(rd, RegType::Integer);
|
||||
instr->setSrcReg(rs1, RegType::Integer);
|
||||
instr->setSrcReg(rs2, RegType::Integer);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs2, RegType::Integer);
|
||||
break;
|
||||
}
|
||||
instr->setFunc3(func3);
|
||||
instr->setFunc7(func7);
|
||||
break;
|
||||
|
||||
case InstType::I_TYPE: {
|
||||
instr->setSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
if (op == Opcode::FL) {
|
||||
instr->setDestReg(rd, RegType::Float);
|
||||
} else {
|
||||
@@ -503,15 +597,23 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
switch (op) {
|
||||
case Opcode::SYS_INST:
|
||||
if (func3 != 0) {
|
||||
// RV32I: CSR*
|
||||
instr->setDestReg(rd, RegType::Integer);
|
||||
}
|
||||
// RV32I: CSR
|
||||
if (func3 >= 5) {
|
||||
// rs1 holds zimm
|
||||
instr->setSrcReg(0, rs1, RegType::None);
|
||||
}
|
||||
} else {
|
||||
instr->setDestReg(rd, RegType::None);
|
||||
instr->setSrcReg(0, rs1, RegType::None);
|
||||
}
|
||||
// uint12
|
||||
instr->setImm(code >> shift_rs2);
|
||||
break;
|
||||
case Opcode::FENCE:
|
||||
// uint12
|
||||
instr->setImm(code >> shift_rs2);
|
||||
instr->setDestReg(rd, RegType::None);
|
||||
instr->setSrcReg(0, rs1, RegType::None);
|
||||
break;
|
||||
case Opcode::I_INST:
|
||||
case Opcode::I_INST_W:
|
||||
@@ -538,11 +640,11 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
}
|
||||
} break;
|
||||
case InstType::S_TYPE: {
|
||||
instr->setSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
if (op == Opcode::FS) {
|
||||
instr->setSrcReg(rs2, RegType::Float);
|
||||
instr->addSrcReg(rs2, RegType::Float);
|
||||
} else {
|
||||
instr->setSrcReg(rs2, RegType::Integer);
|
||||
instr->addSrcReg(rs2, RegType::Integer);
|
||||
}
|
||||
instr->setFunc3(func3);
|
||||
auto imm = (func7 << width_reg) | rd;
|
||||
@@ -550,8 +652,8 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
} break;
|
||||
|
||||
case InstType::B_TYPE: {
|
||||
instr->setSrcReg(rs1, RegType::Integer);
|
||||
instr->setSrcReg(rs2, RegType::Integer);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs2, RegType::Integer);
|
||||
instr->setFunc3(func3);
|
||||
auto bit_11 = rd & 0x1;
|
||||
auto bits_4_1 = rd >> 1;
|
||||
@@ -581,8 +683,8 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
case InstType::V_TYPE:
|
||||
switch (op) {
|
||||
case Opcode::VSET: {
|
||||
instr->setDestVReg(rd);
|
||||
instr->setSrcVReg(rs1);
|
||||
instr->setDestReg(rd, RegType::Vector);
|
||||
instr->addSrcReg(rs1, RegType::Vector);
|
||||
instr->setFunc3(func3);
|
||||
if (func3 == 7) {
|
||||
instr->setImm(!(code >> shift_vset));
|
||||
@@ -593,20 +695,20 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
instr->setVediv((immed >> 4) & 0x3);
|
||||
instr->setVsew((immed >> 2) & 0x3);
|
||||
} else {
|
||||
instr->setSrcVReg(rs2);
|
||||
instr->addSrcReg(rs2, RegType::Vector);
|
||||
}
|
||||
} else {
|
||||
instr->setSrcVReg(rs2);
|
||||
instr->addSrcReg(rs2, RegType::Vector);
|
||||
instr->setVmask((code >> shift_func7) & 0x1);
|
||||
instr->setFunc6(func6);
|
||||
}
|
||||
} break;
|
||||
|
||||
case Opcode::FL:
|
||||
instr->setDestVReg(rd);
|
||||
instr->setSrcVReg(rs1);
|
||||
instr->setDestReg(rd, RegType::Vector);
|
||||
instr->addSrcReg(rs1, RegType::Vector);
|
||||
instr->setVlsWidth(func3);
|
||||
instr->setSrcVReg(rs2);
|
||||
instr->addSrcReg(rs2, RegType::Vector);
|
||||
instr->setVmask(code >> shift_func7);
|
||||
instr->setVmop((code >> shift_vmop) & mask_func3);
|
||||
instr->setVnf((code >> shift_vnf) & mask_func3);
|
||||
@@ -614,9 +716,9 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
|
||||
case Opcode::FS:
|
||||
instr->setVs3(rd);
|
||||
instr->setSrcVReg(rs1);
|
||||
instr->addSrcReg(rs1, RegType::Vector);
|
||||
instr->setVlsWidth(func3);
|
||||
instr->setSrcVReg(rs2);
|
||||
instr->addSrcReg(rs2, RegType::Vector);
|
||||
instr->setVmask(code >> shift_func7);
|
||||
instr->setVmop((code >> shift_vmop) & mask_func3);
|
||||
instr->setVnf((code >> shift_vnf) & mask_func3);
|
||||
@@ -627,16 +729,28 @@ std::shared_ptr<Instr> Decoder::decode(uint32_t code) const {
|
||||
}
|
||||
break;
|
||||
case R4_TYPE:
|
||||
if (op == Opcode::GPU) {
|
||||
instr->setDestReg(rd, RegType::Integer);
|
||||
instr->setSrcReg(rs1, RegType::Integer);
|
||||
instr->setSrcReg(rs2, RegType::Integer);
|
||||
instr->setSrcReg(rs3, RegType::Integer);
|
||||
if (op == Opcode::EXT2) {
|
||||
switch (func3) {
|
||||
case 1:
|
||||
switch (func2) {
|
||||
case 0: // CMOV
|
||||
instr->setDestReg(rd, RegType::Integer);
|
||||
instr->addSrcReg(rs1, RegType::Integer);
|
||||
instr->addSrcReg(rs2, RegType::Integer);
|
||||
instr->addSrcReg(rs3, RegType::Integer);
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
} else {
|
||||
instr->setDestReg(rd, RegType::Float);
|
||||
instr->setSrcReg(rs1, RegType::Float);
|
||||
instr->setSrcReg(rs2, RegType::Float);
|
||||
instr->setSrcReg(rs3, RegType::Float);
|
||||
instr->addSrcReg(rs1, RegType::Float);
|
||||
instr->addSrcReg(rs2, RegType::Float);
|
||||
instr->addSrcReg(rs3, RegType::Float);
|
||||
}
|
||||
instr->setFunc2(func2);
|
||||
instr->setFunc3(func3);
|
||||
|
||||
Reference in New Issue
Block a user