use super::*;
use crate::isa::riscv64::inst::reg_to_gpr_num;
use crate::isa::riscv64::lower::isle::generated_code::{
VecAluOpRImm5, VecAluOpRR, VecAluOpRRImm5, VecAluOpRRR, VecAluOpRRRImm5, VecAluOpRRRR,
VecElementWidth, VecOpCategory, VecOpMasking,
};
use crate::machinst::isle::WritableReg;
use crate::Reg;
fn unsigned_field_width(value: u32, width: u8) -> u32 {
debug_assert_eq!(value & (!0 << width), 0);
value
}
fn encode_r_type_bits(opcode: u32, rd: u32, funct3: u32, rs1: u32, rs2: u32, funct7: u32) -> u32 {
let mut bits = 0;
bits |= unsigned_field_width(opcode, 7);
bits |= unsigned_field_width(rd, 5) << 7;
bits |= unsigned_field_width(funct3, 3) << 12;
bits |= unsigned_field_width(rs1, 5) << 15;
bits |= unsigned_field_width(rs2, 5) << 20;
bits |= unsigned_field_width(funct7, 7) << 25;
bits
}
pub fn encode_r_type(
opcode: u32,
rd: WritableReg,
funct3: u32,
rs1: Reg,
rs2: Reg,
funct7: u32,
) -> u32 {
encode_r_type_bits(
opcode,
reg_to_gpr_num(rd.to_reg()),
funct3,
reg_to_gpr_num(rs1),
reg_to_gpr_num(rs2),
funct7,
)
}
fn encode_i_type_bits(opcode: u32, rd: u32, funct3: u32, rs1: u32, offset: u32) -> u32 {
let mut bits = 0;
bits |= unsigned_field_width(opcode, 7);
bits |= unsigned_field_width(rd, 5) << 7;
bits |= unsigned_field_width(funct3, 3) << 12;
bits |= unsigned_field_width(rs1, 5) << 15;
bits |= unsigned_field_width(offset, 12) << 20;
bits
}
pub fn encode_i_type(opcode: u32, rd: WritableReg, width: u32, rs1: Reg, offset: Imm12) -> u32 {
encode_i_type_bits(
opcode,
reg_to_gpr_num(rd.to_reg()),
width,
reg_to_gpr_num(rs1),
offset.as_u32(),
)
}
pub fn encode_s_type(opcode: u32, width: u32, base: Reg, src: Reg, offset: Imm12) -> u32 {
let mut bits = 0;
bits |= unsigned_field_width(opcode, 7);
bits |= (offset.as_u32() & 0b11111) << 7;
bits |= unsigned_field_width(width, 3) << 12;
bits |= reg_to_gpr_num(base) << 15;
bits |= reg_to_gpr_num(src) << 20;
bits |= unsigned_field_width(offset.as_u32() >> 5, 7) << 25;
bits
}
pub fn encode_valu(
op: VecAluOpRRR,
vd: WritableReg,
vs1: Reg,
vs2: Reg,
masking: VecOpMasking,
) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();
encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
reg_to_gpr_num(vs1),
reg_to_gpr_num(vs2),
funct7,
)
}
pub fn encode_valu_rr_imm(
op: VecAluOpRRImm5,
vd: WritableReg,
imm: Imm5,
vs2: Reg,
masking: VecOpMasking,
) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();
let imm = imm.bits() as u32;
encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
imm,
reg_to_gpr_num(vs2),
funct7,
)
}
pub fn encode_valu_rrrr(
op: VecAluOpRRRR,
vd: WritableReg,
vs2: Reg,
vs1: Reg,
masking: VecOpMasking,
) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();
encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
reg_to_gpr_num(vs1),
reg_to_gpr_num(vs2),
funct7,
)
}
pub fn encode_valu_rrr_imm(
op: VecAluOpRRRImm5,
vd: WritableReg,
imm: Imm5,
vs2: Reg,
masking: VecOpMasking,
) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();
let imm = imm.bits() as u32;
encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
imm,
reg_to_gpr_num(vs2),
funct7,
)
}
pub fn encode_valu_rr(op: VecAluOpRR, vd: WritableReg, vs: Reg, masking: VecOpMasking) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();
let (vs1, vs2) = if op.vs_is_vs2_encoded() {
(op.aux_encoding(), reg_to_gpr_num(vs))
} else {
(reg_to_gpr_num(vs), op.aux_encoding())
};
encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
vs1,
vs2,
funct7,
)
}
pub fn encode_valu_r_imm(
op: VecAluOpRImm5,
vd: WritableReg,
imm: Imm5,
masking: VecOpMasking,
) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();
debug_assert_eq!(op, VecAluOpRImm5::VmvVI);
let vs1 = imm.bits() as u32;
let vs2 = op.aux_encoding();
encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
vs1,
vs2,
funct7,
)
}
pub fn encode_vcfg_imm(opcode: u32, rd: Reg, imm: UImm5, vtype: &VType) -> u32 {
let mut bits = 0;
bits |= unsigned_field_width(opcode, 7);
bits |= reg_to_gpr_num(rd) << 7;
bits |= VecOpCategory::OPCFG.encode() << 12;
bits |= unsigned_field_width(imm.bits(), 5) << 15;
bits |= unsigned_field_width(vtype.encode(), 10) << 20;
bits |= 0b11 << 30;
bits
}
pub fn encode_vmem_load(
opcode: u32,
vd: Reg,
width: VecElementWidth,
rs1: Reg,
lumop: u32,
masking: VecOpMasking,
mop: u32,
nf: u32,
) -> u32 {
let width = match width {
VecElementWidth::E8 => 0b000,
VecElementWidth::E16 => 0b101,
VecElementWidth::E32 => 0b110,
VecElementWidth::E64 => 0b111,
};
let mut bits = 0;
bits |= unsigned_field_width(opcode, 7);
bits |= reg_to_gpr_num(vd) << 7;
bits |= width << 12;
bits |= reg_to_gpr_num(rs1) << 15;
bits |= unsigned_field_width(lumop, 5) << 20;
bits |= masking.encode() << 25;
bits |= unsigned_field_width(mop, 2) << 26;
bits |= 0b0 << 28;
bits |= unsigned_field_width(nf, 3) << 29;
bits
}
pub fn encode_vmem_store(
opcode: u32,
vs3: Reg,
width: VecElementWidth,
rs1: Reg,
sumop: u32,
masking: VecOpMasking,
mop: u32,
nf: u32,
) -> u32 {
encode_vmem_load(opcode, vs3, width, rs1, sumop, masking, mop, nf)
}
pub fn encode_csr_reg(op: CsrRegOP, rd: WritableReg, rs: Reg, csr: CSR) -> u32 {
encode_i_type(op.opcode(), rd, op.funct3(), rs, csr.bits())
}
pub fn encode_csr_imm(op: CsrImmOP, rd: WritableReg, csr: CSR, imm: UImm5) -> u32 {
encode_i_type_bits(
op.opcode(),
reg_to_gpr_num(rd.to_reg()),
op.funct3(),
imm.bits(),
csr.bits().as_u32(),
)
}