Quellcode durchsuchen

Parse DefShiftLeft and DefShiftRight

Isaac Woods vor 4 Jahren
Ursprung
Commit
da7c5eafbe
4 geänderte Dateien mit 98 neuen und 4 gelöschten Zeilen
  1. 2 0
      aml/src/lib.rs
  2. 15 0
      aml/src/name_object.rs
  3. 2 0
      aml/src/opcode.rs
  4. 79 4
      aml/src/type2.rs

+ 2 - 0
aml/src/lib.rs

@@ -391,4 +391,6 @@ pub enum AmlError {
      * Errors produced working with AML values.
      */
     InvalidStatusObject,
+    InvalidShiftLeft,
+    InvalidShiftRight,
 }

+ 15 - 0
aml/src/name_object.rs

@@ -20,6 +20,21 @@ pub enum Target {
     Local(LocalNum),
 }
 
+pub fn target<'a, 'c>() -> impl Parser<'a, 'c, Target>
+where
+    'c: 'a,
+{
+    /*
+     * Target := SuperName | NullName
+     * NullName := 0x00
+     */
+    comment_scope(
+        DebugVerbosity::AllScopes,
+        "Target",
+        choice!(null_name().map(|_| Ok(Target::Null)), super_name()),
+    )
+}
+
 pub fn super_name<'a, 'c>() -> impl Parser<'a, 'c, Target>
 where
     'c: 'a,

+ 2 - 0
aml/src/opcode.rs

@@ -44,6 +44,8 @@ pub const DEF_RETURN_OP: u8 = 0xa4;
  */
 pub const DEF_L_EQUAL_OP: u8 = 0x93;
 pub const DEF_STORE_OP: u8 = 0x70;
+pub const DEF_SHIFT_LEFT: u8 = 0x79;
+pub const DEF_SHIFT_RIGHT: u8 = 0x7a;
 
 /*
  * Miscellaneous objects

+ 79 - 4
aml/src/type2.rs

@@ -1,13 +1,24 @@
 use crate::{
     name_object::{name_string, super_name, target},
     opcode::{self, opcode},
-    parser::{choice, comment_scope, id, take, take_to_end_of_pkglength, try_with_context, Parser},
+    parser::{
+        choice,
+        comment_scope,
+        id,
+        make_parser_concrete,
+        take,
+        take_to_end_of_pkglength,
+        try_with_context,
+        Parser,
+    },
     pkg_length::pkg_length,
     term_object::{data_ref_object, term_arg},
     value::AmlValue,
+    AmlError,
     DebugVerbosity,
 };
 use alloc::vec::Vec;
+use core::convert::TryInto;
 
 /// Type 2 opcodes return a value and so can be used in expressions.
 pub fn type2_opcode<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
@@ -24,12 +35,22 @@ where
      *                DefVarPackage | DefRefOf | DefShiftLeft | DefShitRight | DefSizeOf | DefStore |
      *                DefSubtract | DefTimer | DefToBCD | DefToBuffer | DefToDecimalString |
      *                DefToHexString | DefToInteger | DefToString | DefWait | DefXOr | MethodInvocation
+     *
+     * NOTE: MethodInvocation should always appear last in the choice.
      */
-    comment_scope(
+    make_parser_concrete!(comment_scope(
         DebugVerbosity::AllScopes,
         "Type2Opcode",
-        choice!(def_buffer(), def_l_equal(), def_package(), def_store(), method_invocation()),
-    )
+        choice!(
+            def_buffer(),
+            def_l_equal(),
+            def_package(),
+            def_shift_left(),
+            def_shift_right(),
+            def_store(),
+            method_invocation()
+        ),
+    ))
 }
 
 pub fn def_buffer<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
@@ -116,6 +137,60 @@ where
     choice!(data_ref_object(), name_string().map(|string| Ok(AmlValue::String(string.as_string()))))
 }
 
+fn def_shift_left<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
+where
+    'c: 'a,
+{
+    /*
+     * DefShiftLeft := 0x79 Operand ShiftCount Target
+     * Operand := TermArg => Integer
+     * ShiftCount := TermArg => Integer
+     */
+    opcode(opcode::DEF_SHIFT_LEFT)
+        .then(comment_scope(DebugVerbosity::Scopes, "DefShiftLeft", term_arg().then(term_arg()).then(target())))
+        .map_with_context(|((), ((operand, shift_count), target)), context| {
+            let operand = try_with_context!(context, operand.as_integer());
+            let shift_count = try_with_context!(context, shift_count.as_integer());
+            let shift_count =
+                try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftLeft));
+
+            let result = AmlValue::Integer(try_with_context!(
+                context,
+                operand.checked_shl(shift_count).ok_or(AmlError::InvalidShiftLeft)
+            ));
+
+            try_with_context!(context, context.store(target, result.clone()));
+            (Ok(result), context)
+        })
+}
+
+fn def_shift_right<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
+where
+    'c: 'a,
+{
+    /*
+     * DefShiftRight := 0x7a Operand ShiftCount Target
+     * Operand := TermArg => Integer
+     * ShiftCount := TermArg => Integer
+     */
+    opcode(opcode::DEF_SHIFT_RIGHT)
+        .then(comment_scope(DebugVerbosity::Scopes, "DefShiftRight", term_arg().then(term_arg()).then(target())))
+        .map_with_context(|((), ((operand, shift_count), target)), context| {
+            let operand = try_with_context!(context, operand.as_integer());
+            let shift_count = try_with_context!(context, shift_count.as_integer());
+            let shift_count =
+                try_with_context!(context, shift_count.try_into().map_err(|_| AmlError::InvalidShiftRight));
+
+            let result = AmlValue::Integer(try_with_context!(
+                context,
+                operand.checked_shr(shift_count).ok_or(AmlError::InvalidShiftRight)
+            ));
+
+            try_with_context!(context, context.store(target, result.clone()));
+            (Ok(result), context)
+        })
+}
+
 fn def_store<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
 where
     'c: 'a,