add instruction enum to code item
This commit is contained in:
parent
ee7cf4d325
commit
81c8d0a8ec
2 changed files with 122 additions and 39 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
//! Code items
|
//! Code items
|
||||||
|
|
||||||
use crate as androscalpel_serializer;
|
use crate as androscalpel_serializer;
|
||||||
use crate::{Error, ReadSeek, Result, Serializable, Sleb128, Uleb128};
|
use crate::{Error, Instruction, ReadSeek, Result, Serializable, Sleb128, Uleb128};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ pub struct CodeItem {
|
||||||
/// 0 if no debug info, else offset to a [`crate::DebugInfoItem`].
|
/// 0 if no debug info, else offset to a [`crate::DebugInfoItem`].
|
||||||
pub debug_info_off: u32,
|
pub debug_info_off: u32,
|
||||||
// pub insns_size: u32,
|
// pub insns_size: u32,
|
||||||
pub insns: Vec<u16>,
|
pub insns: Vec<Instruction>,
|
||||||
// pub padding: Vec<u8>,
|
// pub padding: Vec<u8>,
|
||||||
/// try items must refere to non overlapping range an order from low to hight addresses.
|
/// try items must refere to non overlapping range an order from low to hight addresses.
|
||||||
pub tries: Vec<TryItem>,
|
pub tries: Vec<TryItem>,
|
||||||
|
|
@ -29,7 +29,7 @@ impl CodeItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insns_size_field(&self) -> u32 {
|
pub fn insns_size_field(&self) -> u32 {
|
||||||
self.insns.len() as u32
|
self.insns.iter().map(|ins| ins.size() as u32).sum::<u32>() / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sanity_check(&self) -> Result<()> {
|
pub fn sanity_check(&self) -> Result<()> {
|
||||||
|
|
@ -56,7 +56,7 @@ impl CodeItem {
|
||||||
/*
|
/*
|
||||||
// Necessary? no in spec and apk in the wild seams to have try blocks spaming outside the
|
// Necessary? no in spec and apk in the wild seams to have try blocks spaming outside the
|
||||||
// insns array.
|
// insns array.
|
||||||
if max_addr > self.insns.len() as u32 {
|
if max_addr > self.insns_size_field() {
|
||||||
return Err(Error::InconsistantStruct(
|
return Err(Error::InconsistantStruct(
|
||||||
"found try_item whose block span outside of the insns array".into(),
|
"found try_item whose block span outside of the insns array".into(),
|
||||||
));
|
));
|
||||||
|
|
@ -72,7 +72,7 @@ impl CodeItem {
|
||||||
handler.sanity_check()?;
|
handler.sanity_check()?;
|
||||||
for handler in &handler.handlers {
|
for handler in &handler.handlers {
|
||||||
// Necessary? no in spec
|
// Necessary? no in spec
|
||||||
if handler.addr.0 > self.insns.len() as u32 {
|
if handler.addr.0 > self.insns_size_field() {
|
||||||
return Err(Error::InconsistantStruct(
|
return Err(Error::InconsistantStruct(
|
||||||
"Found an handler whose address is outside of the insns array".into(),
|
"Found an handler whose address is outside of the insns array".into(),
|
||||||
));
|
));
|
||||||
|
|
@ -80,7 +80,7 @@ impl CodeItem {
|
||||||
}
|
}
|
||||||
if let Some(Uleb128(addr)) = handler.catch_all_addr {
|
if let Some(Uleb128(addr)) = handler.catch_all_addr {
|
||||||
// Necessary? no in spec
|
// Necessary? no in spec
|
||||||
if addr > self.insns.len() as u32 {
|
if addr > self.insns_size_field() {
|
||||||
return Err(Error::InconsistantStruct(
|
return Err(Error::InconsistantStruct(
|
||||||
"Found a catch all handler whose address is outside of the insns array"
|
"Found a catch all handler whose address is outside of the insns array"
|
||||||
.into(),
|
.into(),
|
||||||
|
|
@ -88,6 +88,46 @@ impl CodeItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut addresses = vec![];
|
||||||
|
for try_ in &self.tries {
|
||||||
|
addresses.push(try_.start_addr);
|
||||||
|
addresses.push(try_.start_addr + try_.insn_count as u32);
|
||||||
|
}
|
||||||
|
for handler in &self.handlers {
|
||||||
|
for catch in &handler.list {
|
||||||
|
for EncodedTypeAddrPair {
|
||||||
|
addr: Uleb128(addr),
|
||||||
|
..
|
||||||
|
} in &catch.handlers
|
||||||
|
{
|
||||||
|
addresses.push(*addr);
|
||||||
|
}
|
||||||
|
if let Some(Uleb128(addr)) = catch.catch_all_addr {
|
||||||
|
addresses.push(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addresses.sort();
|
||||||
|
let mut addr = 0;
|
||||||
|
let mut i = 0;
|
||||||
|
while i < addresses.len() && addresses[i] == addr {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
for insn in &self.insns {
|
||||||
|
addr += insn.size() as u32;
|
||||||
|
while i < addresses.len() && addresses[i] == addr {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i < addresses.len() && addresses[i] < addr {
|
||||||
|
return Err(Error::InconsistantStruct(format!(
|
||||||
|
"Found an address in try block (0x{addr:x}) that does not align with an instruction"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO check goto addresses? pb: op code are not parsed so goto instruction are not known
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -127,9 +167,13 @@ impl Serializable for CodeItem {
|
||||||
let tries_size = u16::deserialize(input)?;
|
let tries_size = u16::deserialize(input)?;
|
||||||
let debug_info_off = u32::deserialize(input)?;
|
let debug_info_off = u32::deserialize(input)?;
|
||||||
let insns_size = u32::deserialize(input)?;
|
let insns_size = u32::deserialize(input)?;
|
||||||
|
|
||||||
let mut insns = vec![];
|
let mut insns = vec![];
|
||||||
for _ in 0..insns_size {
|
let mut serialized_insns_size = 0;
|
||||||
insns.push(u16::deserialize(input)?);
|
while serialized_insns_size != insns_size {
|
||||||
|
let ins = Instruction::deserialize(input)?;
|
||||||
|
serialized_insns_size += ins.size() as u32;
|
||||||
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
if tries_size != 0 && insns_size % 2 == 1 {
|
if tries_size != 0 && insns_size % 2 == 1 {
|
||||||
let _ = u16::deserialize(input)?;
|
let _ = u16::deserialize(input)?;
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,6 @@ impl Instruction {
|
||||||
requires the first byte to be 0 found {v}"
|
requires the first byte to be 0 found {v}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// TODO: check bytes order
|
|
||||||
let a = i16::deserialize(input)?;
|
let a = i16::deserialize(input)?;
|
||||||
Ok(Self::Format20T { op, a })
|
Ok(Self::Format20T { op, a })
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +276,6 @@ impl Instruction {
|
||||||
pub fn deserialize_20bc(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_20bc(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let a = i8::deserialize(input)?;
|
let a = i8::deserialize(input)?;
|
||||||
// TODO: check bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
Ok(Self::Format20BC { a, op, b })
|
Ok(Self::Format20BC { a, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -285,7 +283,6 @@ impl Instruction {
|
||||||
pub fn deserialize_22x(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_22x(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
// TODO: check bytes order
|
|
||||||
let vb = u16::deserialize(input)?;
|
let vb = u16::deserialize(input)?;
|
||||||
Ok(Self::Format22X { va, op, vb })
|
Ok(Self::Format22X { va, op, vb })
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +290,6 @@ impl Instruction {
|
||||||
pub fn deserialize_21t(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_21t(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
// TODO: check bytes order
|
|
||||||
let b = i16::deserialize(input)?;
|
let b = i16::deserialize(input)?;
|
||||||
Ok(Self::Format21T { va, op, b })
|
Ok(Self::Format21T { va, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +297,6 @@ impl Instruction {
|
||||||
pub fn deserialize_21s(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_21s(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
// TODO: check bytes order
|
|
||||||
let b = i16::deserialize(input)?;
|
let b = i16::deserialize(input)?;
|
||||||
Ok(Self::Format21S { va, op, b })
|
Ok(Self::Format21S { va, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -309,7 +304,6 @@ impl Instruction {
|
||||||
pub fn deserialize_21h(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_21h(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
// TODO: check bytes order
|
|
||||||
let b = i16::deserialize(input)?;
|
let b = i16::deserialize(input)?;
|
||||||
Ok(Self::Format21H { va, op, b })
|
Ok(Self::Format21H { va, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -317,7 +311,6 @@ impl Instruction {
|
||||||
pub fn deserialize_21c(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_21c(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
// TODO: check bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
Ok(Self::Format21C { va, op, b })
|
Ok(Self::Format21C { va, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +336,6 @@ impl Instruction {
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
let va = val & 0b0000_1111;
|
let va = val & 0b0000_1111;
|
||||||
let vb = (val & 0b1111_0000) >> 4;
|
let vb = (val & 0b1111_0000) >> 4;
|
||||||
// TODO: check bytes order
|
|
||||||
let c = i16::deserialize(input)?;
|
let c = i16::deserialize(input)?;
|
||||||
Ok(Self::Format22T { vb, va, op, c })
|
Ok(Self::Format22T { vb, va, op, c })
|
||||||
}
|
}
|
||||||
|
|
@ -353,7 +345,6 @@ impl Instruction {
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
let va = val & 0b0000_1111;
|
let va = val & 0b0000_1111;
|
||||||
let vb = (val & 0b1111_0000) >> 4;
|
let vb = (val & 0b1111_0000) >> 4;
|
||||||
// TODO: check bytes order
|
|
||||||
let c = i16::deserialize(input)?;
|
let c = i16::deserialize(input)?;
|
||||||
Ok(Self::Format22S { vb, va, op, c })
|
Ok(Self::Format22S { vb, va, op, c })
|
||||||
}
|
}
|
||||||
|
|
@ -363,7 +354,6 @@ impl Instruction {
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
let va = val & 0b0000_1111;
|
let va = val & 0b0000_1111;
|
||||||
let vb = (val & 0b1111_0000) >> 4;
|
let vb = (val & 0b1111_0000) >> 4;
|
||||||
// TODO: check bytes order
|
|
||||||
let c = u16::deserialize(input)?;
|
let c = u16::deserialize(input)?;
|
||||||
Ok(Self::Format22C { vb, va, op, c })
|
Ok(Self::Format22C { vb, va, op, c })
|
||||||
}
|
}
|
||||||
|
|
@ -373,7 +363,6 @@ impl Instruction {
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
let va = val & 0b0000_1111;
|
let va = val & 0b0000_1111;
|
||||||
let vb = (val & 0b1111_0000) >> 4;
|
let vb = (val & 0b1111_0000) >> 4;
|
||||||
// TODO: check bytes order
|
|
||||||
let c = u16::deserialize(input)?;
|
let c = u16::deserialize(input)?;
|
||||||
Ok(Self::Format22CS { vb, va, op, c })
|
Ok(Self::Format22CS { vb, va, op, c })
|
||||||
}
|
}
|
||||||
|
|
@ -388,7 +377,6 @@ impl Instruction {
|
||||||
requires the first byte to be 0 found {v}"
|
requires the first byte to be 0 found {v}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// TODO: check the bytes order
|
|
||||||
let [a_l0, a_l1, a_h0, a_h1] = i32::deserialize(input)?.to_be_bytes();
|
let [a_l0, a_l1, a_h0, a_h1] = i32::deserialize(input)?.to_be_bytes();
|
||||||
let a = i32::from_be_bytes([a_h0, a_h1, a_l0, a_l1]);
|
let a = i32::from_be_bytes([a_h0, a_h1, a_l0, a_l1]);
|
||||||
Ok(Self::Format30T { op, a })
|
Ok(Self::Format30T { op, a })
|
||||||
|
|
@ -404,9 +392,7 @@ impl Instruction {
|
||||||
requires the first byte to be 0 found {v}"
|
requires the first byte to be 0 found {v}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// TODO: check the bytes order
|
|
||||||
let va = u16::deserialize(input)?;
|
let va = u16::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let vb = u16::deserialize(input)?;
|
let vb = u16::deserialize(input)?;
|
||||||
Ok(Self::Format32X { op, va, vb })
|
Ok(Self::Format32X { op, va, vb })
|
||||||
}
|
}
|
||||||
|
|
@ -415,7 +401,6 @@ impl Instruction {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes();
|
let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes();
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
|
let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
|
||||||
Ok(Self::Format31I { va, op, b })
|
Ok(Self::Format31I { va, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -424,7 +409,6 @@ impl Instruction {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes();
|
let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes();
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
|
let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
|
||||||
Ok(Self::Format31T { va, op, b })
|
Ok(Self::Format31T { va, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -433,7 +417,6 @@ impl Instruction {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let va = u8::deserialize(input)?;
|
let va = u8::deserialize(input)?;
|
||||||
let [b_l0, b_l1, b_h0, b_h1] = u32::deserialize(input)?.to_be_bytes();
|
let [b_l0, b_l1, b_h0, b_h1] = u32::deserialize(input)?.to_be_bytes();
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
|
let b = u32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
|
||||||
Ok(Self::Format31C { va, op, b })
|
Ok(Self::Format31C { va, op, b })
|
||||||
}
|
}
|
||||||
|
|
@ -449,7 +432,6 @@ impl Instruction {
|
||||||
requires A to be between 0 and 5, found {a}"
|
requires A to be between 0 and 5, found {a}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
|
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
|
|
@ -483,7 +465,6 @@ impl Instruction {
|
||||||
requires A to be between 0 and 5, found {a}"
|
requires A to be between 0 and 5, found {a}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
|
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
|
|
@ -517,7 +498,6 @@ impl Instruction {
|
||||||
requires A to be between 0 and 5, found {a}"
|
requires A to be between 0 and 5, found {a}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
|
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
|
|
@ -543,9 +523,7 @@ impl Instruction {
|
||||||
pub fn deserialize_3rc(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_3rc(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let a = u8::deserialize(input)?;
|
let a = u8::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let vc = u16::deserialize(input)?;
|
let vc = u16::deserialize(input)?;
|
||||||
Ok(Self::Format3RC { a, op, b, vc })
|
Ok(Self::Format3RC { a, op, b, vc })
|
||||||
}
|
}
|
||||||
|
|
@ -553,9 +531,7 @@ impl Instruction {
|
||||||
pub fn deserialize_3rms(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_3rms(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let a = u8::deserialize(input)?;
|
let a = u8::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let vc = u16::deserialize(input)?;
|
let vc = u16::deserialize(input)?;
|
||||||
Ok(Self::Format3RMS { a, op, b, vc })
|
Ok(Self::Format3RMS { a, op, b, vc })
|
||||||
}
|
}
|
||||||
|
|
@ -563,9 +539,7 @@ impl Instruction {
|
||||||
pub fn deserialize_3rmi(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_3rmi(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let a = u8::deserialize(input)?;
|
let a = u8::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let vc = u16::deserialize(input)?;
|
let vc = u16::deserialize(input)?;
|
||||||
Ok(Self::Format3RMI { a, op, b, vc })
|
Ok(Self::Format3RMI { a, op, b, vc })
|
||||||
}
|
}
|
||||||
|
|
@ -581,7 +555,6 @@ impl Instruction {
|
||||||
requires A to be between 0 and 5, found {a}"
|
requires A to be between 0 and 5, found {a}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
|
|
||||||
let val = u8::deserialize(input)?;
|
let val = u8::deserialize(input)?;
|
||||||
|
|
@ -592,7 +565,6 @@ impl Instruction {
|
||||||
let vf = (val & 0b1111_0000) >> 4;
|
let vf = (val & 0b1111_0000) >> 4;
|
||||||
let ve = val & 0b0000_1111;
|
let ve = val & 0b0000_1111;
|
||||||
|
|
||||||
// TODO: check the bytes order
|
|
||||||
let h = u16::deserialize(input)?;
|
let h = u16::deserialize(input)?;
|
||||||
|
|
||||||
Ok(Self::Format45CC {
|
Ok(Self::Format45CC {
|
||||||
|
|
@ -611,11 +583,8 @@ impl Instruction {
|
||||||
pub fn deserialize_4rcc(input: &mut dyn ReadSeek) -> Result<Self> {
|
pub fn deserialize_4rcc(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
let op = u8::deserialize(input)?;
|
let op = u8::deserialize(input)?;
|
||||||
let a = u8::deserialize(input)?;
|
let a = u8::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let b = u16::deserialize(input)?;
|
let b = u16::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let vc = u16::deserialize(input)?;
|
let vc = u16::deserialize(input)?;
|
||||||
// TODO: check the bytes order
|
|
||||||
let h = u16::deserialize(input)?;
|
let h = u16::deserialize(input)?;
|
||||||
Ok(Self::Format4RCC { a, op, b, vc, h })
|
Ok(Self::Format4RCC { a, op, b, vc, h })
|
||||||
}
|
}
|
||||||
|
|
@ -2113,6 +2082,76 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parsing_20t() {
|
||||||
|
for (raw, expected) in [
|
||||||
|
(
|
||||||
|
vec![0x29, 0x00, 0xd4, 0xfe],
|
||||||
|
Instruction::Format20T { a: -300, op: 0x29 },
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec![0x29, 0x00, 0x16, 0x01],
|
||||||
|
Instruction::Format20T { a: 278, op: 0x29 },
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
assert_eq!(expected.size(), raw.len());
|
||||||
|
assert_eq!(expected, Instruction::deserialize_from_slice(&raw).unwrap());
|
||||||
|
assert_eq!(raw, expected.serialize_to_vec().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parsing_22x() {
|
||||||
|
for (raw, expected) in [
|
||||||
|
(
|
||||||
|
vec![0x08, 0x0b, 0x11, 0x00],
|
||||||
|
Instruction::Format22X {
|
||||||
|
va: 11,
|
||||||
|
vb: 17,
|
||||||
|
op: 0x8,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec![0x08, 0x03, 0x11, 0x00],
|
||||||
|
Instruction::Format22X {
|
||||||
|
va: 3,
|
||||||
|
vb: 17,
|
||||||
|
op: 0x8,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
assert_eq!(expected.size(), raw.len());
|
||||||
|
assert_eq!(expected, Instruction::deserialize_from_slice(&raw).unwrap());
|
||||||
|
assert_eq!(raw, expected.serialize_to_vec().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parsing_21h() {
|
||||||
|
for (raw, expected) in [
|
||||||
|
(
|
||||||
|
vec![0x15, 0x0b, 0x10, 0x00],
|
||||||
|
Instruction::Format21H {
|
||||||
|
va: 11,
|
||||||
|
b: (1048576 / 65536) as i16,
|
||||||
|
op: 0x15,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec![0x15, 0x06, 0x00, 0x80],
|
||||||
|
Instruction::Format21H {
|
||||||
|
va: 6,
|
||||||
|
b: (-2147483648 / 65536) as i16,
|
||||||
|
op: 0x15,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
assert_eq!(expected.size(), raw.len());
|
||||||
|
assert_eq!(expected, Instruction::deserialize_from_slice(&raw).unwrap());
|
||||||
|
assert_eq!(raw, expected.serialize_to_vec().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parsing_21c() {
|
fn test_parsing_21c() {
|
||||||
let raw = vec![0x22, 0x00, 0x2d, 0x24];
|
let raw = vec![0x22, 0x00, 0x2d, 0x24];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue