Renamed Encodable to Encode and Decodable to Decode.

Added `TryEncode` for fallible encodings.
This commit is contained in:
Filipe Rodrigues 2021-04-26 12:21:00 +01:00
parent 2ebc4eca28
commit 8c24f616e2
18 changed files with 132 additions and 79 deletions

View File

@ -23,7 +23,7 @@ pub use size::InstSize;
pub use target::InstTarget;
// Imports
use self::{basic::Decodable as _, pseudo::Decodable as _};
use self::{basic::Decode as _, pseudo::Decodable as _};
use crate::{DataTable, FuncTable, Pos};
use std::{borrow::Borrow, ops::Deref};

View File

@ -56,7 +56,7 @@ pub enum Inst {
}
impl Decodable for Inst {
impl Decode for Inst {
#[rustfmt::skip]
fn decode(raw: u32) -> Option<Self> {
None
@ -73,20 +73,35 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
/// Encode error
#[derive(PartialEq, Clone, Debug, thiserror::Error)]
pub enum EncodeError {
/// Sys
#[error("Unable to encode `Shift` instruction")]
Shift(shift::EncodeError),
/// Sys
#[error("Unable to encode `Sys` instruction")]
Sys(sys::EncodeError),
}
impl TryEncode for Inst {
type Error = EncodeError;
#[rustfmt::skip]
fn encode(&self) -> u32 {
fn try_encode(&self) -> Result<u32, Self::Error> {
match self {
Self::Alu (inst) => inst.encode(),
Self::Cond (inst) => inst.encode(),
Self::Jmp (inst) => inst.encode(),
Self::Load (inst) => inst.encode(),
Self::Lui (inst) => inst.encode(),
Self::Mult (inst) => inst.encode(),
Self::Shift(inst) => inst.encode(),
Self::Store(inst) => inst.encode(),
Self::Sys (inst) => inst.encode(),
Self::Co (inst) => inst.encode(),
Self::Alu (inst) => Ok(inst.encode()),
Self::Cond (inst) => Ok(inst.encode()),
Self::Jmp (inst) => Ok(inst.encode()),
Self::Load (inst) => Ok(inst.encode()),
Self::Lui (inst) => Ok(inst.encode()),
Self::Mult (inst) => Ok(inst.encode()),
Self::Shift(inst) => inst.try_encode().map_err(EncodeError::Shift),
Self::Store(inst) => Ok(inst.encode()),
Self::Sys (inst) => inst.try_encode().map_err(EncodeError::Sys),
Self::Co (inst) => Ok(inst.encode()),
}
}
}
@ -140,7 +155,7 @@ impl ModifiesReg for Inst {
}
// Any basic decodable instruction is 4 bytes
impl<T: Decodable> InstSize for T {
impl<T: Decode> InstSize for T {
fn size(&self) -> usize {
4
}
@ -165,23 +180,30 @@ impl InstFmt for Inst {
}
/// A decodable basic instruction
pub trait Decodable: Sized {
pub trait Decode: Sized {
/// Decodes this instruction
#[must_use]
fn decode(raw: u32) -> Option<Self>;
}
/// An encodable basic instruction
pub trait Encodable {
pub trait Encode {
/// Encodes this instruction
#[must_use]
fn encode(&self) -> u32;
}
// TODO: TryEncode?
/// An encodable basic instruction with possible failure
pub trait TryEncode {
/// Error type
type Error;
/// Attempts to encode the instructions
fn try_encode(&self) -> Result<u32, Self::Error>;
}
/// Register modifying instructions
pub trait ModifiesReg: Decodable {
pub trait ModifiesReg {
/// Returns if this instruction modifies `reg`.
fn modifies_reg(&self, reg: Register) -> bool;
}

View File

@ -7,7 +7,7 @@ pub mod reg;
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError,
};
@ -23,14 +23,14 @@ pub enum Inst {
Reg(reg::Inst),
}
impl Decodable for Inst {
impl Decode for Inst {
fn decode(raw: u32) -> Option<Self> {
None.or_else(|| imm::Inst::decode(raw).map(Self::Imm))
.or_else(|| reg::Inst::decode(raw).map(Self::Reg))
}
}
impl Encodable for Inst {
impl Encode for Inst {
fn encode(&self) -> u32 {
match self {
Inst::Imm(inst) => inst.encode(),

View File

@ -2,7 +2,7 @@
// Imports
use crate::inst::{
basic::{Decodable, Encodable, ModifiesReg},
basic::{Decode, Encode, ModifiesReg},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -75,7 +75,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [p, s, t, i] = #[bitmatch]
@ -101,7 +101,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
#[rustfmt::skip]

View File

@ -2,7 +2,7 @@
// Imports
use crate::inst::{
basic::{Decodable, Encodable, ModifiesReg},
basic::{Decode, Encode, ModifiesReg},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -76,7 +76,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [s, t, d, f] = #[bitmatch]
@ -105,7 +105,7 @@ impl Decodable for Inst {
})
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
#[rustfmt::skip]

View File

@ -3,7 +3,7 @@
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -98,7 +98,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
// Get `n`
@ -122,7 +122,7 @@ impl Decodable for Inst {
Some(Self { n, kind })
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
let n = self.n;

View File

@ -4,7 +4,7 @@
use super::ModifiesReg;
use crate::{
inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstTarget, InstTargetFmt, Parsable, ParseCtx, ParseError, Register,
},
@ -62,7 +62,7 @@ impl Inst {
}
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [p, s, t, i] = #[bitmatch]
@ -92,7 +92,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
#[rustfmt::skip]

View File

@ -7,7 +7,7 @@ pub mod reg;
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -23,14 +23,14 @@ pub enum Inst {
Reg(reg::Inst),
}
impl Decodable for Inst {
impl Decode for Inst {
fn decode(raw: u32) -> Option<Self> {
None.or_else(|| imm::Inst::decode(raw).map(Self::Imm))
.or_else(|| reg::Inst::decode(raw).map(Self::Reg))
}
}
impl Encodable for Inst {
impl Encode for Inst {
fn encode(&self) -> u32 {
match self {
Self::Imm(inst) => inst.encode(),

View File

@ -3,7 +3,7 @@
// Imports
use crate::{
inst::{
basic::{Decodable, Encodable, ModifiesReg},
basic::{Decode, Encode, ModifiesReg},
parse::LineArg,
InstTarget, InstTargetFmt, Parsable, ParseCtx, ParseError, Register,
},
@ -49,7 +49,7 @@ impl Inst {
}
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [p, i] = #[bitmatch]
@ -68,7 +68,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
let p: u32 = match self.kind {

View File

@ -2,7 +2,7 @@
// Imports
use crate::inst::{
basic::{Decodable, Encodable, ModifiesReg},
basic::{Decode, Encode, ModifiesReg},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -38,7 +38,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [s, d, f] = #[bitmatch]
@ -58,7 +58,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
let (f, d): (u32, u32) = match self.kind {

View File

@ -3,7 +3,7 @@
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -68,7 +68,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [p, s, t, i] = #[bitmatch]
@ -95,7 +95,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
let p: u32 = match self.kind {

View File

@ -3,7 +3,7 @@
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -20,7 +20,7 @@ pub struct Inst {
pub value: u16,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [t, i] = #[bitmatch]
@ -36,7 +36,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
let t = self.dst.idx();

View File

@ -3,7 +3,7 @@
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -99,7 +99,7 @@ impl Inst {
}
}
impl Decodable for Inst {
impl Decode for Inst {
#[rustfmt::skip]
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
@ -128,7 +128,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[rustfmt::skip]
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {

View File

@ -5,9 +5,8 @@ pub mod imm;
pub mod reg;
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode, ModifiesReg, TryEncode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -23,18 +22,28 @@ pub enum Inst {
Reg(reg::Inst),
}
impl Decodable for Inst {
impl Decode for Inst {
fn decode(raw: u32) -> Option<Self> {
None.or_else(|| imm::Inst::decode(raw).map(Self::Imm))
.or_else(|| reg::Inst::decode(raw).map(Self::Reg))
}
}
impl Encodable for Inst {
fn encode(&self) -> u32 {
/// Encode error
#[derive(PartialEq, Clone, Debug, thiserror::Error)]
pub enum EncodeError {
/// Unable to encode `imm` instruction
#[error("Unable to encode `imm` instruction")]
Imm(imm::EncodeError),
}
impl TryEncode for Inst {
type Error = EncodeError;
fn try_encode(&self) -> Result<u32, Self::Error> {
match self {
Self::Imm(inst) => inst.encode(),
Self::Reg(inst) => inst.encode(),
Self::Imm(inst) => inst.try_encode().map_err(EncodeError::Imm),
Self::Reg(inst) => Ok(inst.encode()),
}
}
}

View File

@ -2,7 +2,7 @@
// Imports
use crate::inst::{
basic::{Decodable, Encodable, ModifiesReg},
basic::{Decode, ModifiesReg, TryEncode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -50,7 +50,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [t, d, i, f] = #[bitmatch]
@ -75,11 +75,22 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
/// Encode error
#[derive(PartialEq, Clone, Debug, thiserror::Error)]
pub enum EncodeError {
/// Rhs is too large
#[error("rhs is too large")]
Rhs,
}
impl TryEncode for Inst {
type Error = EncodeError;
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
// TODO: Maybe return error?
assert!(self.rhs < 32);
fn try_encode(&self) -> Result<u32, Self::Error> {
if self.rhs >= 32 {
return Err(EncodeError::Rhs);
}
let f: u32 = match self.kind {
Kind::LeftLogical => 0x0,
@ -90,7 +101,7 @@ impl Encodable for Inst {
let d = self.dst.idx();
let i = self.rhs.zero_extended::<u32>();
bitpack!("000000_?????_ttttt_ddddd_iiiii_0000ff")
Ok(bitpack!("000000_?????_ttttt_ddddd_iiiii_0000ff"))
}
}

View File

@ -2,7 +2,7 @@
// Imports
use crate::inst::{
basic::{Decodable, Encodable, ModifiesReg},
basic::{Decode, Encode, ModifiesReg},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -48,7 +48,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [s, t, d, f] = #[bitmatch]
@ -73,7 +73,7 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
let f: u32 = match self.kind {

View File

@ -3,7 +3,7 @@
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, Encode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -60,7 +60,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [p, s, t, i] = #[bitmatch]
@ -86,7 +86,7 @@ impl Decodable for Inst {
})
}
}
impl Encodable for Inst {
impl Encode for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
let p: u32 = match self.kind {

View File

@ -3,7 +3,7 @@
// Imports
use super::ModifiesReg;
use crate::inst::{
basic::{Decodable, Encodable},
basic::{Decode, TryEncode},
parse::LineArg,
InstFmt, Parsable, ParseCtx, ParseError, Register,
};
@ -40,7 +40,7 @@ pub struct Inst {
pub kind: Kind,
}
impl Decodable for Inst {
impl Decode for Inst {
#[bitmatch::bitmatch]
fn decode(raw: u32) -> Option<Self> {
let [c, f] = #[bitmatch]
@ -59,11 +59,22 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
/// Encode error
#[derive(PartialEq, Clone, Debug, thiserror::Error)]
pub enum EncodeError {
/// Comment is too large
#[error("Comment is too large")]
Comment,
}
impl TryEncode for Inst {
type Error = EncodeError;
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
// TODO: Maybe return Error?
assert!(self.comment < 0x100000);
fn try_encode(&self) -> Result<u32, Self::Error> {
if self.comment >= 0x100000 {
return Err(EncodeError::Comment);
}
let c = self.comment;
let f: u32 = match self.kind {
@ -71,7 +82,7 @@ impl Encodable for Inst {
Kind::Break => 1,
};
bitpack!("000000_ccccc_ccccc_ccccc_ccccc_00110f")
Ok(bitpack!("000000_ccccc_ccccc_ccccc_ccccc_00110f"))
}
}