Added pseudo::Encodable.

This commit is contained in:
Filipe Rodrigues 2021-04-21 14:21:05 +01:00
parent 9a580f4345
commit 48c21f5e88
7 changed files with 163 additions and 27 deletions

View File

@ -19,6 +19,7 @@ ascii = { version = "1.0.0", features = ["serde"] }
int-conv = "0.1.4"
bitmatch = "0.1.1"
snailquote = "0.3.0"
auto_enums = "0.7.12"
# Serde
serde = { version = "1.0.120", features = ["derive"] }

View File

@ -45,6 +45,21 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
type Iterator = impl IntoIterator<Item = basic::Inst>;
#[auto_enums::auto_enum(Iterator)]
fn encode(&self) -> Self::Iterator {
match self {
Inst::LoadImm(inst) => inst.encode(),
Inst::Nop(inst) => inst.encode(),
Inst::MoveReg(inst) => inst.encode(),
Inst::Load(inst) => inst.encode(),
Inst::Store(inst) => inst.encode(),
}
}
}
impl InstSize for Inst {
fn size(&self) -> usize {
match self {
@ -76,11 +91,12 @@ pub trait Decodable: InstSize + Sized {
fn decode(insts: impl Iterator<Item = basic::Inst> + Clone) -> Option<Self>;
}
/*
/// An encodable pseudo instruction
pub trait Encodable: Decodable {
/// Encodes this instruction
pub trait Encodable {
/// Iterator type
type Iterator: IntoIterator<Item = basic::Inst>;
/// Encodes this instruction as basic instructions
#[must_use]
fn encode(&self) -> Self::Raw;
fn encode(&self) -> Self::Iterator;
}
*/

View File

@ -1,12 +1,12 @@
//! Load instructions
// Imports
use super::Decodable;
use super::{Decodable, Encodable};
use crate::{
inst::{basic, InstSize, InstTarget, InstTargetFmt, Register},
Pos,
};
use int_conv::{Join, SignExtended, Signed};
use int_conv::{Join, SignExtended, Signed, Split};
/// Load pseudo instructions
///
@ -46,6 +46,31 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
type Iterator = impl Iterator<Item = basic::Inst>;
fn encode(&self) -> Self::Iterator {
let addr = self.target.0;
let (lo, hi) = match addr.lo().as_signed() < 0 {
true => (u16::MAX - addr.lo(), addr.hi().wrapping_add(1)),
false => addr.lo_hi(),
};
std::array::IntoIter::new([
basic::Inst::Lui(basic::lui::Inst {
dst: self.value,
value: hi,
}),
basic::Inst::Load(basic::load::Inst {
value: self.value,
addr: self.value,
offset: lo.as_signed(),
kind: self.kind,
}),
])
}
}
impl InstSize for Inst {
fn size(&self) -> usize {
8

View File

@ -1,13 +1,13 @@
//! Load immediate
// Imports
use super::Decodable;
use super::{Decodable, Encodable};
use crate::{
inst::{basic, InstFmt, InstSize, InstTargetFmt, Register},
Pos,
};
use dcb_util::SignedHex;
use int_conv::{Join, SignExtended, Signed};
use int_conv::{Join, SignExtended, Signed, Split};
use std::convert::TryInto;
/// Immediate kind
@ -105,6 +105,54 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
type Iterator = impl Iterator<Item = basic::Inst>;
#[auto_enums::auto_enum(Iterator)]
fn encode(&self) -> Self::Iterator {
match self.kind {
Kind::Address(Pos(addr)) => {
let (lo, hi) = match addr.lo().as_signed() < 0 {
true => (u16::MAX - addr.lo(), addr.hi().wrapping_add(1)),
false => addr.lo_hi(),
};
std::array::IntoIter::new([
basic::Inst::Lui(basic::lui::Inst { dst: self.dst, value: hi }),
basic::Inst::Alu(basic::alu::Inst::Imm(basic::alu::imm::Inst {
dst: self.dst,
lhs: self.dst,
kind: basic::alu::imm::Kind::AddUnsigned(lo.as_signed()),
})),
])
},
Kind::Word(value) => {
let (lo, hi) = value.lo_hi();
std::array::IntoIter::new([
basic::Inst::Lui(basic::lui::Inst { dst: self.dst, value: hi }),
basic::Inst::Alu(basic::alu::Inst::Imm(basic::alu::imm::Inst {
dst: self.dst,
lhs: self.dst,
kind: basic::alu::imm::Kind::Or(lo),
})),
])
},
Kind::HalfWordUnsigned(value) => std::iter::once(basic::Inst::Alu(basic::alu::Inst::Imm(basic::alu::imm::Inst {
dst: self.dst,
lhs: Register::Zr,
kind: basic::alu::imm::Kind::Or(value),
}))),
Kind::HalfWordSigned(value) => std::iter::once(basic::Inst::Alu(basic::alu::Inst::Imm(basic::alu::imm::Inst {
dst: self.dst,
lhs: Register::Zr,
kind: basic::alu::imm::Kind::AddUnsigned(value),
}))),
}
}
}
impl InstSize for Inst {
fn size(&self) -> usize {
match self.kind {

View File

@ -1,7 +1,7 @@
//! Move register instruction
// Imports
use super::Decodable;
use super::{Decodable, Encodable};
use crate::inst::{basic, InstFmt, InstSize, Register};
use std::convert::TryInto;
@ -35,6 +35,19 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
type Iterator = impl Iterator<Item = basic::Inst>;
fn encode(&self) -> Self::Iterator {
std::iter::once(basic::Inst::Alu(basic::alu::Inst::Reg(basic::alu::reg::Inst {
dst: self.dst,
lhs: self.src,
rhs: Register::Zr,
kind: basic::alu::reg::Kind::AddUnsigned,
})))
}
}
impl InstSize for Inst {
fn size(&self) -> usize {
4

View File

@ -1,7 +1,7 @@
//! Nop
// Imports
use super::Decodable;
use super::{Decodable, Encodable};
use crate::inst::{basic, InstFmt, InstSize, Register};
/// No-op
@ -10,25 +10,23 @@ use crate::inst::{basic, InstFmt, InstSize, Register};
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct Inst {
/// Length of this nop, in instructions
len: usize,
pub len: usize,
}
impl Inst {
/// Instruction used by the nop
pub const INST: basic::Inst = basic::Inst::Shift(basic::shift::Inst::Imm(basic::shift::imm::Inst {
dst: Register::Zr,
lhs: Register::Zr,
rhs: 0,
kind: basic::shift::imm::Kind::LeftLogical,
}));
}
impl Decodable for Inst {
fn decode(insts: impl Iterator<Item = basic::Inst> + Clone) -> Option<Self> {
// Get how many nops there are, in a row
let len = insts
.take_while(|inst| {
matches!(
inst,
basic::Inst::Shift(basic::shift::Inst::Imm(basic::shift::imm::Inst {
dst: Register::Zr,
lhs: Register::Zr,
rhs: 0,
kind: basic::shift::imm::Kind::LeftLogical,
}))
)
})
.count();
let len = insts.take_while(|inst| matches!(inst, &Self::INST)).count();
match len {
0 => None,
@ -37,6 +35,16 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
type Iterator = impl Iterator<Item = basic::Inst>;
fn encode(&self) -> Self::Iterator {
std::iter::repeat(Self::INST).take(self.len)
}
}
impl InstSize for Inst {
fn size(&self) -> usize {
4 * self.len

View File

@ -1,12 +1,12 @@
//! Store instructions
// Imports
use super::Decodable;
use super::{Decodable, Encodable};
use crate::{
inst::{basic, InstSize, InstTarget, InstTargetFmt, Register},
Pos,
};
use int_conv::{Join, SignExtended, Signed};
use int_conv::{Join, SignExtended, Signed, Split};
/// Store pseudo instructions
///
@ -45,6 +45,31 @@ impl Decodable for Inst {
}
}
impl Encodable for Inst {
type Iterator = impl Iterator<Item = basic::Inst>;
fn encode(&self) -> Self::Iterator {
let addr = self.target.0;
let (lo, hi) = match addr.lo().as_signed() < 0 {
true => (u16::MAX - addr.lo(), addr.hi().wrapping_add(1)),
false => addr.lo_hi(),
};
std::array::IntoIter::new([
basic::Inst::Lui(basic::lui::Inst {
dst: Register::At,
value: hi,
}),
basic::Inst::Store(basic::store::Inst {
value: self.value,
addr: Register::At,
offset: lo.as_signed(),
kind: self.kind,
}),
])
}
}
impl InstSize for Inst {
fn size(&self) -> usize {
8