use crate::types::branch;
use super::decoder::{Decode, Decoder};
use super::encoder::{Encode, Encoder};
use super::{sync, unit, util, Error};
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Payload<I = unit::ReferenceIOptions, D = unit::ReferenceDOptions> {
InstructionTrace(InstructionTrace<I, D>),
DataTrace,
}
impl<I, D> Payload<I, D> {
pub fn as_instruction_trace(&self) -> Option<&InstructionTrace<I, D>> {
match self {
Payload::InstructionTrace(p) => Some(p),
_ => None,
}
}
}
impl<I, D> From<InstructionTrace<I, D>> for Payload<I, D> {
fn from(p: InstructionTrace<I, D>) -> Self {
Self::InstructionTrace(p)
}
}
impl<I, D> TryFrom<Payload<I, D>> for InstructionTrace<I, D> {
type Error = Payload<I, D>;
fn try_from(payload: Payload<I, D>) -> Result<Self, Self::Error> {
match payload {
Payload::InstructionTrace(p) => Ok(p),
p => Err(p),
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum BranchFmt {
NoAddr = 0,
Addr = 2,
AddrFail = 3,
}
impl<U> Decode<'_, '_, U> for BranchFmt {
fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
match decoder.read_bits::<u8>(2)? {
0b00 => Ok(BranchFmt::NoAddr),
0b01 => Err(Error::BadBranchFmt),
0b10 => Ok(BranchFmt::Addr),
0b11 => Ok(BranchFmt::AddrFail),
_ => unreachable!(),
}
}
}
impl<U> Encode<'_, U> for BranchFmt {
fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
let value: u8 = match self {
Self::NoAddr => 0b00,
Self::Addr => 0b10,
Self::AddrFail => 0b11,
};
encoder.write_bits(value, 2)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum InstructionTrace<I = unit::ReferenceIOptions, D = unit::ReferenceDOptions> {
Extension(Extension),
Branch(Branch),
Address(AddressInfo),
Synchronization(sync::Synchronization<I, D>),
}
impl<U: unit::Unit> Decode<'_, '_, U> for InstructionTrace<U::IOptions, U::DOptions> {
fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
match decoder.read_bits::<u8>(2)? {
0b00 => Extension::decode(decoder).map(Into::into),
0b01 => Branch::decode(decoder).map(Into::into),
0b10 => AddressInfo::decode(decoder).map(Into::into),
0b11 => sync::Synchronization::decode(decoder).map(Into::into),
_ => unreachable!(),
}
}
}
impl<'d, U> Encode<'d, U> for InstructionTrace<U::IOptions, U::DOptions>
where
U: unit::Unit,
U::IOptions: Encode<'d, U>,
U::DOptions: Encode<'d, U>,
{
fn encode(&self, encoder: &mut Encoder<'d, U>) -> Result<(), Error> {
match self {
Self::Extension(ext) => {
encoder.write_bits(0b00u8, 2)?;
encoder.encode(ext)
}
Self::Branch(branch) => {
encoder.write_bits(0b01u8, 2)?;
encoder.encode(branch)
}
Self::Address(addr) => {
encoder.write_bits(0b10u8, 2)?;
encoder.encode(addr)
}
Self::Synchronization(sync) => {
encoder.write_bits(0b11u8, 2)?;
encoder.encode(sync)
}
}
}
}
impl<I, D> InstructionTrace<I, D> {
pub fn get_address_info(&self) -> Option<&AddressInfo> {
match self {
Self::Address(addr) => Some(addr),
Self::Branch(branch) => branch.address.as_ref(),
Self::Extension(Extension::BranchCount(branch_count)) => branch_count.address.as_ref(),
_ => None,
}
}
pub fn implicit_return_depth(&self) -> Option<usize> {
match self {
Self::Address(a) => a.irdepth,
Self::Branch(b) => b.address.and_then(|a| a.irdepth),
Self::Extension(Extension::BranchCount(b)) => b.address.and_then(|a| a.irdepth),
Self::Extension(Extension::JumpTargetIndex(j)) => j.irdepth,
_ => None,
}
}
}
impl<I, D> From<Extension> for InstructionTrace<I, D> {
fn from(ex: Extension) -> Self {
Self::Extension(ex)
}
}
impl<I, D> From<BranchCount> for InstructionTrace<I, D> {
fn from(count: BranchCount) -> Self {
Self::Extension(Extension::BranchCount(count))
}
}
impl<I, D> From<JumpTargetIndex> for InstructionTrace<I, D> {
fn from(idx: JumpTargetIndex) -> Self {
Self::Extension(Extension::JumpTargetIndex(idx))
}
}
impl<I, D> From<Branch> for InstructionTrace<I, D> {
fn from(branch: Branch) -> Self {
Self::Branch(branch)
}
}
impl<I, D> From<AddressInfo> for InstructionTrace<I, D> {
fn from(addr: AddressInfo) -> Self {
Self::Address(addr)
}
}
impl<I, D> From<sync::Synchronization<I, D>> for InstructionTrace<I, D> {
fn from(sync: sync::Synchronization<I, D>) -> Self {
Self::Synchronization(sync)
}
}
impl<I, D> From<sync::Start> for InstructionTrace<I, D> {
fn from(start: sync::Start) -> Self {
Self::Synchronization(start.into())
}
}
impl<I, D> From<sync::Trap> for InstructionTrace<I, D> {
fn from(trap: sync::Trap) -> Self {
Self::Synchronization(trap.into())
}
}
impl<I, D> From<sync::Context> for InstructionTrace<I, D> {
fn from(ctx: sync::Context) -> Self {
Self::Synchronization(ctx.into())
}
}
impl<I, D> From<sync::Support<I, D>> for InstructionTrace<I, D> {
fn from(support: sync::Support<I, D>) -> Self {
Self::Synchronization(support.into())
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Extension {
BranchCount(BranchCount),
JumpTargetIndex(JumpTargetIndex),
}
impl<U> Decode<'_, '_, U> for Extension {
fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
match decoder.read_bits(decoder.widths().format0_subformat)? {
0 => BranchCount::decode(decoder).map(Self::BranchCount),
1 => JumpTargetIndex::decode(decoder).map(Self::JumpTargetIndex),
s => Err(Error::UnknownFmt(0, Some(s))),
}
}
}
impl<U> Encode<'_, U> for Extension {
fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
match self {
Self::BranchCount(branch) => encoder.encode(branch),
Self::JumpTargetIndex(jti) => encoder.encode(jti),
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct BranchCount {
pub branch_count: u32,
pub branch_fmt: BranchFmt,
pub address: Option<AddressInfo>,
}
impl<U> Decode<'_, '_, U> for BranchCount {
fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
let branch_count = decoder.read_bits::<u32>(32)? - 31;
let branch_fmt = BranchFmt::decode(decoder)?;
let address = if branch_fmt == BranchFmt::NoAddr {
None
} else {
Some(AddressInfo::decode(decoder)?)
};
Ok(BranchCount {
branch_count,
address,
branch_fmt,
})
}
}
impl<U> Encode<'_, U> for BranchCount {
fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
encoder.write_bits(self.branch_count + 31, 32)?;
encoder.encode(&self.branch_fmt)?;
if let Some(address) = self.address.as_ref() {
encoder.encode(address)?;
}
Ok(())
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct JumpTargetIndex {
pub index: usize,
pub branch_map: branch::Map,
pub irdepth: Option<usize>,
}
impl<U> Decode<'_, '_, U> for JumpTargetIndex {
fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
let index = decoder.read_bits(decoder.widths().cache_index)?;
let branch_map = util::BranchCount::decode(decoder)?.read_branch_map(decoder)?;
let irdepth = util::read_implicit_return(decoder)?;
Ok(JumpTargetIndex {
index,
branch_map,
irdepth,
})
}
}
impl<U> Encode<'_, U> for JumpTargetIndex {
fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
encoder.write_bits(self.index, encoder.widths().cache_index)?;
let count = util::BranchCount(self.branch_map.count());
encoder.encode(&count)?;
encoder.write_bits(self.branch_map.raw_map(), count.field_length())?;
util::write_implicit_return(encoder, self.irdepth)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Branch {
pub branch_map: branch::Map,
pub address: Option<AddressInfo>,
}
impl<U> Decode<'_, '_, U> for Branch {
fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
use util::BranchCount;
let count = BranchCount::decode(decoder)?;
if count.is_zero() {
let branch_map = BranchCount::FULL.read_branch_map(decoder)?;
Ok(Branch {
branch_map,
address: None,
})
} else {
let branch_map = count.read_branch_map(decoder)?;
let address = AddressInfo::decode(decoder)?;
Ok(Branch {
branch_map,
address: Some(address),
})
}
}
}
impl<U> Encode<'_, U> for Branch {
fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
if let Some(address) = self.address.as_ref() {
let count = util::BranchCount(self.branch_map.count());
encoder.encode(&count)?;
encoder.write_bits(self.branch_map.raw_map(), count.field_length())?;
encoder.encode(address)
} else {
encoder.encode(&util::BranchCount(0))?;
encoder.write_bits(self.branch_map.raw_map(), 31)
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AddressInfo {
pub address: i64,
pub notify: bool,
pub updiscon: bool,
pub irdepth: Option<usize>,
}
impl<U> Decode<'_, '_, U> for AddressInfo {
fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
let address = util::read_address(decoder)?;
let notify = decoder.read_differential_bit()?;
let updiscon = decoder.read_differential_bit()?;
let irdepth = util::read_implicit_return(decoder)?;
Ok(AddressInfo {
address,
notify,
updiscon,
irdepth,
})
}
}
impl<U> Encode<'_, U> for AddressInfo {
fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
util::write_address(encoder, self.address)?;
encoder.write_differential_bit(self.notify)?;
encoder.write_differential_bit(self.updiscon)?;
util::write_implicit_return(encoder, self.irdepth)
}
}