diff options
| -rw-r--r-- | src/lib.rs | 32 | ||||
| -rw-r--r-- | tests/test.rs | 61 | 
2 files changed, 74 insertions, 19 deletions
| @@ -33,11 +33,11 @@ impl Default for Opcode {  #[derive(Debug, PartialEq, Eq, Copy, Clone)]  #[allow(non_camel_case_types)]  pub enum Opcode { -    // TODO: what kind of no-op/undefined are these exactly -    Purple, -    Cyan, -    Brown, -    White, +    // Undefined opcode regions come from manual page 3:299. +    Purple, // Reserved if PR[qp] = 1 +    Cyan,   // Reserved if PR[qp] = 1 +    Brown,  // Reserved +    White,  // Ignored; executes as nop (for hint space).      Addp4,      Adds, @@ -1313,21 +1313,31 @@ impl yaxpeax_arch::Instruction for InstructionBundle {              // Rotation size cannot be larger than frame.              (sor << 3) <= sof &&              // Local size cannot be larger than frame. -            sol <= sof && -            // Alloc cannot be predicated. -            insn.predicate() == 0 +            sol <= sof          };          for insn in &self.instructions {              match insn.opcode { -                // B8 family instructions cannot be predicated -                Opcode::Cover | Opcode::Clrrb | Opcode::Clrrb_pr | Opcode::Rfi | Opcode::Bsw_0 | Opcode::Bsw_1 | Opcode::Epc => { +                // Table 5-5 lists the "unpredicatable-instructions" instruction class, which is: +                // - the B2 instruction format for br.cloop, br.ctop, br.cexit +                Opcode::Br_cloop | Opcode::Br_cexit | Opcode::Br_ctop | +                // - the B6 and B7 instruction format for brp. Note however that B6 and B7 use the qp section of opcode +                //   to encode the prediction hint, so these are not included. +                // - the B8 instruction format for bsw.0, bsw.1, clrrrb, clrrrb.pr, cover, epc, rfi, vmsw.0, vmsw.1 +                Opcode::Cover | Opcode::Clrrb | Opcode::Clrrb_pr | Opcode::Rfi | Opcode::Bsw_0 | Opcode::Bsw_1 | Opcode::Epc | +                // - the M25 instruction format for flushrs, loadrs +                Opcode::Flushrs | Opcode::Loadrs | +                // - the M34 instruction format for alloc +                Opcode::Alloc | +                // - and br.ia. +                Opcode::Br_ia => {                      if insn.predicate() != 0 {                          return false;                      }                  },                  // Undefined opcode regions -                Opcode::Purple | Opcode::Cyan | Opcode::Brown | Opcode::White => { +                // Because Opcode::White instructions are defined to execute as `nop`, they are well-defined. +                Opcode::Purple | Opcode::Cyan | Opcode::Brown => {                      return false;                  },                  _ => {}, diff --git a/tests/test.rs b/tests/test.rs index 38b8060..d24fb90 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2364,14 +2364,6 @@ fn test_alloc_restrictions() {      assert_eq!(format!("{}", inst), expected);      assert!(!inst.well_defined()); -    // alloc cannot be predicated. -    let expected = "[MMI] (p02) alloc r34=ar.pfs,5,5,0; break.m 0x0; break.i 0x0"; -    let data = [0x48, 0x10, 0x15, 0x0a, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; -    let mut reader = U8Reader::new(&data[..]); -    let inst = decoder.decode(&mut reader).unwrap(); -    assert_eq!(format!("{}", inst), expected); -    assert!(!inst.well_defined()); -      // alloc cannot be in slot 1 of a bundle type without a stop before it.      let expected = "[MMI] break.m 0x0; alloc r34=ar.pfs,5,5,0; break.i 0x0";      let data = [0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2a, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -2393,6 +2385,28 @@ fn test_alloc_restrictions() {  fn test_predication_not_allowed() {      let decoder = InstDecoder::default(); +    // B2 instructions cannot be predicated +    let expected = "[BBB] (p01) br.cloop.sptk.few $+0x0; break.b 0x0; break.b 0x0"; +    let data = [0x36, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; +    let mut reader = U8Reader::new(&data[..]); +    let inst = decoder.decode(&mut reader).unwrap(); +    assert_eq!(format!("{}", inst), expected); +    assert!(!inst.well_defined()); + +    let expected = "[BBB] (p01) br.cexit.sptk.few $+0x0; break.b 0x0; break.b 0x0"; +    let data = [0x36, 0x30, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; +    let mut reader = U8Reader::new(&data[..]); +    let inst = decoder.decode(&mut reader).unwrap(); +    assert_eq!(format!("{}", inst), expected); +    assert!(!inst.well_defined()); + +    let expected = "[BBB] (p01) br.ctop.sptk.few $+0x0; break.b 0x0; break.b 0x0"; +    let data = [0x36, 0x38, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; +    let mut reader = U8Reader::new(&data[..]); +    let inst = decoder.decode(&mut reader).unwrap(); +    assert_eq!(format!("{}", inst), expected); +    assert!(!inst.well_defined()); +      // B8 instructions cannot be predicated      let expected = "[BBB] (p01) cover; break.b 0x0; break.b 0x0";      let data = [0x36, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -2442,4 +2456,35 @@ fn test_predication_not_allowed() {      let inst = decoder.decode(&mut reader).unwrap();      assert_eq!(format!("{}", inst), expected);      assert!(!inst.well_defined()); + +    // M25 instructions cannot be predicated. +    let expected = "[MMI] (p01) flushrs; break.m 0x0; break.i 0x0"; +    let data = [0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; +    let mut reader = U8Reader::new(&data[..]); +    let inst = decoder.decode(&mut reader).unwrap(); +    assert_eq!(format!("{}", inst), expected); +    assert!(!inst.well_defined()); + +    let expected = "[MMI] (p01) loadrs; break.m 0x0; break.i 0x0"; +    let data = [0x28, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; +    let mut reader = U8Reader::new(&data[..]); +    let inst = decoder.decode(&mut reader).unwrap(); +    assert_eq!(format!("{}", inst), expected); +    assert!(!inst.well_defined()); + +    // alloc cannot be predicated. +    let expected = "[MMI] (p02) alloc r34=ar.pfs,5,5,0; break.m 0x0; break.i 0x0"; +    let data = [0x48, 0x10, 0x15, 0x0a, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; +    let mut reader = U8Reader::new(&data[..]); +    let inst = decoder.decode(&mut reader).unwrap(); +    assert_eq!(format!("{}", inst), expected); +    assert!(!inst.well_defined()); + +    // br.ia cannot be predicated. +    let expected = "[BBB] (p01) br.ia b0,0x0,0x0,0x0; break.b 0x0; break.b 0x0"; +    let data = [0x36, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; +    let mut reader = U8Reader::new(&data[..]); +    let inst = decoder.decode(&mut reader).unwrap(); +    assert_eq!(format!("{}", inst), expected); +    assert!(!inst.well_defined());  } | 
