Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Amanieu
Last active June 28, 2018 18:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Amanieu/6bfc82be37325d22466eeadcd578d54e to your computer and use it in GitHub Desktop.
Save Amanieu/6bfc82be37325d22466eeadcd578d54e to your computer and use it in GitHub Desktop.
use core::hint;
pub mod encode {
#[inline]
pub fn shift_immed(ty: u32, imm5: u32, Rm: u32, Rd: u32) -> u32 {
let mut out = 0;
out |= 0x0 << 29;
out |= (ty as u32 & 0x3) << 27;
out |= (imm5 as u32 & 0x1f) << 22;
out |= (Rm as u32 & 0x7) << 19;
out |= (Rd as u32 & 0x7) << 16;
out
}
#[inline]
pub fn ADD_SUB_reg(op: bool, Rm: u32, Rn: u32, Rd: u32) -> u32 {
let mut out = 0;
out |= 0x6 << 26;
out |= (op as u32 & 0x1) << 25;
out |= (Rm as u32 & 0x7) << 22;
out |= (Rn as u32 & 0x7) << 19;
out |= (Rd as u32 & 0x7) << 16;
out
}
#[inline]
pub fn ADD_SUB_immed3(op: bool, imm3: u32, Rn: u32, Rd: u32) -> u32 {
let mut out = 0;
out |= 0x7 << 26;
out |= (op as u32 & 0x1) << 25;
out |= (imm3 as u32 & 0x7) << 22;
out |= (Rn as u32 & 0x7) << 19;
out |= (Rd as u32 & 0x7) << 16;
out
}
#[inline]
pub fn MOV_immed(Rd: u32, imm8: u32) -> u32 {
let mut out = 0;
out |= 0x4 << 27;
out |= (Rd as u32 & 0x7) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn CMP_immed(Rn: u32, imm8: u32) -> u32 {
let mut out = 0;
out |= 0x5 << 27;
out |= (Rn as u32 & 0x7) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn ADD_SUB_immed8(op: bool, Rdn: u32, imm8: u32) -> u32 {
let mut out = 0;
out |= 0x3 << 28;
out |= (op as u32 & 0x1) << 27;
out |= (Rdn as u32 & 0x7) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn data_proc(op: u32, Rm: u32, Rdn: u32) -> u32 {
let mut out = 0;
out |= 0x10 << 26;
out |= (op as u32 & 0xf) << 22;
out |= (Rm as u32 & 0x7) << 19;
out |= (Rdn as u32 & 0x7) << 16;
out
}
#[inline]
pub fn ADD_high(DN: bool, Rm: u32, Rdn: u32) -> u32 {
let mut out = 0;
out |= 0x44 << 24;
out |= (DN as u32 & 0x1) << 23;
out |= (Rm as u32 & 0xf) << 19;
out |= (Rdn as u32 & 0x7) << 16;
out
}
#[inline]
pub fn CMP_high(N: bool, Rm: u32, Rn: u32) -> u32 {
let mut out = 0;
out |= 0x45 << 24;
out |= (N as u32 & 0x1) << 23;
out |= (Rm as u32 & 0xf) << 19;
out |= (Rn as u32 & 0x7) << 16;
out
}
#[inline]
pub fn MOV_high(D: bool, Rm: u32, Rd: u32) -> u32 {
let mut out = 0;
out |= 0x46 << 24;
out |= (D as u32 & 0x1) << 23;
out |= (Rm as u32 & 0xf) << 19;
out |= (Rd as u32 & 0x7) << 16;
out
}
#[inline]
pub fn BX_BLX_reg(L: bool, Rm: u32) -> u32 {
let mut out = 0;
out |= 0x47 << 24;
out |= (L as u32 & 0x1) << 23;
out |= (Rm as u32 & 0xf) << 19;
out |= 0x0 << 16;
out
}
#[inline]
pub fn LDR_lit(Rt: u32, imm8: u32) -> u32 {
let mut out = 0;
out |= 0x9 << 27;
out |= (Rt as u32 & 0x7) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn LDR_STR_reg(op: u32, Rm: u32, Rn: u32, Rt: u32) -> u32 {
let mut out = 0;
out |= 0x5 << 28;
out |= (op as u32 & 0x7) << 25;
out |= (Rm as u32 & 0x7) << 22;
out |= (Rn as u32 & 0x7) << 19;
out |= (Rt as u32 & 0x7) << 16;
out
}
#[inline]
pub fn LDR_STR_immed(L: bool, imm5: u32, Rn: u32, Rt: u32) -> u32 {
let mut out = 0;
out |= 0x6 << 28;
out |= (L as u32 & 0x1) << 27;
out |= (imm5 as u32 & 0x1f) << 22;
out |= (Rn as u32 & 0x7) << 19;
out |= (Rt as u32 & 0x7) << 16;
out
}
#[inline]
pub fn LDRB_STRB_immed(L: bool, imm5: u32, Rn: u32, Rt: u32) -> u32 {
let mut out = 0;
out |= 0x7 << 28;
out |= (L as u32 & 0x1) << 27;
out |= (imm5 as u32 & 0x1f) << 22;
out |= (Rn as u32 & 0x7) << 19;
out |= (Rt as u32 & 0x7) << 16;
out
}
#[inline]
pub fn LDRH_STRH_immed(L: bool, imm5: u32, Rn: u32, Rt: u32) -> u32 {
let mut out = 0;
out |= 0x8 << 28;
out |= (L as u32 & 0x1) << 27;
out |= (imm5 as u32 & 0x1f) << 22;
out |= (Rn as u32 & 0x7) << 19;
out |= (Rt as u32 & 0x7) << 16;
out
}
#[inline]
pub fn LDR_STR_sp_immed(L: bool, Rt: u32, imm8: u32) -> u32 {
let mut out = 0;
out |= 0x9 << 28;
out |= (L as u32 & 0x1) << 27;
out |= (Rt as u32 & 0x7) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn ADR(Rd: u32, imm8: u32) -> u32 {
let mut out = 0;
out |= 0x14 << 27;
out |= (Rd as u32 & 0x7) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn ADR_sp(Rd: u32, imm8: u32) -> u32 {
let mut out = 0;
out |= 0x15 << 27;
out |= (Rd as u32 & 0x7) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn ADD_SUB_sp(op: bool, imm7: u32) -> u32 {
let mut out = 0;
out |= 0xb0 << 24;
out |= (op as u32 & 0x1) << 23;
out |= (imm7 as u32 & 0x7f) << 16;
out
}
#[inline]
pub fn CBZ_CBNZ(op: bool, i: bool, imm5: u32, Rn: u32) -> u32 {
let mut out = 0;
out |= 0xb << 28;
out |= (op as u32 & 0x1) << 27;
out |= 0x0 << 26;
out |= (i as u32 & 0x1) << 25;
out |= 0x1 << 24;
out |= (imm5 as u32 & 0x1f) << 19;
out |= (Rn as u32 & 0x7) << 16;
out
}
#[inline]
pub fn SXT_UXT(op: u32, Rm: u32, Rd: u32) -> u32 {
let mut out = 0;
out |= 0xb2 << 24;
out |= (op as u32 & 0x3) << 22;
out |= (Rm as u32 & 0x7) << 19;
out |= (Rd as u32 & 0x7) << 16;
out
}
#[inline]
pub fn PUSH_POP(L: bool, MP: bool, reg_list: u32) -> u32 {
let mut out = 0;
out |= 0xb << 28;
out |= (L as u32 & 0x1) << 27;
out |= 0x2 << 25;
out |= (MP as u32 & 0x1) << 24;
out |= (reg_list as u32 & 0xff) << 16;
out
}
#[inline]
pub fn SETEND(E: bool) -> u32 {
let mut out = 0;
out |= 0xb65 << 20;
out |= (E as u32 & 0x1) << 19;
out |= 0x0 << 16;
out
}
#[inline]
pub fn SETPAN(imm: bool) -> u32 {
let mut out = 0;
out |= 0xb61 << 20;
out |= (imm as u32 & 0x1) << 19;
out |= 0x0 << 16;
out
}
#[inline]
pub fn CPS(im: bool, A: bool, I: bool, F: bool) -> u32 {
let mut out = 0;
out |= 0x5b3 << 21;
out |= (im as u32 & 0x1) << 20;
out |= 0x0 << 19;
out |= (A as u32 & 0x1) << 18;
out |= (I as u32 & 0x1) << 17;
out |= (F as u32 & 0x1) << 16;
out
}
#[inline]
pub fn REV(op: u32, Rm: u32, Rd: u32) -> u32 {
let mut out = 0;
out |= 0xba << 24;
out |= (op as u32 & 0x3) << 22;
out |= (Rm as u32 & 0x7) << 19;
out |= (Rd as u32 & 0x7) << 16;
out
}
#[inline]
pub fn HLT(imm6: u32) -> u32 {
let mut out = 0;
out |= 0x2ea << 22;
out |= (imm6 as u32 & 0x3f) << 16;
out
}
#[inline]
pub fn BKPT(imm8: u32) -> u32 {
let mut out = 0;
out |= 0xbe << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn IT(firstcond: u32, mask: u32) -> u32 {
let mut out = 0;
out |= 0xbf << 24;
out |= (firstcond as u32 & 0xf) << 20;
out |= (mask as u32 & 0xf) << 16;
out
}
#[inline]
pub fn HINT(op: u32) -> u32 {
let mut out = 0;
out |= 0xbf << 24;
out |= (op as u32 & 0xf) << 20;
out |= 0x0 << 16;
out
}
#[inline]
pub fn LDM_STM(L: bool, Rn: u32, reg_list: u32) -> u32 {
let mut out = 0;
out |= 0xc << 28;
out |= (L as u32 & 0x1) << 27;
out |= (Rn as u32 & 0x7) << 24;
out |= (reg_list as u32 & 0xff) << 16;
out
}
#[inline]
pub fn B_cond(cond: u32, imm8: i32) -> u32 {
let mut out = 0;
out |= 0xd << 28;
out |= (cond as u32 & 0xf) << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn UDF(imm8: u32) -> u32 {
let mut out = 0;
out |= 0xde << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn SVC(imm8: u32) -> u32 {
let mut out = 0;
out |= 0xdf << 24;
out |= (imm8 as u32 & 0xff) << 16;
out
}
#[inline]
pub fn B(imm11: i32) -> u32 {
let mut out = 0;
out |= 0x1c << 27;
out |= (imm11 as u32 & 0x7ff) << 16;
out
}
#[inline]
pub fn thumb32_prefix(x: u32, y: u32) -> u32 {
let mut out = 0;
out |= 0x7 << 29;
out |= (x as u32 & 0x3) << 27;
out |= (y as u32 & 0x7ff) << 16;
out
}
}
pub mod fields {
#[derive(Copy, Clone)]
pub struct shift_immed(pub u32);
impl shift_immed {
#[inline]
pub fn ty(&self) -> u32 { (self.0 >> 27) & 0x3 }
#[inline]
pub fn imm5(&self) -> u32 { (self.0 >> 22) & 0x1f }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct ADD_SUB_reg(pub u32);
impl ADD_SUB_reg {
#[inline]
pub fn op(&self) -> bool { (self.0 >> 25) & 0x1 != 0 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 22) & 0x7 }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct ADD_SUB_immed3(pub u32);
impl ADD_SUB_immed3 {
#[inline]
pub fn op(&self) -> bool { (self.0 >> 25) & 0x1 != 0 }
#[inline]
pub fn imm3(&self) -> u32 { (self.0 >> 22) & 0x7 }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct MOV_immed(pub u32);
impl MOV_immed {
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct CMP_immed(pub u32);
impl CMP_immed {
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct ADD_SUB_immed8(pub u32);
impl ADD_SUB_immed8 {
#[inline]
pub fn op(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn Rdn(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct data_proc(pub u32);
impl data_proc {
#[inline]
pub fn op(&self) -> u32 { (self.0 >> 22) & 0xf }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rdn(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct ADD_high(pub u32);
impl ADD_high {
#[inline]
pub fn DN(&self) -> bool { (self.0 >> 23) & 0x1 != 0 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0xf }
#[inline]
pub fn Rdn(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct CMP_high(pub u32);
impl CMP_high {
#[inline]
pub fn N(&self) -> bool { (self.0 >> 23) & 0x1 != 0 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0xf }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct MOV_high(pub u32);
impl MOV_high {
#[inline]
pub fn D(&self) -> bool { (self.0 >> 23) & 0x1 != 0 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0xf }
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct BX_BLX_reg(pub u32);
impl BX_BLX_reg {
#[inline]
pub fn L(&self) -> bool { (self.0 >> 23) & 0x1 != 0 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0xf }
}
#[derive(Copy, Clone)]
pub struct LDR_lit(pub u32);
impl LDR_lit {
#[inline]
pub fn Rt(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct LDR_STR_reg(pub u32);
impl LDR_STR_reg {
#[inline]
pub fn op(&self) -> u32 { (self.0 >> 25) & 0x7 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 22) & 0x7 }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rt(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct LDR_STR_immed(pub u32);
impl LDR_STR_immed {
#[inline]
pub fn L(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn imm5(&self) -> u32 { (self.0 >> 22) & 0x1f }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rt(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct LDRB_STRB_immed(pub u32);
impl LDRB_STRB_immed {
#[inline]
pub fn L(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn imm5(&self) -> u32 { (self.0 >> 22) & 0x1f }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rt(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct LDRH_STRH_immed(pub u32);
impl LDRH_STRH_immed {
#[inline]
pub fn L(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn imm5(&self) -> u32 { (self.0 >> 22) & 0x1f }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rt(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct LDR_STR_sp_immed(pub u32);
impl LDR_STR_sp_immed {
#[inline]
pub fn L(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn Rt(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct ADR(pub u32);
impl ADR {
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct ADR_sp(pub u32);
impl ADR_sp {
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct ADD_SUB_sp(pub u32);
impl ADD_SUB_sp {
#[inline]
pub fn op(&self) -> bool { (self.0 >> 23) & 0x1 != 0 }
#[inline]
pub fn imm7(&self) -> u32 { (self.0 >> 16) & 0x7f }
}
#[derive(Copy, Clone)]
pub struct CBZ_CBNZ(pub u32);
impl CBZ_CBNZ {
#[inline]
pub fn op(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn i(&self) -> bool { (self.0 >> 25) & 0x1 != 0 }
#[inline]
pub fn imm5(&self) -> u32 { (self.0 >> 19) & 0x1f }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct SXT_UXT(pub u32);
impl SXT_UXT {
#[inline]
pub fn op(&self) -> u32 { (self.0 >> 22) & 0x3 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct PUSH_POP(pub u32);
impl PUSH_POP {
#[inline]
pub fn L(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn MP(&self) -> bool { (self.0 >> 24) & 0x1 != 0 }
#[inline]
pub fn reg_list(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct SETEND(pub u32);
impl SETEND {
#[inline]
pub fn E(&self) -> bool { (self.0 >> 19) & 0x1 != 0 }
}
#[derive(Copy, Clone)]
pub struct SETPAN(pub u32);
impl SETPAN {
#[inline]
pub fn imm(&self) -> bool { (self.0 >> 19) & 0x1 != 0 }
}
#[derive(Copy, Clone)]
pub struct CPS(pub u32);
impl CPS {
#[inline]
pub fn im(&self) -> bool { (self.0 >> 20) & 0x1 != 0 }
#[inline]
pub fn A(&self) -> bool { (self.0 >> 18) & 0x1 != 0 }
#[inline]
pub fn I(&self) -> bool { (self.0 >> 17) & 0x1 != 0 }
#[inline]
pub fn F(&self) -> bool { (self.0 >> 16) & 0x1 != 0 }
}
#[derive(Copy, Clone)]
pub struct REV(pub u32);
impl REV {
#[inline]
pub fn op(&self) -> u32 { (self.0 >> 22) & 0x3 }
#[inline]
pub fn Rm(&self) -> u32 { (self.0 >> 19) & 0x7 }
#[inline]
pub fn Rd(&self) -> u32 { (self.0 >> 16) & 0x7 }
}
#[derive(Copy, Clone)]
pub struct HLT(pub u32);
impl HLT {
#[inline]
pub fn imm6(&self) -> u32 { (self.0 >> 16) & 0x3f }
}
#[derive(Copy, Clone)]
pub struct BKPT(pub u32);
impl BKPT {
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct IT(pub u32);
impl IT {
#[inline]
pub fn firstcond(&self) -> u32 { (self.0 >> 20) & 0xf }
#[inline]
pub fn mask(&self) -> u32 { (self.0 >> 16) & 0xf }
}
#[derive(Copy, Clone)]
pub struct HINT(pub u32);
impl HINT {
#[inline]
pub fn op(&self) -> u32 { (self.0 >> 20) & 0xf }
}
#[derive(Copy, Clone)]
pub struct LDM_STM(pub u32);
impl LDM_STM {
#[inline]
pub fn L(&self) -> bool { (self.0 >> 27) & 0x1 != 0 }
#[inline]
pub fn Rn(&self) -> u32 { (self.0 >> 24) & 0x7 }
#[inline]
pub fn reg_list(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct B_cond(pub u32);
impl B_cond {
#[inline]
pub fn cond(&self) -> u32 { (self.0 >> 24) & 0xf }
#[inline]
pub fn imm8(&self) -> i32 { ((self.0 as i32) << 8) >> 24 }
}
#[derive(Copy, Clone)]
pub struct UDF(pub u32);
impl UDF {
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct SVC(pub u32);
impl SVC {
#[inline]
pub fn imm8(&self) -> u32 { (self.0 >> 16) & 0xff }
}
#[derive(Copy, Clone)]
pub struct B(pub u32);
impl B {
#[inline]
pub fn imm11(&self) -> i32 { ((self.0 as i32) << 5) >> 21 }
}
#[derive(Copy, Clone)]
pub struct thumb32_prefix(pub u32);
impl thumb32_prefix {
#[inline]
pub fn x(&self) -> u32 { (self.0 >> 27) & 0x3 }
#[inline]
pub fn y(&self) -> u32 { (self.0 >> 16) & 0x7ff }
}
}
pub mod decode {
#[inline]
pub fn shift_immed(instr: u32) -> Option<super::fields::shift_immed> {
if instr & 0xe0000000 == 0x0 && instr & 0x18000000 != 0x18000000 {
Some(super::fields::shift_immed(instr))
} else {
None
}
}
#[inline]
pub fn ADD_SUB_reg(instr: u32) -> Option<super::fields::ADD_SUB_reg> {
if instr & 0xfc000000 == 0x18000000 {
Some(super::fields::ADD_SUB_reg(instr))
} else {
None
}
}
#[inline]
pub fn ADD_SUB_immed3(instr: u32) -> Option<super::fields::ADD_SUB_immed3> {
if instr & 0xfc000000 == 0x1c000000 {
Some(super::fields::ADD_SUB_immed3(instr))
} else {
None
}
}
#[inline]
pub fn MOV_immed(instr: u32) -> Option<super::fields::MOV_immed> {
if instr & 0xf8000000 == 0x20000000 {
Some(super::fields::MOV_immed(instr))
} else {
None
}
}
#[inline]
pub fn CMP_immed(instr: u32) -> Option<super::fields::CMP_immed> {
if instr & 0xf8000000 == 0x28000000 {
Some(super::fields::CMP_immed(instr))
} else {
None
}
}
#[inline]
pub fn ADD_SUB_immed8(instr: u32) -> Option<super::fields::ADD_SUB_immed8> {
if instr & 0xf0000000 == 0x30000000 {
Some(super::fields::ADD_SUB_immed8(instr))
} else {
None
}
}
#[inline]
pub fn data_proc(instr: u32) -> Option<super::fields::data_proc> {
if instr & 0xfc000000 == 0x40000000 {
Some(super::fields::data_proc(instr))
} else {
None
}
}
#[inline]
pub fn ADD_high(instr: u32) -> Option<super::fields::ADD_high> {
if instr & 0xff000000 == 0x44000000 {
Some(super::fields::ADD_high(instr))
} else {
None
}
}
#[inline]
pub fn CMP_high(instr: u32) -> Option<super::fields::CMP_high> {
if instr & 0xff000000 == 0x45000000 {
Some(super::fields::CMP_high(instr))
} else {
None
}
}
#[inline]
pub fn MOV_high(instr: u32) -> Option<super::fields::MOV_high> {
if instr & 0xff000000 == 0x46000000 {
Some(super::fields::MOV_high(instr))
} else {
None
}
}
#[inline]
pub fn BX_BLX_reg(instr: u32) -> Option<super::fields::BX_BLX_reg> {
if instr & 0xff070000 == 0x47000000 {
Some(super::fields::BX_BLX_reg(instr))
} else {
None
}
}
#[inline]
pub fn LDR_lit(instr: u32) -> Option<super::fields::LDR_lit> {
if instr & 0xf8000000 == 0x48000000 {
Some(super::fields::LDR_lit(instr))
} else {
None
}
}
#[inline]
pub fn LDR_STR_reg(instr: u32) -> Option<super::fields::LDR_STR_reg> {
if instr & 0xf0000000 == 0x50000000 {
Some(super::fields::LDR_STR_reg(instr))
} else {
None
}
}
#[inline]
pub fn LDR_STR_immed(instr: u32) -> Option<super::fields::LDR_STR_immed> {
if instr & 0xf0000000 == 0x60000000 {
Some(super::fields::LDR_STR_immed(instr))
} else {
None
}
}
#[inline]
pub fn LDRB_STRB_immed(instr: u32) -> Option<super::fields::LDRB_STRB_immed> {
if instr & 0xf0000000 == 0x70000000 {
Some(super::fields::LDRB_STRB_immed(instr))
} else {
None
}
}
#[inline]
pub fn LDRH_STRH_immed(instr: u32) -> Option<super::fields::LDRH_STRH_immed> {
if instr & 0xf0000000 == 0x80000000 {
Some(super::fields::LDRH_STRH_immed(instr))
} else {
None
}
}
#[inline]
pub fn LDR_STR_sp_immed(instr: u32) -> Option<super::fields::LDR_STR_sp_immed> {
if instr & 0xf0000000 == 0x90000000 {
Some(super::fields::LDR_STR_sp_immed(instr))
} else {
None
}
}
#[inline]
pub fn ADR(instr: u32) -> Option<super::fields::ADR> {
if instr & 0xf8000000 == 0xa0000000 {
Some(super::fields::ADR(instr))
} else {
None
}
}
#[inline]
pub fn ADR_sp(instr: u32) -> Option<super::fields::ADR_sp> {
if instr & 0xf8000000 == 0xa8000000 {
Some(super::fields::ADR_sp(instr))
} else {
None
}
}
#[inline]
pub fn ADD_SUB_sp(instr: u32) -> Option<super::fields::ADD_SUB_sp> {
if instr & 0xff000000 == 0xb0000000 {
Some(super::fields::ADD_SUB_sp(instr))
} else {
None
}
}
#[inline]
pub fn CBZ_CBNZ(instr: u32) -> Option<super::fields::CBZ_CBNZ> {
if instr & 0xf5000000 == 0xb1000000 {
Some(super::fields::CBZ_CBNZ(instr))
} else {
None
}
}
#[inline]
pub fn SXT_UXT(instr: u32) -> Option<super::fields::SXT_UXT> {
if instr & 0xff000000 == 0xb2000000 {
Some(super::fields::SXT_UXT(instr))
} else {
None
}
}
#[inline]
pub fn PUSH_POP(instr: u32) -> Option<super::fields::PUSH_POP> {
if instr & 0xf6000000 == 0xb4000000 {
Some(super::fields::PUSH_POP(instr))
} else {
None
}
}
#[inline]
pub fn SETEND(instr: u32) -> Option<super::fields::SETEND> {
if instr & 0xfff70000 == 0xb6500000 {
Some(super::fields::SETEND(instr))
} else {
None
}
}
#[inline]
pub fn SETPAN(instr: u32) -> Option<super::fields::SETPAN> {
if instr & 0xfff70000 == 0xb6100000 {
Some(super::fields::SETPAN(instr))
} else {
None
}
}
#[inline]
pub fn CPS(instr: u32) -> Option<super::fields::CPS> {
if instr & 0xffe80000 == 0xb6600000 {
Some(super::fields::CPS(instr))
} else {
None
}
}
#[inline]
pub fn REV(instr: u32) -> Option<super::fields::REV> {
if instr & 0xff000000 == 0xba000000 && instr & 0xc00000 != 0x800000 {
Some(super::fields::REV(instr))
} else {
None
}
}
#[inline]
pub fn HLT(instr: u32) -> Option<super::fields::HLT> {
if instr & 0xffc00000 == 0xba800000 {
Some(super::fields::HLT(instr))
} else {
None
}
}
#[inline]
pub fn BKPT(instr: u32) -> Option<super::fields::BKPT> {
if instr & 0xff000000 == 0xbe000000 {
Some(super::fields::BKPT(instr))
} else {
None
}
}
#[inline]
pub fn IT(instr: u32) -> Option<super::fields::IT> {
if instr & 0xff000000 == 0xbf000000 && instr & 0xf0000 != 0x0 {
Some(super::fields::IT(instr))
} else {
None
}
}
#[inline]
pub fn HINT(instr: u32) -> Option<super::fields::HINT> {
if instr & 0xff0f0000 == 0xbf000000 {
Some(super::fields::HINT(instr))
} else {
None
}
}
#[inline]
pub fn LDM_STM(instr: u32) -> Option<super::fields::LDM_STM> {
if instr & 0xf0000000 == 0xc0000000 {
Some(super::fields::LDM_STM(instr))
} else {
None
}
}
#[inline]
pub fn B_cond(instr: u32) -> Option<super::fields::B_cond> {
if instr & 0xf0000000 == 0xd0000000 && instr & 0xe000000 != 0xe000000 {
Some(super::fields::B_cond(instr))
} else {
None
}
}
#[inline]
pub fn UDF(instr: u32) -> Option<super::fields::UDF> {
if instr & 0xff000000 == 0xde000000 {
Some(super::fields::UDF(instr))
} else {
None
}
}
#[inline]
pub fn SVC(instr: u32) -> Option<super::fields::SVC> {
if instr & 0xff000000 == 0xdf000000 {
Some(super::fields::SVC(instr))
} else {
None
}
}
#[inline]
pub fn B(instr: u32) -> Option<super::fields::B> {
if instr & 0xf8000000 == 0xe0000000 {
Some(super::fields::B(instr))
} else {
None
}
}
#[inline]
pub fn thumb32_prefix(instr: u32) -> Option<super::fields::thumb32_prefix> {
if instr & 0xe0000000 == 0xe0000000 && instr & 0x18000000 != 0x0 {
Some(super::fields::thumb32_prefix(instr))
} else {
None
}
}
}
#[derive(Copy, Clone)]
pub enum Instruction {
shift_immed(fields::shift_immed),
ADD_SUB_reg(fields::ADD_SUB_reg),
ADD_SUB_immed3(fields::ADD_SUB_immed3),
MOV_immed(fields::MOV_immed),
CMP_immed(fields::CMP_immed),
ADD_SUB_immed8(fields::ADD_SUB_immed8),
data_proc(fields::data_proc),
ADD_high(fields::ADD_high),
CMP_high(fields::CMP_high),
MOV_high(fields::MOV_high),
BX_BLX_reg(fields::BX_BLX_reg),
LDR_lit(fields::LDR_lit),
LDR_STR_reg(fields::LDR_STR_reg),
LDR_STR_immed(fields::LDR_STR_immed),
LDRB_STRB_immed(fields::LDRB_STRB_immed),
LDRH_STRH_immed(fields::LDRH_STRH_immed),
LDR_STR_sp_immed(fields::LDR_STR_sp_immed),
ADR(fields::ADR),
ADR_sp(fields::ADR_sp),
ADD_SUB_sp(fields::ADD_SUB_sp),
CBZ_CBNZ(fields::CBZ_CBNZ),
SXT_UXT(fields::SXT_UXT),
PUSH_POP(fields::PUSH_POP),
SETEND(fields::SETEND),
SETPAN(fields::SETPAN),
CPS(fields::CPS),
REV(fields::REV),
HLT(fields::HLT),
BKPT(fields::BKPT),
IT(fields::IT),
HINT(fields::HINT),
LDM_STM(fields::LDM_STM),
B_cond(fields::B_cond),
UDF(fields::UDF),
SVC(fields::SVC),
B(fields::B),
thumb32_prefix(fields::thumb32_prefix),
undefined,
}
pub fn decode<T, F: FnOnce(Instruction) -> T>(instr: u32, f: F) -> T {
match instr & 0xe0000000 {
0x00000000 => if instr & 0x18000000 == 0x18000000 {
match instr & 0x04000000 {
0x00000000 => f(Instruction::ADD_SUB_reg(fields::ADD_SUB_reg(instr))),
0x04000000 => f(Instruction::ADD_SUB_immed3(fields::ADD_SUB_immed3(instr))),
_ => unsafe { hint::unreachable_unchecked() }
}
} else {
f(Instruction::shift_immed(fields::shift_immed(instr)))
},
0x80000000 => match instr & 0x10000000 {
0x00000000 => f(Instruction::LDRH_STRH_immed(fields::LDRH_STRH_immed(instr))),
0x10000000 => f(Instruction::LDR_STR_sp_immed(fields::LDR_STR_sp_immed(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0x40000000 => match instr & 0x10000000 {
0x00000000 => match instr & 0x08000000 {
0x00000000 => match instr & 0x04000000 {
0x00000000 => f(Instruction::data_proc(fields::data_proc(instr))),
0x04000000 => match instr & 0x03000000 {
0x00000000 => f(Instruction::ADD_high(fields::ADD_high(instr))),
0x02000000 => f(Instruction::MOV_high(fields::MOV_high(instr))),
0x01000000 => f(Instruction::CMP_high(fields::CMP_high(instr))),
0x03000000 => match instr & 0x00070000 {
0x00000000 => f(Instruction::BX_BLX_reg(fields::BX_BLX_reg(instr))),
_ => f(Instruction::undefined),
},
_ => unsafe { hint::unreachable_unchecked() }
},
_ => unsafe { hint::unreachable_unchecked() }
},
0x08000000 => f(Instruction::LDR_lit(fields::LDR_lit(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0x10000000 => f(Instruction::LDR_STR_reg(fields::LDR_STR_reg(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0xc0000000 => match instr & 0x10000000 {
0x00000000 => f(Instruction::LDM_STM(fields::LDM_STM(instr))),
0x10000000 => if instr & 0x0e000000 == 0x0e000000 {
match instr & 0x01000000 {
0x00000000 => f(Instruction::UDF(fields::UDF(instr))),
0x01000000 => f(Instruction::SVC(fields::SVC(instr))),
_ => unsafe { hint::unreachable_unchecked() }
}
} else {
f(Instruction::B_cond(fields::B_cond(instr)))
},
_ => unsafe { hint::unreachable_unchecked() }
},
0x20000000 => match instr & 0x10000000 {
0x00000000 => match instr & 0x08000000 {
0x00000000 => f(Instruction::MOV_immed(fields::MOV_immed(instr))),
0x08000000 => f(Instruction::CMP_immed(fields::CMP_immed(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0x10000000 => f(Instruction::ADD_SUB_immed8(fields::ADD_SUB_immed8(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0xa0000000 => match instr & 0x10000000 {
0x00000000 => match instr & 0x08000000 {
0x00000000 => f(Instruction::ADR(fields::ADR(instr))),
0x08000000 => f(Instruction::ADR_sp(fields::ADR_sp(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0x10000000 => match instr & 0x04000000 {
0x00000000 => match instr & 0x01000000 {
0x00000000 => match instr & 0x0a000000 {
0x00000000 => f(Instruction::ADD_SUB_sp(fields::ADD_SUB_sp(instr))),
0x02000000 => f(Instruction::SXT_UXT(fields::SXT_UXT(instr))),
0x0a000000 => if instr & 0x00c00000 == 0x00800000 {
f(Instruction::HLT(fields::HLT(instr)))
} else {
f(Instruction::REV(fields::REV(instr)))
},
_ => f(Instruction::undefined),
},
0x01000000 => f(Instruction::CBZ_CBNZ(fields::CBZ_CBNZ(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0x04000000 => match instr & 0x02000000 {
0x00000000 => f(Instruction::PUSH_POP(fields::PUSH_POP(instr))),
0x02000000 => match instr & 0x09000000 {
0x00000000 => match instr & 0x00e00000 {
0x00000000 => match instr & 0x00170000 {
0x00100000 => f(Instruction::SETPAN(fields::SETPAN(instr))),
_ => f(Instruction::undefined),
},
0x00400000 => match instr & 0x00170000 {
0x00100000 => f(Instruction::SETEND(fields::SETEND(instr))),
_ => f(Instruction::undefined),
},
0x00600000 => match instr & 0x00080000 {
0x00000000 => f(Instruction::CPS(fields::CPS(instr))),
_ => f(Instruction::undefined),
},
_ => f(Instruction::undefined),
},
0x08000000 => f(Instruction::BKPT(fields::BKPT(instr))),
0x09000000 => if instr & 0x000f0000 == 0x00000000 {
f(Instruction::HINT(fields::HINT(instr)))
} else {
f(Instruction::IT(fields::IT(instr)))
},
_ => f(Instruction::undefined),
},
_ => unsafe { hint::unreachable_unchecked() }
},
_ => unsafe { hint::unreachable_unchecked() }
},
_ => unsafe { hint::unreachable_unchecked() }
},
0x60000000 => match instr & 0x10000000 {
0x00000000 => f(Instruction::LDR_STR_immed(fields::LDR_STR_immed(instr))),
0x10000000 => f(Instruction::LDRB_STRB_immed(fields::LDRB_STRB_immed(instr))),
_ => unsafe { hint::unreachable_unchecked() }
},
0xe0000000 => if instr & 0x18000000 == 0x00000000 {
f(Instruction::B(fields::B(instr)))
} else {
f(Instruction::thumb32_prefix(fields::thumb32_prefix(instr)))
},
_ => unsafe { hint::unreachable_unchecked() }
}
}
# Shift, add, subtract and compare
shift_immed 000 type:2 imm5:5 Rm:3 Rd:3 ?type!=11
ADD_SUB_reg 000110 op:1 Rm:3 Rn:3 Rd:3
ADD_SUB_immed3 000111 op:1 imm3:3 Rn:3 Rd:3
MOV_immed 00100 Rd:3 imm8:8
CMP_immed 00101 Rn:3 imm8:8
ADD_SUB_immed8 0011 op:1 Rdn:3 imm8:8
# Data-processing
data_proc 010000 op:4 Rm:3 Rdn:3
# Special data instructions and branch and exchange
ADD_high 01000100 DN:1 Rm:4 Rdn:3
CMP_high 01000101 N:1 Rm:4 Rn:3
MOV_high 01000110 D:1 Rm:4 Rd:3
BX_BLX_reg 01000111 L:1 Rm:4 000
# Load from Literal Pool
LDR_lit 01001 Rt:3 imm8:8
# Load/store single data item
LDR_STR_reg 0101 op:3 Rm:3 Rn:3 Rt:3
LDR_STR_immed 0110 L:1 imm5:5 Rn:3 Rt:3
LDRB_STRB_immed 0111 L:1 imm5:5 Rn:3 Rt:3
LDRH_STRH_immed 1000 L:1 imm5:5 Rn:3 Rt:3
LDR_STR_sp_immed 1001 L:1 Rt:3 imm8:8
# Generate PC-relative address
ADR 10100 Rd:3 imm8:8
# Generate SP-relative address
ADR_sp 10101 Rd:3 imm8:8
# Miscellaneous 16-bit instructions
ADD_SUB_sp 10110000 op:1 imm7:7
CBZ_CBNZ 1011 op:1 0 i:1 1 imm5:5 Rn:3
SXT_UXT 10110010 op:2 Rm:3 Rd:3
PUSH_POP 1011 L:1 10 MP:1 reg_list:8
SETEND 101101100101 E:1 000
SETPAN 101101100001 imm:1 000
CPS 10110110011 im:1 0 A:1 I:1 F:1
REV 10111010 op:2 Rm:3 Rd:3 ?op!=10
HLT 1011101010 imm6:6
BKPT 10111110 imm8:8
IT 10111111 firstcond:4 mask:4 ?mask!=0000
HINT 10111111 op:4 0000
# Load/store multiple registers
LDM_STM 1100 L:1 Rn:3 reg_list:8
# Conditional branch and supervisor call
B_cond 1101 cond:4 imm8:s8 ?cond!=111x
UDF 11011110 imm8:8
SVC 11011111 imm8:8
# Unconditional branch
B 11100 imm11:s11
# Thumb32 prefix
thumb32_prefix 111 x:2 y:11 ?x!=00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment