use crate::config::Parameters;
use super::bits::Bits;
use super::info::Info;
pub trait Decode<I: Info> {
fn decode_16(&self, insn: u16) -> I;
fn decode_32(&self, insn: u32) -> I;
fn decode_48(&self, insn: u64) -> I;
fn decode_64(&self, insn: u64) -> I;
fn decode_bits(&self, bits: Bits) -> I {
match bits {
Bits::Bit16(bits) => self.decode_16(bits),
Bits::Bit32(bits) => self.decode_32(bits),
Bits::Bit48(bits) => self.decode_48(bits),
Bits::Bit64(bits) => self.decode_64(bits),
}
}
}
impl<D, I> Decode<(I, Bits)> for D
where
D: Decode<I>,
I: Info,
(I, Bits): Info,
{
fn decode_16(&self, insn: u16) -> (I, Bits) {
(self.decode_16(insn), Bits::Bit16(insn))
}
fn decode_32(&self, insn: u32) -> (I, Bits) {
(self.decode_32(insn), Bits::Bit32(insn))
}
fn decode_48(&self, insn: u64) -> (I, Bits) {
(self.decode_48(insn), Bits::Bit48(insn))
}
fn decode_64(&self, insn: u64) -> (I, Bits) {
(self.decode_64(insn), Bits::Bit64(insn))
}
}
#[cfg(feature = "riscv-isa")]
impl Decode<riscv_isa::Instruction> for riscv_isa::Target {
fn decode_16(&self, insn: u16) -> riscv_isa::Instruction {
use riscv_isa::Compressed;
match riscv_isa::decode_compressed(insn, self) {
Compressed::C_LUI { rd: 0, .. } => Compressed::UNIMP,
Compressed::C_JR { rs1: 0, .. } => Compressed::UNIMP,
Compressed::C_JALR { rs1: 0, .. } => Compressed::UNIMP,
insn => insn,
}
.into()
}
fn decode_32(&self, insn: u32) -> riscv_isa::Instruction {
riscv_isa::decode_full(insn, self)
}
fn decode_48(&self, _insn: u64) -> riscv_isa::Instruction {
riscv_isa::Instruction::UNIMP
}
fn decode_64(&self, _insn: u64) -> riscv_isa::Instruction {
riscv_isa::Instruction::UNIMP
}
}
#[cfg(feature = "riscv-isa")]
impl Decode<riscv_isa::Compressed> for riscv_isa::Target {
fn decode_16(&self, insn: u16) -> riscv_isa::Compressed {
use riscv_isa::Compressed;
match riscv_isa::decode_compressed(insn, self) {
Compressed::C_LUI { rd: 0, .. } => Compressed::UNIMP,
Compressed::C_JR { rs1: 0, .. } => Compressed::UNIMP,
Compressed::C_JALR { rs1: 0, .. } => Compressed::UNIMP,
insn => insn,
}
}
fn decode_32(&self, _insn: u32) -> riscv_isa::Compressed {
riscv_isa::Compressed::UNIMP
}
fn decode_48(&self, _insn: u64) -> riscv_isa::Compressed {
riscv_isa::Compressed::UNIMP
}
fn decode_64(&self, _insn: u64) -> riscv_isa::Compressed {
riscv_isa::Compressed::UNIMP
}
}
#[cfg(all(feature = "either", feature = "riscv-isa"))]
impl Decode<either::Either<riscv_isa::Compressed, riscv_isa::Instruction>> for riscv_isa::Target {
fn decode_16(
&self,
insn: u16,
) -> either::Either<riscv_isa::Compressed, riscv_isa::Instruction> {
either::Left(self.decode_16(insn))
}
fn decode_32(
&self,
insn: u32,
) -> either::Either<riscv_isa::Compressed, riscv_isa::Instruction> {
either::Right(self.decode_32(insn))
}
fn decode_48(
&self,
insn: u64,
) -> either::Either<riscv_isa::Compressed, riscv_isa::Instruction> {
either::Right(self.decode_48(insn))
}
fn decode_64(
&self,
insn: u64,
) -> either::Either<riscv_isa::Compressed, riscv_isa::Instruction> {
either::Right(self.decode_64(insn))
}
}
pub trait MakeDecode {
fn rv32i_full() -> Self;
fn rv64i_full() -> Self;
fn infer_from_params(params: &Parameters) -> Option<Self>
where
Self: Sized,
{
match params.iaddress_width_p.get() {
0..=32 => Some(Self::rv32i_full()),
33..=64 => Some(Self::rv64i_full()),
_ => None,
}
}
}
#[cfg(feature = "riscv-isa")]
impl MakeDecode for riscv_isa::Target {
fn rv32i_full() -> Self {
Self {
xlen: riscv_isa::Xlen::Rv32,
privileged: true,
supervisor_mode: true,
m: true,
a: true,
f: true,
d: true,
q: true,
c: true,
zicsr: true,
zifencei: true,
zawrs: true,
zfh: true,
zba: true,
zbb: true,
zbc: true,
zbkb: true,
zbs: true,
}
}
fn rv64i_full() -> Self {
Self {
xlen: riscv_isa::Xlen::Rv64,
privileged: true,
supervisor_mode: true,
m: true,
a: true,
f: true,
d: true,
q: true,
c: true,
zicsr: true,
zifencei: true,
zawrs: true,
zfh: true,
zba: true,
zbb: true,
zbc: true,
zbkb: true,
zbs: true,
}
}
}