From dca858ff598689804cd98f9041b3fd706d563b48 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 11 Oct 2020 23:33:44 -0700 Subject: clean up more misunderstood opcodes, add missing M__ encodings --- src/lib.rs | 352 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 318 insertions(+), 34 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d410282..79a96b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,7 +53,6 @@ pub enum Opcode { Ptc_ga, Ttag, Ptr_d, - Mov_to_cr, Ptr_i, Mov_to_psr_l, Itr_d, @@ -206,7 +205,6 @@ pub enum Opcode { Probe_w_fault, Mov_to_pmc, Mov_from_pmc, - Mov_from_cr, Ptc_e, Ldfp_a, Ldfp_sa, @@ -249,7 +247,6 @@ pub enum Opcode { Ldfps_sa, Ldfpd_sa, - Mov_m_to_ar, Mov_from_pkr, Setf_sig, Setf_exp, @@ -575,7 +572,6 @@ impl fmt::Display for Opcode { Opcode::Ptc_ga => { write!(f, "ptc.ga") } Opcode::Ttag => { write!(f, "ttag") } Opcode::Ptr_d => { write!(f, "ptr.d") } - Opcode::Mov_to_cr => { write!(f, "mov.to.cr") } Opcode::Ptr_i => { write!(f, "ptr.i") } Opcode::Mov_to_psr_l => { write!(f, "mov.to.psr.l") } Opcode::Itr_d => { write!(f, "itr.d") } @@ -728,7 +724,6 @@ impl fmt::Display for Opcode { Opcode::Probe_w_fault => { write!(f, "probe.w.fault") } Opcode::Mov_to_pmc => { write!(f, "mov.to.pmc") } Opcode::Mov_from_pmc => { write!(f, "mov.from.pmc") } - Opcode::Mov_from_cr => { write!(f, "mov.from.cr") } Opcode::Ptc_e => { write!(f, "ptc.e") } Opcode::Ldfp_a => { write!(f, "ldfp.a") } Opcode::Ldfp_sa => { write!(f, "ldfp.sa") } @@ -771,7 +766,6 @@ impl fmt::Display for Opcode { Opcode::Ldfps_sa => { write!(f, "ldfps.sa") } Opcode::Ldfpd_sa => { write!(f, "ldfpd.sa") } - Opcode::Mov_m_to_ar => { write!(f, "mov.m.to.ar") } Opcode::Mov_from_pkr => { write!(f, "mov.from.pkr") } Opcode::Setf_sig => { write!(f, "setf.sig") } Opcode::Setf_exp => { write!(f, "setf.exp") } @@ -1077,7 +1071,6 @@ pub struct Instruction { // specify which operand, if any, is the last written operand in an instruction. dest_boundary: Option, operands: [Operand; 5], - prefetch_hint: Option, } impl fmt::Display for Instruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1250,13 +1243,6 @@ impl fmt::Display for Instruction { } } #[derive(Debug, PartialEq, Eq)] -pub enum PrefetchHint { - None, - Nt1, - Nt2, - Nta, -} -#[derive(Debug, PartialEq, Eq)] pub struct InstructionBundle { bundle_tag: u8, instructions: [Instruction; 3], @@ -1368,6 +1354,13 @@ impl fmt::Display for PredicateRegister { } } #[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct ControlRegister(pub u8); +impl fmt::Display for ControlRegister { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "cr{}", self.0) + } +} +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct BranchRegister(pub u8); // 8 64-bit registers impl fmt::Display for BranchRegister { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1375,6 +1368,34 @@ impl fmt::Display for BranchRegister { } } #[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum IndirectionReg { + Cpuid, + Dbr, + Dtr, + Ibr, + Itr, + Pkr, + Pmc, + Pmd, + Rr, +} +impl fmt::Display for IndirectionReg { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use IndirectionReg::*; + match self { + Cpuid => write!(f, "cpuid"), + Dbr => write!(f, "dbr"), + Dtr => write!(f, "dtr"), + Ibr => write!(f, "ibr"), + Itr => write!(f, "itr"), + Pkr => write!(f, "pkr"), + Pmc => write!(f, "pmc"), + Pmd => write!(f, "pmd"), + Rr => write!(f, "rr"), + } + } +} +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct ApplicationRegister(pub u8); // 128 64-bit(?) registers impl fmt::Display for ApplicationRegister { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1458,6 +1479,7 @@ impl ApplicationRegister { pub const EC: ApplicationRegister = ApplicationRegister(66); } +#[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Operand { None, @@ -1468,10 +1490,14 @@ pub enum Operand { ImmU64(u64), Memory(GPRegister), PSR, // processor status register (see 3.3.2) + PSR_l, // lower 32 bits of psr + PSR_um, // user mask of psr (bits [0,5]) PR, // predicate register (all 64 bits) IP, // is this an application register? distinct? ApplicationRegister(ApplicationRegister), BranchRegister(BranchRegister), + ControlRegister(ControlRegister), + Indirection(IndirectionReg, GPRegister), } impl Operand { @@ -1509,7 +1535,11 @@ impl fmt::Display for Operand { Operand::PredicateRegister(reg) => { write!(f, "{}", reg) }, Operand::ApplicationRegister(reg) => { write!(f, "{}", reg) }, Operand::BranchRegister(reg) => { write!(f, "{}", reg) }, + Operand::ControlRegister(reg) => { write!(f, "{}", reg) }, + Operand::Indirection(ir, reg) => { write!(f, "{}[{}]", ir, reg) }, Operand::PSR => { write!(f, "psr") }, + Operand::PSR_l => { write!(f, "psr.l") }, + Operand::PSR_um => { write!(f, "psr.um") }, Operand::PR => { write!(f, "pr") }, Operand::IP => { write!(f, "ip") }, } @@ -1632,8 +1662,6 @@ impl Decoder for InstDecoder { predicate: word[0..6].load::(), dest_boundary, operands, - // TODO: figure out hints - prefetch_hint: None, } } @@ -1657,8 +1685,6 @@ impl Decoder for InstDecoder { predicate: word[0..6].load::(), dest_boundary, operands, - // TODO: figure out hints - prefetch_hint: None, } }, InstructionType::F => { @@ -1753,8 +1779,6 @@ impl Decoder for InstDecoder { predicate: word[0..6].load::(), dest_boundary, operands, - // TODO: figure out hints - prefetch_hint: None, } }, InstructionType::B => { @@ -1772,8 +1796,6 @@ impl Decoder for InstDecoder { predicate, dest_boundary, operands, - // TODO: figure out hints - prefetch_hint: None, } }, InstructionType::L => { @@ -1801,8 +1823,6 @@ impl Decoder for InstDecoder { predicate: word[0..6].load::(), dest_boundary, operands, - // TODO: figure out hints - prefetch_hint: None, } } InstructionType::M => { @@ -1836,8 +1856,6 @@ impl Decoder for InstDecoder { predicate: word[0..6].load::(), dest_boundary, operands, - // TODO: figure out hints - prefetch_hint: None, } } InstructionType::X => unreachable!("should never try to decode InstructionType::X, preceded by an InstructionType::L that may have been missed?") @@ -2375,7 +2393,7 @@ fn read_i_operands(encoding: OperandEncodingI, word: &BitSlice) -> (Op let r1 = word[6..13].load::(); let z = word[13..20].load::(); // TODO: error on this properly? is this a #ud-like? - assert_eq!(z, 0); + // assert_eq!(z, 0); let r3 = word[20..27].load::(); two_op( Some(0), @@ -2630,7 +2648,7 @@ fn read_i_operands(encoding: OperandEncodingI, word: &BitSlice) -> (Op let imm = word[14..19].load::(); let z = word[20..27].load::(); // TODO: what happens when this field isn't actually zero? - assert_eq!(z, 0); + // assert_eq!(z, 0); let p2 = word[27..33].load::(); three_op( Some(1), @@ -2644,6 +2662,7 @@ fn read_i_operands(encoding: OperandEncodingI, word: &BitSlice) -> (Op fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Option, [Operand; 5]) { use OperandEncodingM::*; match encoding { + None => { unreachable!("none operand encoding"); } M1 => { let r1 = word[6..13].load::(); let _ = word[13..20].load::(); @@ -2816,7 +2835,19 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Op Operand::GPRegister(GPRegister(r2)), ) } - // TODO: m15? + M15 => { + let _ = word[6..13].load::(); + let imm7b = word[13..20].load::(); + let r3 = word[20..27].load::(); + let i = word[27] as u16; + let s = word[36] as u16; + let imm = (s << 8) + (i << 7) + imm7b; + two_op( + Option::None, + Operand::Memory(GPRegister(r3)), + Operand::ImmI64(imm as i64), + ) + } M16 => { let r1 = word[6..13].load::(); let r2 = word[13..20].load::(); @@ -2860,6 +2891,79 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Op Operand::FloatRegister(FloatRegister(f2)), ) } + M20 => { + let imm7a = word[6..13].load::(); + let r2 = word[13..20].load::(); + let imm13c = word[20..33].load::(); + let s = word[36] as u32; + let imm = (((imm7a + (imm13c << 7) + (s << 20)) as i32) << 11) >> 11; + two_op( + Option::None, + Operand::GPRegister(GPRegister(r2)), + Operand::ImmI64(imm as i64), + ) + } + M21 => { + let imm7a = word[6..13].load::(); + let f2 = word[13..20].load::(); + let imm13c = word[20..33].load::(); + let s = word[36] as u32; + let imm = (((imm7a + (imm13c << 7) + (s << 20)) as i32) << 11) >> 11; + two_op( + Option::None, + Operand::FloatRegister(FloatRegister(f2)), + Operand::ImmI64(imm as i64), + ) + } + M22 => { + let r1 = word[6..13].load::(); + let imm20b = word[13..33].load::(); + let s = word[36] as u32; + let imm = ((imm20b + (s << 20)) << 11) >> 11; + two_op( + Option::None, + Operand::GPRegister(GPRegister(r1)), + Operand::ImmI64(imm as i64), + ) + } + M23 => { + let f1 = word[6..13].load::(); + let imm20b = word[13..33].load::(); + let s = word[36] as u32; + let imm = ((imm20b + (s << 20)) << 11) >> 11; + two_op( + Option::None, + Operand::FloatRegister(FloatRegister(f1)), + Operand::ImmI64(imm as i64), + ) + } + M24 => { + one_op(false, Operand::None) + } + M25 => { + one_op(false, Operand::None) + } + M26 => { + let r1 = word[6..13].load::(); + one_op( + false, + Operand::GPRegister(GPRegister(r1)), + ) + } + M27 => { + let f1 = word[6..13].load::(); + one_op( + false, + Operand::FloatRegister(FloatRegister(f1)), + ) + } + M28 => { + let r3 = word[20..27].load::(); + one_op( + false, + Operand::GPRegister(GPRegister(r3)), + ) + } M29 => { let _ = word[6..13].load::(); let r2 = word[13..20].load::(); @@ -2870,6 +2974,18 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Op Operand::GPRegister(GPRegister(r2)), ) } + M30 => { + let _ = word[6..13].load::(); + let imm7b = word[13..20].load::(); + let ar3 = word[20..27].load::(); + let s = word[36] as u8; + let imm = imm7b + (s << 7); + two_op( + Some(0), + Operand::ApplicationRegister(ApplicationRegister(ar3)), + Operand::ImmI64(imm as i8 as i64), + ) + } M31 => { let r1 = word[6..13].load::(); let _ = word[13..20].load::(); @@ -2880,6 +2996,26 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Op Operand::ApplicationRegister(ApplicationRegister(ar3)), ) } + M32 => { + let _ = word[6..13].load::(); + let r2 = word[13..20].load::(); + let cr3 = word[20..27].load::(); + two_op( + Some(0), + Operand::ControlRegister(ControlRegister(cr3)), + Operand::GPRegister(GPRegister(r2)), + ) + } + M33 => { + let r1 = word[6..13].load::(); + let _ = word[13..20].load::(); + let cr3 = word[20..27].load::(); + two_op( + Some(0), + Operand::GPRegister(GPRegister(r1)), + Operand::ControlRegister(ControlRegister(cr3)), + ) + } M34 => { let r1 = word[6..13].load::(); let sof = word[13..20].load::(); @@ -2896,15 +3032,163 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice) -> (Op ] ) } - M48 => { + M35 => { + let r2 = word[13..20].load::(); + let x6 = word[27..33].load::(); + let psr = if x6 == 0x2d { + Operand::PSR_l + } else if x6 == 0x29 { + Operand::PSR_um + } else { + Operand::None + }; + two_op( + Some(0), + psr, + Operand::GPRegister(GPRegister(r2)), + ) + } + M36 => { + let r1 = word[6..13].load::(); + let x6 = word[27..33].load::(); + let psr = if x6 == 0x25 { + Operand::PSR + } else if x6 == 0x21 { + Operand::PSR_um + } else { + Operand::None + }; + two_op( + Some(0), + Operand::GPRegister(GPRegister(r1)), + psr, + ) + } + M37 => { let i = word[6..26].load::() + ((word[36] as u32) << 20); one_op( false, Operand::ImmU64(i as u64), ) } - other => { - unimplemented!("unimplemented m operand encoding: {:?}", other); + M38 => { + let r1 = word[6..13].load::(); + let r2 = word[13..20].load::(); + let r3 = word[20..27].load::(); + three_op( + Some(0), + Operand::GPRegister(GPRegister(r1)), + Operand::GPRegister(GPRegister(r3)), + Operand::GPRegister(GPRegister(r2)), + ) + } + M39 => { + let r1 = word[6..13].load::(); + let i2b = word[13..15].load::(); + let r3 = word[20..27].load::(); + three_op( + Some(0), + Operand::GPRegister(GPRegister(r1)), + Operand::GPRegister(GPRegister(r3)), + Operand::ImmU64(i2b as u64), + ) + } + M40 => { + let i2b = word[13..15].load::(); + let r3 = word[20..27].load::(); + two_op( + Option::None, + Operand::GPRegister(GPRegister(r3)), + Operand::ImmU64(i2b as u64), + ) + } + M41 => { + let r2 = word[13..20].load::(); + one_op( + false, + Operand::GPRegister(GPRegister(r2)), + ) + } + M42 => { + let x6 = word[27..33].load::(); + let ind = match x6 { + 0x00 => IndirectionReg::Rr, + 0x01 => IndirectionReg::Dbr, + 0x02 => IndirectionReg::Ibr, + 0x03 => IndirectionReg::Pkr, + 0x04 => IndirectionReg::Pmc, + 0x05 => IndirectionReg::Pmd, + 0x0e => IndirectionReg::Dtr, + 0x0f => IndirectionReg::Itr, + _ => { return one_op(false, Operand::None); } + }; + let r2 = word[13..20].load::(); + let r3 = word[20..27].load::(); + two_op( + Some(0), + Operand::Indirection(ind, GPRegister(r3)), + Operand::GPRegister(GPRegister(r2)), + ) + } + M43 => { + let x6 = word[27..33].load::(); + let ind = match x6 { + 0x10 => IndirectionReg::Rr, + 0x11 => IndirectionReg::Dbr, + 0x12 => IndirectionReg::Ibr, + 0x13 => IndirectionReg::Pkr, + 0x14 => IndirectionReg::Pmc, + 0x15 => IndirectionReg::Cpuid, + 0x17 => IndirectionReg::Pmd, + _ => { return one_op(false, Operand::None); } + }; + let r2 = word[13..20].load::(); + let r3 = word[20..27].load::(); + two_op( + Some(0), + Operand::GPRegister(GPRegister(r2)), + Operand::Indirection(ind, GPRegister(r3)), + ) + } + M44 => { + let imm21a = word[6..27].load::(); + let i2d = word[31..33].load::(); + let i = word[36] as u32; + // TODO: probably have the order wrong here + let imm = imm21a + (i2d << 21) + (i << 23); + one_op( + false, + Operand::ImmU64(imm as u64), + ) + } + M45 => { + let r2 = word[13..20].load::(); + let r3 = word[20..27].load::(); + two_op( + Option::None, + Operand::GPRegister(GPRegister(r3)), + Operand::GPRegister(GPRegister(r2)), + ) + } + M46 => { + let r1 = word[6..13].load::(); + let r3 = word[20..27].load::(); + two_op( + Some(0), + Operand::GPRegister(GPRegister(r1)), + Operand::GPRegister(GPRegister(r3)), + ) + } + M47 => { + let r3 = word[20..27].load::(); + one_op(false, Operand::GPRegister(GPRegister(r3))) + } + M48 => { + let i = word[6..26].load::() + ((word[36] as u32) << 20); + one_op( + false, + Operand::ImmU64(i as u64), + ) } } } @@ -3602,7 +3886,7 @@ fn get_m_opcode_and_encoding(tag: u8, word: &BitSlice) -> (Opcode, Ope (Rum, M44), (Rum, M44), (Rum, M44), (Rum, M44), (Ssm, M44), (Ssm, M44), (Ssm, M44), (Ssm, M44), (Rsm, M44), (Rsm, M44), (Rsm, M44), (Rsm, M44), - (Purple, None), (Purple, None), (Mov_m_to_ar, M30), (Purple, None), + (Purple, None), (Purple, None), (Mov_m, M30), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Loadrs, M25), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), @@ -3643,7 +3927,7 @@ fn get_m_opcode_and_encoding(tag: u8, word: &BitSlice) -> (Opcode, Ope const TABLE4_45: [(Opcode, OperandEncodingM); 64] = [ (Mov_to_rr, M42), (Mov_to_dbr, M42), (Mov_to_ibr, M42), (Mov_to_pkr, M43), (Mov_to_pmc, M42), (Mov_to_pmd, 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_from_rr, M43),(Mov_from_dbr, M43), (Mov_from_ibr, M43), (Mov_from_pkr, M43), (Mov_from_pmc, M43), (Mov_from_pmd, M43), (Purple, None), (Mov_from_cpuid, M43), (Probe_r, M39), (Probe_w, M39), (Thash, M46), (Ttag, M46), (Purple, None), (Purple, None), (Tpa, M46), (Tak, M46), - (Purple, None), (Mov_from_psr_um, M36), (Mov_m, M31), (Purple, None), (Mov_from_cr, M33), (Mov_from_psr, M36), (Purple, None), (Purple, None), (Purple, None), (Mov_to_psr_um, M35), (Mov_m, M29), (Purple, None), (Mov_to_cr, M32), (Mov_to_psr_l, M35), (Itc_d, M41), (Itc_i, M41), + (Purple, None), (Mov_from_psr_um, M36), (Mov_m, M31), (Purple, None), (Mov, M33), (Mov_from_psr, M36), (Purple, None), (Purple, None), (Purple, None), (Mov_to_psr_um, M35), (Mov_m, M29), (Purple, None), (Mov, M32), (Mov_to_psr_l, 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), ]; let index = word[27..33].load::(); -- cgit v1.1