use crate::error::*;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Operand {
None,
MnemonicCondition(MnemonicCondition),
AddressMode(AddressMode),
Condition(Condition),
ConditionalInstruction(ConditionalInstruction),
ItCondition(ItCondition),
Register(Register),
SpecialRegister(SpecialRegister),
BankedRegister(BankedRegister),
RegisterList(RegisterList),
SignedImmediate(i32),
UnsignedImmediate(u32),
ModifiedImmediate(ModifiedImmediate),
Label(Label),
Shift(Shift),
ShiftType(ShiftType),
Iflags(Iflags),
BarrierOperation(BarrierOperation),
PlusMinus(PlusMinus),
WriteBack(WriteBack),
SysRegEncodingSpace(SysRegEncodingSpace),
SysRegRegister(SysRegRegister),
ApsrNzcv,
Endianness(Endianness),
}
impl Operand {
pub fn is_none(&self) -> bool {
if let Operand::None = self {
return true;
}
false
}
pub fn as_mnemonic_condition(&self) -> Result<&MnemonicCondition> {
if let Operand::MnemonicCondition(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_address_mode(&self) -> Result<&AddressMode> {
if let Operand::AddressMode(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_condition(&self) -> Result<&Condition> {
if let Operand::Condition(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_it_condition(&self) -> Result<&ItCondition> {
if let Operand::ItCondition(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_register(&self) -> Result<&Register> {
if let Operand::Register(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_special_register(&self) -> Result<&SpecialRegister> {
if let Operand::SpecialRegister(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_banked_register(&self) -> Result<&BankedRegister> {
if let Operand::BankedRegister(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_register_list(&self) -> Result<&RegisterList> {
if let Operand::RegisterList(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_signed_immediate(&self) -> Result<i32> {
if let Operand::SignedImmediate(value) = self {
return Ok(*value);
}
todo!()
}
pub fn as_unsigned_immediate(&self) -> Result<u32> {
if let Operand::UnsignedImmediate(uimm) = self {
return Ok(*uimm);
}
if let Operand::SignedImmediate(uimm) = self {
return Ok(*uimm as u32);
}
todo!()
}
pub fn as_label(&self) -> Result<&Label> {
if let Operand::Label(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_modified_immediate(&self) -> Result<&ModifiedImmediate> {
if let Operand::ModifiedImmediate(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_shift(&self) -> Result<&Shift> {
if let Operand::Shift(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_shift_type(&self) -> Result<&ShiftType> {
if let Operand::ShiftType(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_iflags(&self) -> Result<&Iflags> {
if let Operand::Iflags(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_barrier_operation(&self) -> Result<&BarrierOperation> {
if let Operand::BarrierOperation(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_plus_minus(&self) -> Result<&PlusMinus> {
if let Operand::PlusMinus(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_write_back(&self) -> Result<&WriteBack> {
if let Operand::WriteBack(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_sysreg_encoding_space(&self) -> Result<&SysRegEncodingSpace> {
if let Operand::SysRegEncodingSpace(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_sysreg_register(&self) -> Result<&SysRegRegister> {
if let Operand::SysRegRegister(value) = self {
return Ok(value);
}
todo!()
}
pub fn as_endianness(&self) -> Result<&Endianness> {
if let Operand::Endianness(value) = self {
return Ok(value);
}
todo!()
}
}
impl Default for Operand {
fn default() -> Self {
Operand::None
}
}
impl From<MnemonicCondition> for Operand {
fn from(value: MnemonicCondition) -> Self {
Operand::MnemonicCondition(value)
}
}
impl From<AddressMode> for Operand {
fn from(value: AddressMode) -> Self {
Operand::AddressMode(value)
}
}
impl From<Condition> for Operand {
fn from(value: Condition) -> Self {
Operand::Condition(value)
}
}
impl From<ItCondition> for Operand {
fn from(value: ItCondition) -> Self {
Operand::ItCondition(value)
}
}
impl From<Register> for Operand {
fn from(value: Register) -> Self {
Operand::Register(value)
}
}
impl From<SpecialRegister> for Operand {
fn from(value: SpecialRegister) -> Self {
Operand::SpecialRegister(value)
}
}
impl From<BankedRegister> for Operand {
fn from(value: BankedRegister) -> Self {
Operand::BankedRegister(value)
}
}
impl From<RegisterList> for Operand {
fn from(value: RegisterList) -> Self {
Operand::RegisterList(value)
}
}
impl From<&[Register]> for Operand {
fn from(value: &[Register]) -> Self {
let value = value
.iter()
.fold(0, |acc, register| acc | (1 << *register as usize));
Operand::RegisterList(RegisterList::decode(value))
}
}
impl From<u32> for Operand {
fn from(value: u32) -> Self {
Operand::UnsignedImmediate(value)
}
}
impl From<i32> for Operand {
fn from(value: i32) -> Self {
Operand::SignedImmediate(value)
}
}
impl From<ModifiedImmediate> for Operand {
fn from(value: ModifiedImmediate) -> Self {
Operand::ModifiedImmediate(value)
}
}
impl From<Label> for Operand {
fn from(value: Label) -> Self {
Operand::Label(value)
}
}
impl From<Shift> for Operand {
fn from(value: Shift) -> Self {
Operand::Shift(value)
}
}
impl From<ShiftType> for Operand {
fn from(value: ShiftType) -> Self {
Operand::ShiftType(value)
}
}
impl From<Iflags> for Operand {
fn from(value: Iflags) -> Self {
Operand::Iflags(value)
}
}
impl From<BarrierOperation> for Operand {
fn from(value: BarrierOperation) -> Self {
Operand::BarrierOperation(value)
}
}
impl From<PlusMinus> for Operand {
fn from(value: PlusMinus) -> Self {
Operand::PlusMinus(value)
}
}
impl From<WriteBack> for Operand {
fn from(value: WriteBack) -> Self {
Operand::WriteBack(value)
}
}
impl From<SysRegEncodingSpace> for Operand {
fn from(value: SysRegEncodingSpace) -> Self {
Operand::SysRegEncodingSpace(value)
}
}
impl From<SysRegRegister> for Operand {
fn from(value: SysRegRegister) -> Self {
Operand::SysRegRegister(value)
}
}
impl From<Endianness> for Operand {
fn from(value: Endianness) -> Self {
Operand::Endianness(value)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum MnemonicCondition {
Eq,
Ne,
Cs,
Cc,
Mi,
Pl,
Vs,
Vc,
Hi,
Ls,
Ge,
Lt,
Gt,
Le,
Al,
}
impl MnemonicCondition {
pub fn decode(value: u32) -> Result<Self> {
match value {
0b0000 => Ok(Self::Eq),
0b0001 => Ok(Self::Ne),
0b0010 => Ok(Self::Cs),
0b0011 => Ok(Self::Cc),
0b0100 => Ok(Self::Mi),
0b0101 => Ok(Self::Pl),
0b0110 => Ok(Self::Vs),
0b0111 => Ok(Self::Vc),
0b1000 => Ok(Self::Hi),
0b1001 => Ok(Self::Ls),
0b1010 => Ok(Self::Ge),
0b1011 => Ok(Self::Lt),
0b1100 => Ok(Self::Gt),
0b1101 => Ok(Self::Le),
0b1110 => Ok(Self::Al),
_ => Err(OperandError::MnemonicConditionOutOfRange(value))?,
}
}
pub fn encode(self) -> u32 {
match self {
Self::Eq => 0b0000,
Self::Ne => 0b0001,
Self::Cs => 0b0010,
Self::Cc => 0b0011,
Self::Mi => 0b0100,
Self::Pl => 0b0101,
Self::Vs => 0b0110,
Self::Vc => 0b0111,
Self::Hi => 0b1000,
Self::Ls => 0b1001,
Self::Ge => 0b1010,
Self::Lt => 0b1011,
Self::Gt => 0b1100,
Self::Le => 0b1101,
Self::Al => 0b1110,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::Eq => "eq",
Self::Ne => "ne",
Self::Cs => "hs",
Self::Cc => "lo",
Self::Mi => "mi",
Self::Pl => "pl",
Self::Vs => "vs",
Self::Vc => "vc",
Self::Hi => "hi",
Self::Ls => "ls",
Self::Ge => "ge",
Self::Lt => "lt",
Self::Gt => "gt",
Self::Le => "le",
Self::Al => "al",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum AddressMode {
DecrementAfter,
FullAscending,
DecrementBefore,
EmptyAscending,
IncrementAfter,
FullDescending,
IncrementBefore,
EmptyDescending,
}
#[allow(non_upper_case_globals)]
impl AddressMode {
pub const DA: Self = Self::DecrementAfter;
pub const FA: Self = Self::FullAscending;
pub const DB: Self = Self::DecrementBefore;
pub const EA: Self = Self::EmptyAscending;
pub const IA: Self = Self::IncrementAfter;
pub const FD: Self = Self::FullDescending;
pub const IB: Self = Self::IncrementBefore;
pub const ED: Self = Self::EmptyDescending;
pub fn decode(value: u32) -> Self {
match (value & 2, value & 1) {
(0, 0) => Self::DecrementAfter,
(0, 1) => Self::DecrementBefore,
(2, 0) => Self::IncrementAfter,
(2, 1) => Self::IncrementBefore,
_ => unreachable!(),
}
}
pub fn encode(self) -> u32 {
match self {
Self::DecrementAfter => 0,
Self::FullAscending => 0,
Self::DecrementBefore => 1,
Self::EmptyAscending => 1,
Self::IncrementAfter => 2,
Self::FullDescending => 2,
Self::IncrementBefore => 3,
Self::EmptyDescending => 3,
}
}
pub fn as_str(self) -> &'static str {
match self {
Self::DecrementAfter => "da",
Self::FullAscending => "fa",
Self::DecrementBefore => "db",
Self::EmptyAscending => "ea",
Self::IncrementAfter => "ia",
Self::FullDescending => "fd",
Self::IncrementBefore => "ib",
Self::EmptyDescending => "ed",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum AssemblerQualifier {
None,
Narrow,
Wide,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum PlusMinus {
Plus,
Minus,
}
impl PlusMinus {
pub fn decode(value: u32) -> Self {
match value {
0 => Self::Minus,
_ => Self::Plus,
}
}
pub fn encode(self) -> u32 {
match self {
Self::Minus => 0,
Self::Plus => 1,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum WriteBack {
True,
False,
}
impl WriteBack {
pub fn decode(value: u32) -> Self {
match value {
1 => Self::True,
_ => Self::False,
}
}
pub fn encode(self) -> u32 {
match self {
Self::False => 0,
Self::True => 1,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Register {
R0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
}
impl Register {
pub const SP: Self = Self::R13;
pub const LR: Self = Self::R14;
pub const PC: Self = Self::R15;
pub fn decode(value: u32) -> Result<Self> {
match value {
0 => Ok(Self::R0),
1 => Ok(Self::R1),
2 => Ok(Self::R2),
3 => Ok(Self::R3),
4 => Ok(Self::R4),
5 => Ok(Self::R5),
6 => Ok(Self::R6),
7 => Ok(Self::R7),
8 => Ok(Self::R8),
9 => Ok(Self::R9),
10 => Ok(Self::R10),
11 => Ok(Self::R11),
12 => Ok(Self::R12),
13 => Ok(Self::R13),
14 => Ok(Self::R14),
15 => Ok(Self::R15),
_ => Err(OperandError::RegisterOutOfRange(value))?,
}
}
pub fn encode(self) -> u32 {
match self {
Self::R0 => 0,
Self::R1 => 1,
Self::R2 => 2,
Self::R3 => 3,
Self::R4 => 4,
Self::R5 => 5,
Self::R6 => 6,
Self::R7 => 7,
Self::R8 => 8,
Self::R9 => 9,
Self::R10 => 10,
Self::R11 => 11,
Self::R12 => 12,
Self::R13 => 13,
Self::R14 => 14,
Self::R15 => 15,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::R0 => "r0",
Self::R1 => "r1",
Self::R2 => "r2",
Self::R3 => "r3",
Self::R4 => "r4",
Self::R5 => "r5",
Self::R6 => "r6",
Self::R7 => "r7",
Self::R8 => "r8",
Self::R9 => "r9",
Self::R10 => "r10",
Self::R11 => "r11",
Self::R12 => "r12",
Self::R13 => "sp",
Self::R14 => "lr",
Self::R15 => "pc",
}
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum SpecialRegister {
CPSR,
CPSR_c,
CPSR_x,
CPSR_xc,
CPSR_s,
CPSR_sc,
CPSR_sx,
CPSR_sxc,
CPSR_f,
CPSR_fc,
CPSR_fx,
CPSR_fxc,
CPSR_fs,
CPSR_fsc,
CPSR_fsx,
CPSR_fsxc,
SPSR,
SPSR_c,
SPSR_x,
SPSR_xc,
SPSR_s,
SPSR_sc,
SPSR_sx,
SPSR_sxc,
SPSR_f,
SPSR_fc,
SPSR_fx,
SPSR_fxc,
SPSR_fs,
SPSR_fsc,
SPSR_fsx,
SPSR_fsxc,
APSR,
APSR_nzcvq,
APSR_g,
APSR_nzcvqg,
}
impl SpecialRegister {
pub fn decode(r: u32, mask: u32, as_apsr: bool) -> Result<Self> {
let f = (mask >> 0) & 1;
let s = (mask >> 1) & 1;
let x = (mask >> 2) & 1;
let c = (mask >> 3) & 1;
Ok(match (r, c, x, s, f) {
(0, 0, 0, 0, 1) => Self::CPSR_c,
(0, 0, 0, 1, 0) => Self::CPSR_x,
(0, 0, 0, 1, 1) => Self::CPSR_xc,
(0, 0, 1, 0, 0) => {
if as_apsr {
Self::APSR_g
} else {
Self::CPSR_s
}
}
(0, 0, 1, 0, 1) => Self::CPSR_sc,
(0, 0, 1, 1, 0) => Self::CPSR_sx,
(0, 0, 1, 1, 1) => Self::CPSR_sxc,
(0, 1, 0, 0, 0) => {
if as_apsr {
Self::APSR_nzcvq
} else {
Self::CPSR_f
}
}
(0, 1, 0, 0, 1) => Self::CPSR_fc,
(0, 1, 0, 1, 0) => Self::CPSR_fx,
(0, 1, 0, 1, 1) => Self::CPSR_fxc,
(0, 1, 1, 0, 0) => {
if as_apsr {
Self::APSR_nzcvqg
} else {
Self::CPSR_fs
}
}
(0, 1, 1, 0, 1) => Self::CPSR_fsc,
(0, 1, 1, 1, 0) => Self::CPSR_fsx,
(0, 1, 1, 1, 1) => Self::CPSR_fsxc,
(1, 0, 0, 0, 0) => Self::SPSR,
(1, 0, 0, 0, 1) => Self::SPSR_c,
(1, 0, 0, 1, 0) => Self::SPSR_x,
(1, 0, 0, 1, 1) => Self::SPSR_xc,
(1, 0, 1, 0, 0) => Self::SPSR_s,
(1, 0, 1, 0, 1) => Self::SPSR_sc,
(1, 0, 1, 1, 0) => Self::SPSR_sx,
(1, 0, 1, 1, 1) => Self::SPSR_sxc,
(1, 1, 0, 0, 0) => Self::SPSR_f,
(1, 1, 0, 0, 1) => Self::SPSR_fc,
(1, 1, 0, 1, 0) => Self::SPSR_fx,
(1, 1, 0, 1, 1) => Self::SPSR_fxc,
(1, 1, 1, 0, 0) => Self::SPSR_fs,
(1, 1, 1, 0, 1) => Self::SPSR_fsc,
(1, 1, 1, 1, 0) => Self::SPSR_fsx,
(1, 1, 1, 1, 1) => Self::SPSR_fsxc,
x => todo!("{:#?}", x),
})
}
pub fn encode(self) -> Result<(u32, u32)> {
let (r, c, x, s, f) = match self {
Self::CPSR_c => (0, 0, 0, 0, 1),
Self::CPSR_x => (0, 0, 0, 1, 0),
Self::CPSR_xc => (0, 0, 0, 1, 1),
Self::CPSR_s | Self::APSR_g => (0, 0, 1, 0, 0),
Self::CPSR_sc => (0, 0, 1, 0, 1),
Self::CPSR_sx => (0, 0, 1, 1, 0),
Self::CPSR_sxc => (0, 0, 1, 1, 1),
Self::CPSR_f | Self::APSR_nzcvq => (0, 1, 0, 0, 0),
Self::CPSR_fc => (0, 1, 0, 0, 1),
Self::CPSR_fx => (0, 1, 0, 1, 0),
Self::CPSR_fxc => (0, 1, 0, 1, 1),
Self::CPSR_fs | Self::APSR_nzcvqg => (0, 1, 1, 0, 0),
Self::CPSR_fsc => (0, 1, 1, 0, 1),
Self::CPSR_fsx => (0, 1, 1, 1, 0),
Self::CPSR_fsxc => (0, 1, 1, 1, 1),
Self::SPSR => (1, 0, 0, 0, 0),
Self::SPSR_c => (1, 0, 0, 0, 1),
Self::SPSR_x => (1, 0, 0, 1, 0),
Self::SPSR_xc => (1, 0, 0, 1, 1),
Self::SPSR_s => (1, 0, 1, 0, 0),
Self::SPSR_sc => (1, 0, 1, 0, 1),
Self::SPSR_sx => (1, 0, 1, 1, 0),
Self::SPSR_sxc => (1, 0, 1, 1, 1),
Self::SPSR_f => (1, 1, 0, 0, 0),
Self::SPSR_fc => (1, 1, 0, 0, 1),
Self::SPSR_fx => (1, 1, 0, 1, 0),
Self::SPSR_fxc => (1, 1, 0, 1, 1),
Self::SPSR_fs => (1, 1, 1, 0, 0),
Self::SPSR_fsc => (1, 1, 1, 0, 1),
Self::SPSR_fsx => (1, 1, 1, 1, 0),
Self::SPSR_fsxc => (1, 1, 1, 1, 1),
x => todo!("{:#?}", x),
};
let mask = (c << 3) | (x << 2) | (s << 1) | f;
Ok((r, mask))
}
pub fn as_str(&self) -> &str {
match self {
Self::CPSR => "CPSR",
Self::CPSR_c => "CPSR_c",
Self::CPSR_x => "CPSR_x",
Self::CPSR_xc => "CPSR_xc",
Self::CPSR_s => "CPSR_s",
Self::CPSR_sc => "CPSR_sc",
Self::CPSR_sx => "CPSR_sx",
Self::CPSR_sxc => "CPSR_sxc",
Self::CPSR_f => "CPSR_f",
Self::CPSR_fc => "CPSR_fc",
Self::CPSR_fx => "CPSR_fx",
Self::CPSR_fxc => "CPSR_fxc",
Self::CPSR_fs => "CPSR_fs",
Self::CPSR_fsc => "CPSR_fsc",
Self::CPSR_fsx => "CPSR_fsx",
Self::CPSR_fsxc => "CPSR_fsxc",
Self::SPSR => "SPSR",
Self::SPSR_c => "SPSR_c",
Self::SPSR_x => "SPSR_x",
Self::SPSR_xc => "SPSR_xc",
Self::SPSR_s => "SPSR_s",
Self::SPSR_sc => "SPSR_sc",
Self::SPSR_sx => "SPSR_sx",
Self::SPSR_sxc => "SPSR_sxc",
Self::SPSR_f => "SPSR_f",
Self::SPSR_fc => "SPSR_fc",
Self::SPSR_fx => "SPSR_fx",
Self::SPSR_fxc => "SPSR_fxc",
Self::SPSR_fs => "SPSR_fs",
Self::SPSR_fsc => "SPSR_fsc",
Self::SPSR_fsx => "SPSR_fsx",
Self::SPSR_fsxc => "SPSR_fsxc",
Self::APSR => "APSR",
Self::APSR_nzcvq => "APSR_nzcvq",
Self::APSR_g => "APSR_g",
Self::APSR_nzcvqg => "APSR_nzcvqg",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum BankedRegister {
R8Usr,
R9Usr,
R10Usr,
R11Usr,
R12Usr,
SpUsr,
LrUsr,
R8Fiq,
R9Fiq,
R10Fiq,
R11Fiq,
R12Fiq,
SpFiq,
LrFiq,
LrIrq,
SpIrq,
LrSvc,
SpSvc,
LrAbt,
SpAbt,
LrUnd,
SpUnd,
LrMon,
SpMon,
ElrHyp,
SpHyp,
SpsrFiq,
SpsrIrq,
SpsrSvc,
SpsrAbt,
SpsrUnd,
SpsrMon,
SpsrHyp,
}
impl BankedRegister {
pub fn as_str(&self) -> &str {
match self {
Self::R8Usr => "r8_usr",
Self::R9Usr => "r9_usr",
Self::R10Usr => "r10_usr",
Self::R11Usr => "r11_usr",
Self::R12Usr => "r12_usr",
Self::SpUsr => "sp_usr",
Self::LrUsr => "lr_usr",
Self::R8Fiq => "r8_fiq",
Self::R9Fiq => "r9_fiq",
Self::R10Fiq => "r10_fiq",
Self::R11Fiq => "r11_fiq",
Self::R12Fiq => "r12_fiq",
Self::SpFiq => "sp_fiq",
Self::LrFiq => "lr_fiq",
Self::LrIrq => "lr_irq",
Self::SpIrq => "sp_irq",
Self::LrSvc => "lr_svc",
Self::SpSvc => "sp_svc",
Self::LrAbt => "lr_abt",
Self::SpAbt => "sp_abt",
Self::LrUnd => "lr_und",
Self::SpUnd => "sp_und",
Self::LrMon => "lr_mon",
Self::SpMon => "sp_mon",
Self::ElrHyp => "elr_hyp",
Self::SpHyp => "sp_hyp",
Self::SpsrFiq => "SPSR_fiq",
Self::SpsrIrq => "SPSR_irq",
Self::SpsrSvc => "SPSR_svc",
Self::SpsrAbt => "SPSR_abt",
Self::SpsrUnd => "SPSR_und",
Self::SpsrMon => "SPSR_mon",
Self::SpsrHyp => "SPSR_hyp",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub struct RegisterList(pub u16);
impl RegisterList {
pub fn decode(value: u32) -> Self {
Self(value as u16)
}
pub fn encode(self) -> u32 {
self.0 as u32
}
pub fn value(self) -> Vec<Register> {
(0..16)
.into_iter()
.filter(|i| (self.0 >> i) & 1 == 1)
.fold(vec![], |mut acc, x| {
acc.push(Register::decode(x).unwrap());
acc
})
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Condition {
Eq,
Ne,
Cs,
Cc,
Mi,
Pl,
Vs,
Vc,
Hi,
Ls,
Ge,
Lt,
Gt,
Le,
Al,
}
impl Condition {
pub fn decode(value: u32) -> Result<Self> {
match value {
0b0000 => Ok(Self::Eq),
0b0001 => Ok(Self::Ne),
0b0010 => Ok(Self::Cs),
0b0011 => Ok(Self::Cc),
0b0100 => Ok(Self::Mi),
0b0101 => Ok(Self::Pl),
0b0110 => Ok(Self::Vs),
0b0111 => Ok(Self::Vc),
0b1000 => Ok(Self::Hi),
0b1001 => Ok(Self::Ls),
0b1010 => Ok(Self::Ge),
0b1011 => Ok(Self::Lt),
0b1100 => Ok(Self::Gt),
0b1101 => Ok(Self::Le),
0b1110 => Ok(Self::Al),
_ => Err(OperandError::ConditionOutOfRange(value))?,
}
}
pub fn encode(self) -> u32 {
match self {
Self::Eq => 0b0000,
Self::Ne => 0b0001,
Self::Cs => 0b0010,
Self::Cc => 0b0011,
Self::Mi => 0b0100,
Self::Pl => 0b0101,
Self::Vs => 0b0110,
Self::Vc => 0b0111,
Self::Hi => 0b1000,
Self::Ls => 0b1001,
Self::Ge => 0b1010,
Self::Lt => 0b1011,
Self::Gt => 0b1100,
Self::Le => 0b1101,
Self::Al => 0b1110,
}
}
pub fn opposite(self) -> Self {
match self {
Self::Eq => Self::Ne,
Self::Ne => Self::Eq,
Self::Cs => Self::Cc,
Self::Cc => Self::Cs,
Self::Mi => Self::Pl,
Self::Pl => Self::Mi,
Self::Vs => Self::Vc,
Self::Vc => Self::Vs,
Self::Hi => Self::Ls,
Self::Ls => Self::Hi,
Self::Ge => Self::Lt,
Self::Lt => Self::Ge,
Self::Gt => Self::Le,
Self::Le => Self::Gt,
_ => todo!(),
}
}
pub fn as_str(&self) -> &str {
match self {
Self::Eq => "eq",
Self::Ne => "ne",
Self::Cs => "hs",
Self::Cc => "lo",
Self::Mi => "mi",
Self::Pl => "pl",
Self::Vs => "vs",
Self::Vc => "vc",
Self::Hi => "hi",
Self::Ls => "ls",
Self::Ge => "ge",
Self::Lt => "lt",
Self::Gt => "gt",
Self::Le => "le",
Self::Al => "al",
}
}
}
impl From<Condition> for MnemonicCondition {
fn from(value: Condition) -> Self {
match value {
Condition::Eq => Self::Eq,
Condition::Ne => Self::Ne,
Condition::Cs => Self::Cs,
Condition::Cc => Self::Cc,
Condition::Mi => Self::Mi,
Condition::Pl => Self::Pl,
Condition::Vs => Self::Vs,
Condition::Vc => Self::Vc,
Condition::Hi => Self::Hi,
Condition::Ls => Self::Ls,
Condition::Ge => Self::Ge,
Condition::Lt => Self::Lt,
Condition::Gt => Self::Gt,
Condition::Le => Self::Le,
Condition::Al => Self::Al,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum ItCondition {
None,
If,
Else,
}
impl ItCondition {
pub fn is_none(&self) -> bool {
if let ItCondition::None = self {
return true;
}
false
}
pub fn decode(value: u32, firstcond: u32, position: u32) -> Result<Self> {
if position == 0 || position > 3 {
todo!()
}
let shift = 4 - position;
let mask = (1 << shift) - 1;
if value & mask == 0 {
return Ok(Self::None);
} else if (value >> shift) & 1 == firstcond & 1 {
return Ok(Self::If);
} else {
return Ok(Self::Else);
}
}
pub fn encode(self, firstcond: u32, position: u32) -> u32 {
match self {
Self::None => 1 << (4 - position),
Self::If => (firstcond & 1) << (4 - position) | if position == 3 { 1 } else { 0 },
Self::Else => {
((firstcond + 1) % 2) << (4 - position) | if position == 3 { 1 } else { 0 }
}
}
}
pub fn as_str(&self) -> &str {
match self {
Self::None => "",
Self::If => "t",
Self::Else => "e",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum ConditionalInstruction {
None,
ItBlock(Condition, ItCondition, ItCondition, ItCondition),
Condition(usize, bool, bool),
}
impl ConditionalInstruction {
pub fn encode(self) -> (u32, u32) {
match self {
Self::ItBlock(cond, ic1, ic2, ic3) => {
let firstcond = cond.encode();
let mut mask = 0;
mask |= ic1.encode(firstcond, 1);
if ic1.is_none() {
return (firstcond, mask);
}
mask |= ic2.encode(firstcond, 2);
if ic2.is_none() {
return (firstcond, mask);
}
mask |= ic3.encode(firstcond, 3);
return (firstcond, mask);
}
_ => todo!(),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub struct ModifiedImmediate(pub u32, pub u32);
impl ModifiedImmediate {
pub fn decode(value: u32) -> Self {
let rotation = (value >> 8) & 0xf;
let value = value & 0xff;
Self(rotation, value)
}
pub fn encode(self) -> u32 {
(self.0 << 8) | self.1
}
pub fn value(self) -> u32 {
self.1.rotate_right(self.0 * 2)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Label {
LabelName(u64),
Label(i32),
LabelModified(ModifiedImmediate),
LabelModifiedNegative(ModifiedImmediate),
}
impl Label {
pub fn decode(value: i64, modified: bool) -> Self {
if modified {
if value < 0 {
Self::LabelModifiedNegative(ModifiedImmediate::decode(-value as u32))
} else {
Self::LabelModified(ModifiedImmediate::decode(value as u32))
}
} else {
Self::Label(value as i32)
}
}
pub fn encode(self) -> Result<u32> {
match self {
Self::Label(imm) => Ok(imm as u32),
Self::LabelModified(imm) => Ok(imm.encode()),
Self::LabelModifiedNegative(imm) => Ok(imm.encode()),
Self::LabelName(_) => todo!(),
}
}
pub fn value(self) -> i64 {
match self {
Self::Label(imm) => imm as i64,
Self::LabelModified(imm) => imm.value() as i64,
Self::LabelModifiedNegative(imm) => -(imm.value() as i64),
Self::LabelName(imm) => imm as i64,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Shift {
LSL(u32),
LSR(u32),
ASR(u32),
ROR(u32),
RRX,
}
impl Shift {
pub fn value(self) -> u32 {
match self {
Self::LSL(imm) => imm,
Self::LSR(imm) => imm,
Self::ASR(imm) => imm,
Self::ROR(imm) => imm,
Self::RRX => 1,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::LSL(_) => "lsl",
Self::LSR(_) => "lsr",
Self::ASR(_) => "asr",
Self::ROR(_) => "ror",
Self::RRX => "rrx",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum ShiftType {
LSL,
LSR,
ASR,
ROR,
}
impl ShiftType {
pub fn as_str(&self) -> &str {
match self {
Self::LSL => "lsl",
Self::LSR => "lsr",
Self::ASR => "asr",
Self::ROR => "ror",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub struct Iflags {
pub a: bool,
pub i: bool,
pub f: bool,
}
impl Iflags {
pub fn decode(a: u32, i: u32, f: u32) -> Self {
Self {
a: a != 0,
i: i != 0,
f: f != 0,
}
}
pub fn encode(self) -> (u32, u32, u32) {
(self.a as u32, self.i as u32, self.f as u32)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum BarrierOperation {
Ssbb,
Pssbb,
Sy,
St,
Ld,
Ish,
Ishst,
Ishld,
Nsh,
Nshst,
Nshld,
Osh,
Oshst,
Oshld,
Reserved(u8),
}
impl BarrierOperation {
pub fn decode_dsb(value: u32) -> Self {
match value {
0b0000 => Self::Ssbb,
0b0001 => Self::Oshld,
0b0010 => Self::Oshst,
0b0011 => Self::Osh,
0b0100 => Self::Pssbb,
0b0101 => Self::Nshld,
0b0110 => Self::Nshst,
0b0111 => Self::Nsh,
0b1001 => Self::Ishld,
0b1010 => Self::Ishst,
0b1011 => Self::Ish,
0b1101 => Self::Ld,
0b1110 => Self::St,
0b1111 => Self::Sy,
_ => Self::Reserved(value as u8),
}
}
pub fn decode_dmb(value: u32) -> Self {
match value {
0b0001 => Self::Oshld,
0b0010 => Self::Oshst,
0b0011 => Self::Osh,
0b0101 => Self::Nshld,
0b0110 => Self::Nshst,
0b0111 => Self::Nsh,
0b1001 => Self::Ishld,
0b1010 => Self::Ishst,
0b1011 => Self::Ish,
0b1101 => Self::Ld,
0b1110 => Self::St,
0b1111 => Self::Sy,
_ => Self::Reserved(value as u8),
}
}
pub fn decode_isb(value: u32) -> Self {
match value {
0b1111 => Self::Sy,
_ => Self::Reserved(value as u8),
}
}
pub fn encode(self) -> u32 {
match self {
Self::Ssbb => 0b0000,
Self::Oshld => 0b0001,
Self::Oshst => 0b0010,
Self::Osh => 0b0011,
Self::Pssbb => 0b0100,
Self::Nshld => 0b0101,
Self::Nshst => 0b0110,
Self::Nsh => 0b0111,
Self::Ishld => 0b1001,
Self::Ishst => 0b1010,
Self::Ish => 0b1011,
Self::Ld => 0b1101,
Self::St => 0b1110,
Self::Sy => 0b1111,
Self::Reserved(x) => x as u32,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::Ssbb => "ssbb",
Self::Oshld => "oshld",
Self::Oshst => "oshst",
Self::Osh => "osh",
Self::Pssbb => "pssbb",
Self::Nshld => "nshld",
Self::Nshst => "nshst",
Self::Nsh => "nsh",
Self::Ishld => "ishld",
Self::Ishst => "ishst",
Self::Ish => "ish",
Self::Ld => "ld",
Self::St => "st",
Self::Sy => "sy",
Self::Reserved(_) => "reserved",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum SysRegEncodingSpace {
P14,
P15,
}
impl SysRegEncodingSpace {
pub fn decode(value: u32) -> Result<Self> {
Ok(match value {
0 => Self::P14,
1 => Self::P15,
_ => todo!(),
})
}
pub fn encode(self) -> u32 {
match self {
Self::P14 => 0,
Self::P15 => 1,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::P14 => "p14",
Self::P15 => "p15",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum SysRegRegister {
C0,
C1,
C2,
C3,
C4,
C5,
C6,
C7,
C8,
C9,
C10,
C11,
C12,
C13,
C14,
C15,
}
impl SysRegRegister {
pub fn decode(value: u32) -> Result<Self> {
match value {
0 => Ok(Self::C0),
1 => Ok(Self::C1),
2 => Ok(Self::C2),
3 => Ok(Self::C3),
4 => Ok(Self::C4),
5 => Ok(Self::C5),
6 => Ok(Self::C6),
7 => Ok(Self::C7),
8 => Ok(Self::C8),
9 => Ok(Self::C9),
10 => Ok(Self::C10),
11 => Ok(Self::C11),
12 => Ok(Self::C12),
13 => Ok(Self::C13),
14 => Ok(Self::C14),
15 => Ok(Self::C15),
_ => Err(OperandError::RegisterOutOfRange(value))?,
}
}
pub fn encode(self) -> u32 {
match self {
Self::C0 => 0,
Self::C1 => 1,
Self::C2 => 2,
Self::C3 => 3,
Self::C4 => 4,
Self::C5 => 5,
Self::C6 => 6,
Self::C7 => 7,
Self::C8 => 8,
Self::C9 => 9,
Self::C10 => 10,
Self::C11 => 11,
Self::C12 => 12,
Self::C13 => 13,
Self::C14 => 14,
Self::C15 => 15,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::C0 => "c0",
Self::C1 => "c1",
Self::C2 => "c2",
Self::C3 => "c3",
Self::C4 => "c4",
Self::C5 => "c5",
Self::C6 => "c6",
Self::C7 => "c7",
Self::C8 => "c8",
Self::C9 => "c9",
Self::C10 => "c10",
Self::C11 => "c11",
Self::C12 => "c12",
Self::C13 => "c13",
Self::C14 => "c14",
Self::C15 => "c15",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Endianness {
Le,
Be,
}
impl Endianness {
pub fn decode(value: u32) -> Result<Self> {
match value {
0 => Ok(Self::Le),
1 => Ok(Self::Be),
_ => todo!(),
}
}
pub fn encode(self) -> u32 {
match self {
Self::Le => 0,
Self::Be => 1,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::Le => "le",
Self::Be => "be",
}
}
}