Implemented further opcodes in full, added get to context
This commit is contained in:
@@ -34,10 +34,7 @@ pub enum ObjectReference {
|
||||
pub enum AmlValue {
|
||||
None,
|
||||
Uninitialized,
|
||||
Buffer {
|
||||
length: Box<AmlValue>,
|
||||
byte_list: Vec<u8>
|
||||
},
|
||||
Buffer(Vec<u8>),
|
||||
BufferField {
|
||||
source_buf: Box<AmlValue>,
|
||||
index: Box<AmlValue>,
|
||||
@@ -81,13 +78,19 @@ pub enum AmlValue {
|
||||
}
|
||||
|
||||
impl AmlValue {
|
||||
// TODO: These should be able to throw errors rather than returning options
|
||||
pub fn get_as_string(&self) -> Result<String, AmlError> {
|
||||
match *self {
|
||||
AmlValue::String(ref s) => Ok(s.clone()),
|
||||
_ => Err(AmlError::AmlValueError)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_as_buffer(&self) -> Result<Vec<u8>, AmlError> {
|
||||
match *self {
|
||||
AmlValue::Buffer(ref b) => Ok(b.clone()),
|
||||
_ => Err(AmlError::AmlValueError)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_as_package(&self) -> Result<Vec<AmlValue>, AmlError> {
|
||||
match *self {
|
||||
|
||||
@@ -56,4 +56,16 @@ impl AmlExecutionContext {
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, name: AmlValue) -> AmlValue {
|
||||
match name {
|
||||
AmlValue::None => AmlValue::None,
|
||||
AmlValue::ObjectReference(r) => match r {
|
||||
ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(),
|
||||
ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(),
|
||||
_ => AmlValue::None
|
||||
},
|
||||
_ => AmlValue::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ macro_rules! parser_selector {
|
||||
match $func($data, $ctx) {
|
||||
Ok(res) => return Ok(res),
|
||||
Err(AmlError::AmlInvalidOpCode) => (),
|
||||
Err(e) => {
|
||||
// println!("This doesn't work for some reason");
|
||||
return Err(e);
|
||||
}
|
||||
Err(e) => return Err(e)
|
||||
}
|
||||
};
|
||||
{$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => {
|
||||
|
||||
+138
-50
@@ -110,15 +110,22 @@ pub fn parse_def_object_type(data: &[u8],
|
||||
pub fn parse_def_package(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Handle deferred loads in here
|
||||
// TODO: Truncate/extend array if necessary
|
||||
parser_opcode!(data, 0x12);
|
||||
|
||||
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;
|
||||
let num_elements = data[1 + pkg_length_len];
|
||||
let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?;
|
||||
let numelements = data[1 + pkg_length_len] as usize;
|
||||
let mut elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?.val.get_as_package()?;
|
||||
|
||||
if elements.len() > numelements {
|
||||
elements = elements[0 .. numelements].to_vec();
|
||||
} else if numelements > elements.len() {
|
||||
for i in 0..numelements - elements.len() {
|
||||
elements.push(AmlValue::Uninitialized);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: elements.val,
|
||||
val: AmlValue::Package(elements),
|
||||
len: 1 + pkg_length
|
||||
})
|
||||
}
|
||||
@@ -126,16 +133,25 @@ pub fn parse_def_package(data: &[u8],
|
||||
pub fn parse_def_var_package(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Handle deferred loads in here
|
||||
// TODO: Truncate/extend array if necessary
|
||||
parser_opcode!(data, 0x13);
|
||||
|
||||
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;
|
||||
let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?;
|
||||
let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len ..
|
||||
1 + pkg_length], ctx)?;
|
||||
let mut elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len ..
|
||||
1 + pkg_length], ctx)?.val.get_as_package()?;
|
||||
|
||||
let numelements = num_elements.val.get_as_integer()? as usize;
|
||||
|
||||
if elements.len() > numelements {
|
||||
elements = elements[0 .. numelements].to_vec();
|
||||
} else if numelements > elements.len() {
|
||||
for i in 0..numelements - elements.len() {
|
||||
elements.push(AmlValue::Uninitialized);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: elements.val,
|
||||
val: AmlValue::Package(elements),
|
||||
len: 1 + pkg_length
|
||||
})
|
||||
}
|
||||
@@ -224,14 +240,15 @@ fn parse_def_acquire(data: &[u8],
|
||||
|
||||
fn parse_def_increment(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Store the result
|
||||
// TODO: Perform computation
|
||||
parser_opcode!(data, 0x75);
|
||||
|
||||
let obj = parse_super_name(&data[1..], ctx)?;
|
||||
let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? + 1);
|
||||
|
||||
ctx.modify(obj.val, value.clone());
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::Uninitialized,
|
||||
val: value,
|
||||
len: 1 + obj.len
|
||||
})
|
||||
}
|
||||
@@ -464,16 +481,15 @@ fn parse_def_size_of(data: &[u8],
|
||||
|
||||
fn parse_def_store(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Return the DRO
|
||||
parser_opcode!(data, 0x70);
|
||||
|
||||
let operand = parse_term_arg(&data[1..], ctx)?;
|
||||
let target = parse_super_name(&data[1 + operand.len..], ctx)?;
|
||||
|
||||
ctx.modify(target.val, operand.val);
|
||||
ctx.modify(target.val.clone(), operand.val);
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::Uninitialized,
|
||||
val: target.val,
|
||||
len: 1 + operand.len + target.len
|
||||
})
|
||||
}
|
||||
@@ -664,61 +680,99 @@ fn parse_def_concat(data: &[u8],
|
||||
|
||||
fn parse_def_decrement(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Compute the result
|
||||
// TODO: Store the result
|
||||
parser_opcode!(data, 0x76);
|
||||
|
||||
let target = parse_super_name(&data[1..], ctx)?;
|
||||
let obj = parse_super_name(&data[1..], ctx)?;
|
||||
let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? - 1);
|
||||
|
||||
ctx.modify(obj.val, value.clone());
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::Uninitialized,
|
||||
len: 1 + target.len
|
||||
val: value,
|
||||
len: 1 + obj.len
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_def_divide(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Compute the result
|
||||
// TODO: Store the result, if appropriate
|
||||
parser_opcode!(data, 0x78);
|
||||
|
||||
let lhs = parse_term_arg(&data[1..], ctx)?;
|
||||
let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?;
|
||||
let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?;
|
||||
let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], ctx)?;
|
||||
|
||||
let numerator = lhs.val.get_as_integer()?;
|
||||
let denominator = rhs.val.get_as_integer()?;
|
||||
|
||||
let remainder = numerator % denominator;
|
||||
let quotient = (numerator - remainder) / denominator;
|
||||
|
||||
ctx.modify(target_remainder.val, AmlValue::Integer(remainder));
|
||||
ctx.modify(target_quotient.val, AmlValue::Integer(quotient));
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::Uninitialized,
|
||||
val: AmlValue::Integer(quotient),
|
||||
len: 1 + lhs.len + rhs.len + target_remainder.len + target_quotient.len
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_def_find_set_left_bit(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Compute the result
|
||||
// TODO: Store the result, if appropriate
|
||||
parser_opcode!(data, 0x81);
|
||||
|
||||
let operand = parse_term_arg(&data[2..], ctx)?;
|
||||
let target = parse_target(&data[2 + operand.len..], ctx)?;
|
||||
|
||||
let mut first_bit = 32;
|
||||
let mut test = operand.val.get_as_integer()?;
|
||||
|
||||
while first_bit > 0{
|
||||
if test & 0x8000000000000000 > 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
test <<= 1;
|
||||
first_bit -= 1;
|
||||
}
|
||||
|
||||
let result = AmlValue::Integer(first_bit);
|
||||
ctx.modify(target.val, result.clone());
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::Uninitialized,
|
||||
val: result,
|
||||
len: 1 + operand.len + target.len
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_def_find_set_right_bit(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Compute the result
|
||||
// TODO: Store the result, if appropriate
|
||||
parser_opcode!(data, 0x82);
|
||||
|
||||
let operand = parse_term_arg(&data[2..], ctx)?;
|
||||
let target = parse_target(&data[2 + operand.len..], ctx)?;
|
||||
|
||||
let mut first_bit = 1;
|
||||
let mut test = operand.val.get_as_integer()?;
|
||||
|
||||
while first_bit <= 32 {
|
||||
if test & 1 > 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
test >>= 1;
|
||||
first_bit += 1;
|
||||
}
|
||||
|
||||
if first_bit == 33 {
|
||||
first_bit = 0;
|
||||
}
|
||||
|
||||
let result = AmlValue::Integer(first_bit);
|
||||
ctx.modify(target.val, result.clone());
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::Uninitialized,
|
||||
val: result,
|
||||
len: 1 + operand.len + target.len
|
||||
})
|
||||
}
|
||||
@@ -784,31 +838,25 @@ fn parse_def_match(data: &[u8],
|
||||
|
||||
fn parse_def_from_bcd(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Clean up match block
|
||||
parser_opcode_extended!(data, 0x28);
|
||||
|
||||
let operand = parse_term_arg(&data[2..], ctx)?;
|
||||
let target = parse_target(&data[2 + operand.len..], ctx)?;
|
||||
|
||||
let result = AmlValue::Integer(match target.val.get_as_integer() {
|
||||
Ok(i) => {
|
||||
let mut i = i;
|
||||
let mut ires = 0;
|
||||
|
||||
while i != 0 {
|
||||
if i & 0x0F > 10 {
|
||||
return Err(AmlError::AmlValueError);
|
||||
}
|
||||
let mut i = operand.val.get_as_integer()?;
|
||||
let mut result = 0;
|
||||
|
||||
ires *= 10;
|
||||
ires += i & 0x0F;
|
||||
i >>= 4;
|
||||
}
|
||||
while i != 0 {
|
||||
if i & 0x0F > 10 {
|
||||
return Err(AmlError::AmlValueError);
|
||||
}
|
||||
|
||||
result *= 10;
|
||||
result += i & 0x0F;
|
||||
i >>= 4;
|
||||
}
|
||||
|
||||
ires
|
||||
},
|
||||
Err(e) => return Err(e)
|
||||
});
|
||||
let result = AmlValue::Integer(result);
|
||||
|
||||
ctx.modify(target.val, result.clone());
|
||||
|
||||
@@ -820,8 +868,6 @@ fn parse_def_from_bcd(data: &[u8],
|
||||
|
||||
fn parse_def_mid(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Compute the result
|
||||
// TODO: Store the result, if appropriate
|
||||
parser_opcode!(data, 0x9E);
|
||||
|
||||
let source = parse_term_arg(&data[1..], ctx)?;
|
||||
@@ -829,21 +875,63 @@ fn parse_def_mid(data: &[u8],
|
||||
let length = parse_term_arg(&data[1 + source.len + index.len..], ctx)?;
|
||||
let target = parse_target(&data[1 + source.len + index.len + length.len..], ctx)?;
|
||||
|
||||
let idx = index.val.get_as_integer()? as usize;
|
||||
let mut len = length.val.get_as_integer()? as usize;
|
||||
|
||||
let result = match source.val {
|
||||
AmlValue::String(s) => {
|
||||
if idx > s.len() {
|
||||
AmlValue::String(String::new())
|
||||
} else {
|
||||
let mut res = s.clone().split_off(idx);
|
||||
|
||||
if len < res.len() {
|
||||
res.split_off(len);
|
||||
}
|
||||
|
||||
AmlValue::String(res)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// If it isn't a string already, treat it as a buffer. Must perform that check first,
|
||||
// as Mid can operate on both strings and buffers, but a string can be cast as a buffer
|
||||
// implicitly.
|
||||
// Additionally, any type that can be converted to a buffer can also be converted to a
|
||||
// string, so no information is lost
|
||||
let b = source.val.get_as_buffer()?;
|
||||
|
||||
if idx > b.len() {
|
||||
AmlValue::Buffer(vec!())
|
||||
} else {
|
||||
if idx + len > b.len() {
|
||||
len = b.len() - idx;
|
||||
}
|
||||
|
||||
AmlValue::Buffer(b[idx .. idx + len].to_vec())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ctx.modify(target.val, result.clone());
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::Uninitialized,
|
||||
val: result,
|
||||
len: 1 + source.len + index.len + length.len + target.len
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_def_mod(data: &[u8],
|
||||
ctx: &mut AmlExecutionContext) -> ParseResult {
|
||||
// TODO: Fatal exception on rhs == 0
|
||||
parser_opcode!(data, 0x85);
|
||||
|
||||
let lhs = parse_term_arg(&data[1..], ctx)?;
|
||||
let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?;
|
||||
let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?;
|
||||
|
||||
if rhs.val.get_as_integer()? == 0 {
|
||||
return Err(AmlError::AmlValueError);
|
||||
}
|
||||
|
||||
let result = AmlValue::Integer(lhs.val.get_as_integer()? % rhs.val.get_as_integer()?);
|
||||
|
||||
ctx.modify(target.val, result.clone());
|
||||
|
||||
Reference in New Issue
Block a user