From a781322552d9fb52b7b5e51641f49f12678f682f Mon Sep 17 00:00:00 2001
From: iximeow <me@iximeow.net>
Date: Thu, 1 Jul 2021 23:54:06 -0700
Subject: reallocate OperandCode, convert disparate registers to array

also remove redundant assignments of operand_count and some OperandSpec,
bulk-assign all registers and operands on entry to `read_instr`. this
all, taken together, shaves off about 7 cycles per decode.
---
 test/long_mode/display.rs             |  3 ++-
 test/long_mode/evex_generated.rs      |  8 +++++---
 test/long_mode/mod.rs                 |  6 ++++--
 test/long_mode/operand.rs             | 14 +++++++-------
 test/long_mode/reuse_test.rs          | 10 +++++++---
 test/protected_mode/display.rs        |  3 ++-
 test/protected_mode/evex_generated.rs |  8 +++++---
 test/protected_mode/mod.rs            |  6 ++++--
 8 files changed, 36 insertions(+), 22 deletions(-)

(limited to 'test')

diff --git a/test/long_mode/display.rs b/test/long_mode/display.rs
index 4ef3f74..fc59427 100644
--- a/test/long_mode/display.rs
+++ b/test/long_mode/display.rs
@@ -12,7 +12,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
     for b in data {
         write!(hex, "{:02x}", b).unwrap();
     }
-    match decoder.decode(data.into_iter().map(|x| *x)) {
+    let mut reader = yaxpeax_arch::U8Reader::new(data);
+    match decoder.decode(&mut reader) {
         Ok(instr) => {
             let text = format!("{}", instr.display_with(DisplayStyle::C));
             assert!(
diff --git a/test/long_mode/evex_generated.rs b/test/long_mode/evex_generated.rs
index 9c23e4b..dcb4e01 100644
--- a/test/long_mode/evex_generated.rs
+++ b/test/long_mode/evex_generated.rs
@@ -1,6 +1,6 @@
 use std::fmt::Write;
 
-use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction};
+use yaxpeax_arch::{AddressBase, Decoder, U8Reader, LengthedInstruction};
 use yaxpeax_x86::long_mode::InstDecoder;
 
 #[allow(dead_code)]
@@ -9,7 +9,8 @@ fn test_invalid(data: &[u8]) {
 }
 
 fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) {
-    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) {
+    let mut reader = U8Reader::new(data);
+    if let Ok(inst) = decoder.decode(&mut reader) {
         panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);
     } else {
         // this is fine
@@ -26,7 +27,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
     for b in data {
         write!(hex, "{:02x}", b).unwrap();
     }
-    match decoder.decode(data.into_iter().map(|x| *x)) {
+    let mut reader = U8Reader::new(data);
+    match decoder.decode(&mut reader) {
         Ok(instr) => {
             let text = format!("{}", instr);
             assert!(
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index cbd881c..1eedfec 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -16,7 +16,8 @@ fn test_invalid(data: &[u8]) {
 }
 
 fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) {
-    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) {
+    let mut reader = yaxpeax_arch::U8Reader::new(data);
+    if let Ok(inst) = decoder.decode(&mut reader)  {
         panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);
     } else {
         // this is fine
@@ -32,7 +33,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
     for b in data {
         write!(hex, "{:02x}", b).unwrap();
     }
-    match decoder.decode(data.into_iter().map(|x| *x)) {
+    let mut reader = yaxpeax_arch::U8Reader::new(data);
+    match decoder.decode(&mut reader) {
         Ok(instr) => {
             let text = format!("{}", instr);
             assert!(
diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs
index f0300d6..77ce256 100644
--- a/test/long_mode/operand.rs
+++ b/test/long_mode/operand.rs
@@ -2,15 +2,15 @@ use yaxpeax_x86::long_mode::{Operand, RegSpec};
 
 #[test]
 fn register_widths() {
-    assert_eq!(Operand::Register(RegSpec::rsp()).width(), 8);
-    assert_eq!(Operand::Register(RegSpec::esp()).width(), 4);
-    assert_eq!(Operand::Register(RegSpec::sp()).width(), 2);
-    assert_eq!(Operand::Register(RegSpec::cl()).width(), 1);
-    assert_eq!(Operand::Register(RegSpec::ch()).width(), 1);
-    assert_eq!(Operand::Register(RegSpec::gs()).width(), 2);
+    assert_eq!(Operand::Register(RegSpec::rsp()).width(), Some(8));
+    assert_eq!(Operand::Register(RegSpec::esp()).width(), Some(4));
+    assert_eq!(Operand::Register(RegSpec::sp()).width(), Some(2));
+    assert_eq!(Operand::Register(RegSpec::cl()).width(), Some(1));
+    assert_eq!(Operand::Register(RegSpec::ch()).width(), Some(1));
+    assert_eq!(Operand::Register(RegSpec::gs()).width(), Some(2));
 }
 
 #[test]
 fn memory_widths() {
-    assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), 8);
+    assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), None);
 }
diff --git a/test/long_mode/reuse_test.rs b/test/long_mode/reuse_test.rs
index 117f3fa..60a91e1 100644
--- a/test/long_mode/reuse_test.rs
+++ b/test/long_mode/reuse_test.rs
@@ -1989,17 +1989,21 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [
 #[test]
 fn test_against_leftover_data() {
     use super::rand::{thread_rng, Rng};
+    use yaxpeax_arch::U8Reader;
     let mut rng = thread_rng();
 
     let decoder = InstDecoder::default();
 
     for _ in 0..100000 {
         let first_vec = INSTRUCTIONS[rng.gen_range(0..INSTRUCTIONS.len())];
-        let first_decode = decoder.decode(first_vec.to_vec().iter().cloned()).unwrap();
+        let mut first_reader = U8Reader::new(first_vec);
+        let first_decode = decoder.decode(&mut first_reader).unwrap();
 
         let second_vec = INSTRUCTIONS[rng.gen_range(0..INSTRUCTIONS.len())];
-        let mut reused_decode = decoder.decode(second_vec.to_vec().iter().cloned()).unwrap();
-        decoder.decode_into(&mut reused_decode, first_vec.to_vec().iter().cloned()).unwrap();
+        let mut second_reader = U8Reader::new(second_vec);
+        let mut reused_decode = decoder.decode(&mut second_reader).unwrap();
+        let mut first_reader = U8Reader::new(first_vec);
+        decoder.decode_into(&mut reused_decode, &mut first_reader).unwrap();
 
         assert_eq!(first_decode, reused_decode);
     }
diff --git a/test/protected_mode/display.rs b/test/protected_mode/display.rs
index 8426a0a..694c38c 100644
--- a/test/protected_mode/display.rs
+++ b/test/protected_mode/display.rs
@@ -12,7 +12,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
     for b in data {
         write!(hex, "{:02x}", b).unwrap();
     }
-    match decoder.decode(data.into_iter().map(|x| *x)) {
+    let mut reader = yaxpeax_arch::U8Reader::new(data);
+    match decoder.decode(&mut reader) {
         Ok(instr) => {
             let text = format!("{}", instr.display_with(DisplayStyle::C));
             assert!(
diff --git a/test/protected_mode/evex_generated.rs b/test/protected_mode/evex_generated.rs
index 333c3c6..236edec 100644
--- a/test/protected_mode/evex_generated.rs
+++ b/test/protected_mode/evex_generated.rs
@@ -1,6 +1,6 @@
 use std::fmt::Write;
 
-use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction};
+use yaxpeax_arch::{AddressBase, Decoder, U8Reader, LengthedInstruction};
 use yaxpeax_x86::protected_mode::InstDecoder;
 
 #[allow(dead_code)]
@@ -9,7 +9,8 @@ fn test_invalid(data: &[u8]) {
 }
 
 fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) {
-    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) {
+    let mut reader = U8Reader::new(data);
+    if let Ok(inst) = decoder.decode(&mut reader) {
         panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);
     } else {
         // this is fine
@@ -26,7 +27,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
     for b in data {
         write!(hex, "{:02x}", b).unwrap();
     }
-    match decoder.decode(data.into_iter().map(|x| *x)) {
+    let mut reader = U8Reader::new(data);
+    match decoder.decode(&mut reader) {
         Ok(instr) => {
             let text = format!("{}", instr);
             assert!(
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index 6e2ded9..9221e7d 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -13,7 +13,8 @@ fn test_invalid(data: &[u8]) {
 }
 
 fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) {
-    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) {
+    let mut reader = yaxpeax_arch::U8Reader::new(data);
+    if let Ok(inst) = decoder.decode(&mut reader) {
         panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);
     } else {
         // this is fine
@@ -29,7 +30,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
     for b in data {
         write!(hex, "{:02x}", b).unwrap();
     }
-    match decoder.decode(data.into_iter().map(|x| *x)) {
+    let mut reader = yaxpeax_arch::U8Reader::new(data);
+    match decoder.decode(&mut reader) {
         Ok(instr) => {
             let text = format!("{}", instr);
             assert!(
-- 
cgit v1.1