use crate::error::*;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Operand {
None,
Register(Register),
Shift(Shift),
Extension(Extension),
ExtensionWrapper(ExtensionWrapper),
SignedImmediate(i32),
UnsignedImmediate(u32),
SignedImmediate64(i64),
UnsignedImmediate64(u64),
Label(Label),
Bitmask(u8, u8, u8, bool),
Condition(Condition),
PrefetchOp(PrefetchOp),
}
impl Operand {
pub fn is_none(&self) -> bool {
if let Operand::None = self {
return true;
}
false
}
pub fn as_register(&self) -> Result<Register> {
if let Operand::Register(register) = self {
return Ok(*register);
}
todo!()
}
pub fn as_shift(&self) -> Result<Shift> {
if let Operand::Shift(shift) = self {
return Ok(*shift);
}
todo!()
}
pub fn is_shift(&self) -> bool {
if let Operand::Shift(_) = self {
return true;
}
false
}
pub fn as_extension(&self) -> Result<Extension> {
if let Operand::Extension(ext) = self {
return Ok(*ext);
}
if let Operand::ExtensionWrapper(ext) = self {
return Ok((*ext).into());
}
todo!()
}
pub fn is_extension(&self) -> bool {
if let Operand::Extension(_) = self {
return true;
}
false
}
pub fn as_extension_wrapper(&self) -> Result<ExtensionWrapper> {
if let Operand::ExtensionWrapper(ext) = self {
return Ok(*ext);
}
todo!()
}
pub fn as_signed_immediate(&self) -> Result<i32> {
if let Operand::SignedImmediate(simm) = self {
return Ok(*simm);
}
todo!()
}
pub fn as_unsigned_immediate(&self) -> Result<u32> {
if let Operand::UnsignedImmediate(uimm) = self {
return Ok(*uimm);
}
if let Operand::SignedImmediate(simm) = self {
return Ok(*simm as u32);
}
todo!()
}
pub fn as_signed_immediate_64(&self) -> Result<i64> {
if let Operand::SignedImmediate64(simm) = self {
return Ok(*simm);
}
todo!()
}
pub fn as_unsigned_immediate_64(&self) -> Result<u64> {
if let Operand::UnsignedImmediate64(uimm) = self {
return Ok(*uimm);
}
if let Operand::SignedImmediate64(simm) = self {
return Ok(*simm as u64);
}
todo!()
}
pub fn as_label(&self) -> Result<Label> {
if let Operand::Label(label) = self {
return Ok(*label);
}
todo!()
}
pub fn as_bitmask(&self) -> Result<(u8, u8, u8, bool)> {
if let Operand::Bitmask(n, imms, immr, aarch32) = self {
return Ok((*n, *imms, *immr, *aarch32));
}
todo!()
}
pub fn as_condition(&self) -> Result<Condition> {
if let Operand::Condition(cond) = self {
return Ok(*cond);
}
todo!()
}
pub fn as_prefetch_op(&self) -> Result<PrefetchOp> {
if let Operand::PrefetchOp(op) = self {
return Ok(*op);
}
todo!()
}
}
impl Default for Operand {
fn default() -> Self {
Operand::None
}
}
impl From<Register> for Operand {
fn from(value: Register) -> Self {
Operand::Register(value)
}
}
impl From<Shift> for Operand {
fn from(value: Shift) -> Self {
Operand::Shift(value)
}
}
impl From<Extension> for Operand {
fn from(value: Extension) -> Self {
Operand::Extension(value)
}
}
impl From<ExtensionWrapper> for Operand {
fn from(value: ExtensionWrapper) -> Self {
Operand::ExtensionWrapper(value)
}
}
impl From<u8> for Operand {
fn from(value: u8) -> Self {
Operand::UnsignedImmediate(value as u32)
}
}
impl From<u16> for Operand {
fn from(value: u16) -> Self {
Operand::UnsignedImmediate(value as u32)
}
}
impl From<u32> for Operand {
fn from(value: u32) -> Self {
Operand::UnsignedImmediate(value)
}
}
impl From<u64> for Operand {
fn from(value: u64) -> Self {
Operand::UnsignedImmediate64(value)
}
}
impl From<i8> for Operand {
fn from(value: i8) -> Self {
Operand::SignedImmediate(value as i32)
}
}
impl From<i16> for Operand {
fn from(value: i16) -> Self {
Operand::SignedImmediate(value as i32)
}
}
impl From<i32> for Operand {
fn from(value: i32) -> Self {
Operand::SignedImmediate(value)
}
}
impl From<i64> for Operand {
fn from(value: i64) -> Self {
Operand::SignedImmediate64(value)
}
}
impl From<Label> for Operand {
fn from(value: Label) -> Self {
Operand::Label(value)
}
}
impl From<Condition> for Operand {
fn from(value: Condition) -> Self {
Operand::Condition(value)
}
}
impl From<PrefetchOp> for Operand {
fn from(value: PrefetchOp) -> Self {
Operand::PrefetchOp(value)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Register {
W0 = 0,
W1,
W2,
W3,
W4,
W5,
W6,
W7,
W8,
W9,
W10,
W11,
W12,
W13,
W14,
W15,
W16,
W17,
W18,
W19,
W20,
W21,
W22,
W23,
W24,
W25,
W26,
W27,
W28,
W29,
W30,
WZR,
WSP,
X0,
X1,
X2,
X3,
X4,
X5,
X6,
X7,
X8,
X9,
X10,
X11,
X12,
X13,
X14,
X15,
X16,
X17,
X18,
X19,
X20,
X21,
X22,
X23,
X24,
X25,
X26,
X27,
X28,
X29,
X30,
XZR,
SP,
}
impl Register {
pub fn aarch32(index: u32, is_sp: bool) -> Result<Self> {
match index {
0 => Ok(Self::W0),
1 => Ok(Self::W1),
2 => Ok(Self::W2),
3 => Ok(Self::W3),
4 => Ok(Self::W4),
5 => Ok(Self::W5),
6 => Ok(Self::W6),
7 => Ok(Self::W7),
8 => Ok(Self::W8),
9 => Ok(Self::W9),
10 => Ok(Self::W10),
11 => Ok(Self::W11),
12 => Ok(Self::W12),
13 => Ok(Self::W13),
14 => Ok(Self::W14),
15 => Ok(Self::W15),
16 => Ok(Self::W16),
17 => Ok(Self::W17),
18 => Ok(Self::W18),
19 => Ok(Self::W19),
20 => Ok(Self::W20),
21 => Ok(Self::W21),
22 => Ok(Self::W22),
23 => Ok(Self::W23),
24 => Ok(Self::W24),
25 => Ok(Self::W25),
26 => Ok(Self::W26),
27 => Ok(Self::W27),
28 => Ok(Self::W28),
29 => Ok(Self::W29),
30 => Ok(Self::W30),
31 => {
if is_sp {
Ok(Self::WSP)
} else {
Ok(Self::WZR)
}
}
_ => Err(OperandError::RegisterOutOfRange(index))?,
}
}
pub fn aarch64(index: u32, is_sp: bool) -> Result<Self> {
match index {
0 => Ok(Self::X0),
1 => Ok(Self::X1),
2 => Ok(Self::X2),
3 => Ok(Self::X3),
4 => Ok(Self::X4),
5 => Ok(Self::X5),
6 => Ok(Self::X6),
7 => Ok(Self::X7),
8 => Ok(Self::X8),
9 => Ok(Self::X9),
10 => Ok(Self::X10),
11 => Ok(Self::X11),
12 => Ok(Self::X12),
13 => Ok(Self::X13),
14 => Ok(Self::X14),
15 => Ok(Self::X15),
16 => Ok(Self::X16),
17 => Ok(Self::X17),
18 => Ok(Self::X18),
19 => Ok(Self::X19),
20 => Ok(Self::X20),
21 => Ok(Self::X21),
22 => Ok(Self::X22),
23 => Ok(Self::X23),
24 => Ok(Self::X24),
25 => Ok(Self::X25),
26 => Ok(Self::X26),
27 => Ok(Self::X27),
28 => Ok(Self::X28),
29 => Ok(Self::X29),
30 => Ok(Self::X30),
31 => {
if is_sp {
Ok(Self::SP)
} else {
Ok(Self::XZR)
}
}
_ => Err(OperandError::RegisterOutOfRange(index))?,
}
}
pub fn is_aarch32(self) -> bool {
match self {
x if x as usize >= Register::W0 as usize && x as usize <= Register::WSP as usize => {
true
}
_ => false,
}
}
pub fn is_aarch64(self) -> bool {
match self {
x if x as usize >= Register::X0 as usize && x as usize <= Register::SP as usize => true,
_ => false,
}
}
pub fn encode(self) -> u32 {
match self {
Self::W0 => 0,
Self::W1 => 1,
Self::W2 => 2,
Self::W3 => 3,
Self::W4 => 4,
Self::W5 => 5,
Self::W6 => 6,
Self::W7 => 7,
Self::W8 => 8,
Self::W9 => 9,
Self::W10 => 10,
Self::W11 => 11,
Self::W12 => 12,
Self::W13 => 13,
Self::W14 => 14,
Self::W15 => 15,
Self::W16 => 16,
Self::W17 => 17,
Self::W18 => 18,
Self::W19 => 19,
Self::W20 => 20,
Self::W21 => 21,
Self::W22 => 22,
Self::W23 => 23,
Self::W24 => 24,
Self::W25 => 25,
Self::W26 => 26,
Self::W27 => 27,
Self::W28 => 28,
Self::W29 => 29,
Self::W30 => 30,
Self::WZR => 31,
Self::WSP => 31,
Self::X0 => 0,
Self::X1 => 1,
Self::X2 => 2,
Self::X3 => 3,
Self::X4 => 4,
Self::X5 => 5,
Self::X6 => 6,
Self::X7 => 7,
Self::X8 => 8,
Self::X9 => 9,
Self::X10 => 10,
Self::X11 => 11,
Self::X12 => 12,
Self::X13 => 13,
Self::X14 => 14,
Self::X15 => 15,
Self::X16 => 16,
Self::X17 => 17,
Self::X18 => 18,
Self::X19 => 19,
Self::X20 => 20,
Self::X21 => 21,
Self::X22 => 22,
Self::X23 => 23,
Self::X24 => 24,
Self::X25 => 25,
Self::X26 => 26,
Self::X27 => 27,
Self::X28 => 28,
Self::X29 => 29,
Self::X30 => 30,
Self::XZR => 31,
Self::SP => 31,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::W0 => "w0",
Self::W1 => "w1",
Self::W2 => "w2",
Self::W3 => "w3",
Self::W4 => "w4",
Self::W5 => "w5",
Self::W6 => "w6",
Self::W7 => "w7",
Self::W8 => "w8",
Self::W9 => "w9",
Self::W10 => "w10",
Self::W11 => "w11",
Self::W12 => "w12",
Self::W13 => "w13",
Self::W14 => "w14",
Self::W15 => "w15",
Self::W16 => "w16",
Self::W17 => "w17",
Self::W18 => "w18",
Self::W19 => "w19",
Self::W20 => "w20",
Self::W21 => "w21",
Self::W22 => "w22",
Self::W23 => "w23",
Self::W24 => "w24",
Self::W25 => "w25",
Self::W26 => "w26",
Self::W27 => "w27",
Self::W28 => "w28",
Self::W29 => "w29",
Self::W30 => "w30",
Self::WZR => "wzr",
Self::WSP => "wsp",
Self::X0 => "x0",
Self::X1 => "x1",
Self::X2 => "x2",
Self::X3 => "x3",
Self::X4 => "x4",
Self::X5 => "x5",
Self::X6 => "x6",
Self::X7 => "x7",
Self::X8 => "x8",
Self::X9 => "x9",
Self::X10 => "x10",
Self::X11 => "x11",
Self::X12 => "x12",
Self::X13 => "x13",
Self::X14 => "x14",
Self::X15 => "x15",
Self::X16 => "x16",
Self::X17 => "x17",
Self::X18 => "x18",
Self::X19 => "x19",
Self::X20 => "x20",
Self::X21 => "x21",
Self::X22 => "x22",
Self::X23 => "x23",
Self::X24 => "x24",
Self::X25 => "x25",
Self::X26 => "x26",
Self::X27 => "x27",
Self::X28 => "x28",
Self::X29 => "x29",
Self::X30 => "x30",
Self::XZR => "xzr",
Self::SP => "sp",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Shift {
LSL(Option<u32>),
LSR(Option<u32>),
ASR(Option<u32>),
ROR(Option<u32>),
}
impl Shift {
pub fn value(self) -> u32 {
match self {
Self::LSL(Some(imm)) => imm,
Self::LSR(Some(imm)) => imm,
Self::ASR(Some(imm)) => imm,
Self::ROR(Some(imm)) => imm,
_ => 0,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::LSL(_) => "lsl",
Self::LSR(_) => "lsr",
Self::ASR(_) => "asr",
Self::ROR(_) => "ror",
}
}
pub fn is_lsl(&self) -> bool {
if let Self::LSL(_) = self {
return true;
}
false
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Extension {
Uxtb(u32),
Uxth(u32),
Uxtw(u32),
Uxtx(u32),
Sxtb(u32),
Sxth(u32),
Sxtw(u32),
Sxtx(u32),
Lsl(u32),
Lsr(u32),
Asr(u32),
Ror(u32),
}
impl Extension {
pub fn value(self) -> u32 {
match self {
Self::Uxtb(imm) => imm,
Self::Uxth(imm) => imm,
Self::Uxtw(imm) => imm,
Self::Uxtx(imm) => imm,
Self::Sxtb(imm) => imm,
Self::Sxth(imm) => imm,
Self::Sxtw(imm) => imm,
Self::Sxtx(imm) => imm,
Self::Lsl(imm) => imm,
Self::Lsr(imm) => imm,
Self::Asr(imm) => imm,
Self::Ror(imm) => imm,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::Uxtb(_) => "uxtb",
Self::Uxth(_) => "uxth",
Self::Uxtw(_) => "uxtw",
Self::Uxtx(_) => "uxtx",
Self::Sxtb(_) => "sxtb",
Self::Sxth(_) => "sxth",
Self::Sxtw(_) => "sxtw",
Self::Sxtx(_) => "sxtx",
Self::Lsl(_) => "lsl",
Self::Lsr(_) => "lsr",
Self::Asr(_) => "asr",
Self::Ror(_) => "ror",
}
}
pub fn is_lsl(&self) -> bool {
match self {
Self::Lsl(_) => true,
_ => false,
}
}
}
impl From<ExtensionWrapper> for Extension {
fn from(value: ExtensionWrapper) -> Self {
match value {
ExtensionWrapper::CanOmit(e) => e,
ExtensionWrapper::CantOmit(e) => e,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum ExtensionWrapper {
CanOmit(Extension),
CantOmit(Extension),
}
impl ExtensionWrapper {
pub fn can_omit(&self) -> bool {
match self {
Self::CanOmit(_) => true,
Self::CantOmit(_) => false,
}
}
}
impl From<Extension> for ExtensionWrapper {
fn from(value: Extension) -> Self {
ExtensionWrapper::CanOmit(value)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Label {
Label(i64),
LabelName(u64),
}
impl Label {
pub fn decode(value: i64) -> Self {
Self::Label(value)
}
pub fn encode(self) -> Result<i64> {
match self {
Self::Label(imm) => Ok(imm),
Self::LabelName(_) => todo!(),
}
}
pub fn value(self) -> i64 {
match self {
Self::Label(imm) => imm,
Self::LabelName(imm) => imm as i64,
}
}
}
#[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,
Nv,
}
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),
0b1111 => Ok(Self::Nv),
_ => 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,
Self::Nv => 0b1111,
}
}
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,
Self::Nv => Self::Al,
Self::Al => Self::Nv,
}
}
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",
Self::Nv => "nv",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum PrefetchOp {
PLDKEEP,
PSTKEEP,
PLDSTRM,
PSTSTRM,
PLDL1KEEP,
PLDL1STRM,
PLDL2KEEP,
PLDL2STRM,
PLDL3KEEP,
PLDL3STRM,
PLDSLCKEEP,
PLDSLCSTRM,
PLIL1KEEP,
PLIL1STRM,
PLIL2KEEP,
PLIL2STRM,
PLIL3KEEP,
PLIL3STRM,
PLISLCKEEP,
PLISLCSTRM,
PSTL1KEEP,
PSTL1STRM,
PSTL2KEEP,
PSTL2STRM,
PSTL3KEEP,
PSTL3STRM,
PSTSLCKEEP,
PSTSLCSTRM,
IR,
Other(u32),
}