From 2c5c5cda6c39f5b7d29063731b89771ee3be30ae Mon Sep 17 00:00:00 2001 From: The6P4C Date: Mon, 14 Dec 2020 13:46:23 +1000 Subject: Add MSR load/store, fix M43 interpretation and CPUID indirection --- src/lib.rs | 25 ++++++++++++++++------ tests/test.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8c7496b..384e107 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1426,6 +1426,7 @@ pub enum IndirectionReg { Dtr, Ibr, Itr, + Msr, Pkr, Pmc, Pmd, @@ -1440,6 +1441,7 @@ impl fmt::Display for IndirectionReg { Dtr => write!(f, "dtr"), Ibr => write!(f, "ibr"), Itr => write!(f, "itr"), + Msr => write!(f, "msr"), Pkr => write!(f, "pkr"), Pmc => write!(f, "pmc"), Pmd => write!(f, "pmd"), @@ -3194,6 +3196,7 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Op 0x03 => IndirectionReg::Pkr, 0x04 => IndirectionReg::Pmc, 0x05 => IndirectionReg::Pmd, + 0x06 => IndirectionReg::Msr, 0x0e => IndirectionReg::Dtr, 0x0f => IndirectionReg::Itr, _ => { return one_op(false, Operand::None); } @@ -3214,15 +3217,16 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Op 0x12 => IndirectionReg::Ibr, 0x13 => IndirectionReg::Pkr, 0x14 => IndirectionReg::Pmc, - 0x15 => IndirectionReg::Cpuid, - 0x17 => IndirectionReg::Pmd, + 0x15 => IndirectionReg::Pmd, + 0x16 => IndirectionReg::Msr, + 0x17 => IndirectionReg::Cpuid, _ => { return one_op(false, Operand::None); } }; - let r2 = word[13..20].load::(); + let r1 = word[6..13].load::(); let r3 = word[20..27].load::(); two_op( Some(0), - Operand::GPRegister(GPRegister(r2)), + Operand::GPRegister(GPRegister(r1)), Operand::Indirection(ind, GPRegister(r3)), ) } @@ -3988,9 +3992,18 @@ fn get_m_opcode_and_encoding(tag: u8, word: &BitSlice) -> (Opcode, Ope // `Table 4-44 Opcode 1 System/Memory Management 3-bit Opcode Extensions` if x3 == 0 { // `Table 4-45 System/Memory Management 6-bit Ext` + + // Indices 0x06 and 0x16 are unallocated within the table, + // however these correspond to MSR store/load respectively and + // follow the same format as other indirect register stores and + // loads. These instructions appear in the 460GX system + // firmware and are decoded by IDA. These instructions are also + // referenced in a + // [UEFI Itanium platform assembler source file](https://github.com/open-estuary/uefi/blob/af332aea6e16dec610a76da9279d4cbfe0e87cc3/MdePkg/Library/BaseLib/Ipf/AccessMsr.s) + // for accessing MSRs which uses similar syntax. const TABLE4_45: [(Opcode, OperandEncodingM); 64] = [ - (Mov, M42), (Mov, M42), (Mov, M42), (Mov, M43), (Mov, M42), (Mov, M42), (Purple, None), (Purple, None), (Purple, None), (Ptc_l, M45), (Ptc_g, M45), (Ptc_ga, M45), (Ptr_d, M45), (Ptr_i, M45), (Itr_d, M42), (Itr_i, M42), - (Mov, M43),(Mov, M43), (Mov, M43), (Mov, M43), (Mov, M43), (Mov, M43), (Purple, None), (Mov, M43), (Probe_r, M39), (Probe_w, M39), (Thash, M46), (Ttag, M46), (Purple, None), (Purple, None), (Tpa, M46), (Tak, M46), + (Mov, M42), (Mov, M42), (Mov, M42), (Mov, M43), (Mov, M42), (Mov, M42), (Mov, M42), (Purple, None), (Purple, None), (Ptc_l, M45), (Ptc_g, M45), (Ptc_ga, M45), (Ptr_d, M45), (Ptr_i, M45), (Itr_d, M42), (Itr_i, M42), + (Mov, M43),(Mov, M43), (Mov, M43), (Mov, M43), (Mov, M43), (Mov, M43), (Mov, M43), (Mov, M43), (Probe_r, M39), (Probe_w, M39), (Thash, M46), (Ttag, M46), (Purple, None), (Purple, None), (Tpa, M46), (Tak, M46), (Purple, None), (Mov, M36), (Mov_m, M31), (Purple, None), (Mov, M33), (Mov, M36), (Purple, None), (Purple, None), (Purple, None), (Mov, M35), (Mov_m, M29), (Purple, None), (Mov, M32), (Mov, M35), (Itc_d, M41), (Itc_i, M41), (Fc, M28),(Probe_rw_fault, M40), (Probe_r_fault, M40), (Probe_w_fault, M40), (Ptc_e, M47), (Purple, None), (Purple, None), (Purple, None), (Probe_r, M38), (Probe_w, M38), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), ]; diff --git a/tests/test.rs b/tests/test.rs index a21cfcc..2c4e855 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1824,3 +1824,70 @@ fn test_bash_cfree() { let inst = decoder.decode(data[..].iter().cloned()).unwrap(); assert_eq!(format!("{}", inst), expected); } + +// from 460gx system firmware +#[test] +fn test_msr() { + let decoder = InstDecoder::default(); + + let expected = "[MMI] mov r44=0x40; mov r31=msr[r37]; nop.i 0x0;;"; + let data = [0x09, 0x60, 0x01, 0x01, 0x00, 0x24, 0xf0, 0x01, 0x94, 0x2c, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MFI] mov msr[r37]=r9; nop.f 0x0; nop.i 0x0;;"; + let data = [0x0d, 0x00, 0x24, 0x4a, 0x06, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MFI] mov msr[r2]=r9; nop.f 0x0; nop.i 0x0;;"; + let data = [0x0d, 0x00, 0x24, 0x04, 0x06, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MMI] mov r20=msr[r3]; mov r21=msr[r21]; nop.i 0x0"; + let data = [0x08, 0xa0, 0x00, 0x06, 0x16, 0x04, 0x50, 0x01, 0x54, 0x2c, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MMI] mov r50=0x60e; mov r54=msr[r48]; nop.i 0x0"; + let data = [0x08, 0x90, 0x39, 0x00, 0x0c, 0x24, 0x60, 0x03, 0xc0, 0x2c, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MII] (p04) mov msr[r3]=r38; (p08) mov r16=0x405; (p09) mov r17=0x406;;"; + let data = [0x81, 0x00, 0x98, 0x06, 0x06, 0x04, 0x02, 0x29, 0x00, 0x10, 0xc8, 0x24, 0x62, 0x00, 0x20, 0x90]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); +} + +// from 460gx system firmware +#[test] +fn test_indirection() { + let decoder = InstDecoder::default(); + + let expected = "[MMI] mov r2=0x3;; mov r2=cpuid[r2]; nop.i 0x0;;"; + let data = [0x0B, 0x10, 0x0C, 0x00, 0x00, 0x24, 0x20, 0x00, 0x08, 0x2E, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MMI] mov r20=0x3;; mov r20=cpuid[r20]; nop.i 0x0;;"; + let data = [0x0B, 0xA0, 0x0C, 0x00, 0x00, 0x24, 0x40, 0x01, 0x50, 0x2E, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MMI] mov r41=dbr[r0]; mov r42=dbr[r37]; nop.i 0x0"; + let data = [0x08, 0x48, 0x01, 0x00, 0x11, 0x04, 0xA0, 0x02, 0x94, 0x22, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MMI] mov dbr[r37]=r42;; mov dbr[r38]=r43; nop.i 0x0;;"; + let data = [0x0B, 0x00, 0xA8, 0x4A, 0x01, 0x04, 0x00, 0x58, 0x99, 0x02, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); + + let expected = "[MMI] mov r44=pmc[r0]; mov pmc[r0]=r2; nop.i 0x0;;"; + let data = [0x09, 0x60, 0x01, 0x00, 0x14, 0x04, 0x00, 0x10, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); +} -- cgit v1.1