99 * - Load and LoadTable
1010 * - DefDataRegion
1111 * - Notify
12- * - DefMatch
1312 *
1413 * - Method recursion depth?
1514 * - Loop timeouts
1615 * - Fuzzing and guarantee panic-free interpretation
1716 */
1817
1918mod interrupt_model_used;
19+ mod match_expr;
20+
2021pub mod namespace;
2122pub mod object;
2223pub mod op_region;
@@ -51,6 +52,7 @@ use core::{
5152} ;
5253pub use interrupt_model_used:: InterruptModelUsed ;
5354use log:: { error, info, trace, warn} ;
55+ use match_expr:: { MatchOp , do_match} ;
5456use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
5557use object:: {
5658 DeviceStatus ,
@@ -1076,6 +1078,35 @@ where
10761078 context. retire_op ( op) ;
10771079 }
10781080 }
1081+ Opcode :: Match => {
1082+ extract_args ! ( op => [
1083+ Argument :: Object ( search_pkg) ,
1084+ Argument :: MatchOp ( opcode_a) ,
1085+ Argument :: Object ( operand_a) ,
1086+ Argument :: MatchOp ( opcode_b) ,
1087+ Argument :: Object ( operand_b) ,
1088+ Argument :: Object ( start_index) ]
1089+ ) ;
1090+
1091+ let Object :: Package ( ref pkg) = * * search_pkg else {
1092+ return Err ( AmlError :: ObjectNotOfExpectedType {
1093+ expected : ObjectType :: Package ,
1094+ got : search_pkg. typ ( ) ,
1095+ } ) ;
1096+ } ;
1097+
1098+ let result = do_match (
1099+ pkg,
1100+ opcode_a,
1101+ operand_a. as_integer ( ) ?,
1102+ opcode_b,
1103+ operand_b. as_integer ( ) ?,
1104+ start_index. as_integer ( ) ?,
1105+ ) ;
1106+
1107+ context. contribute_arg ( Argument :: Object ( Object :: Integer ( result) . wrap ( ) ) ) ;
1108+ context. retire_op ( op) ;
1109+ }
10791110 _ => panic ! ( "Unexpected operation has created in-flight op!" ) ,
10801111 }
10811112 }
@@ -1212,6 +1243,13 @@ where
12121243 Opcode :: One => {
12131244 context. contribute_arg ( Argument :: Object ( Object :: Integer ( 1 ) . wrap ( ) ) ) ;
12141245 }
1246+ Opcode :: MatchOp ( opcode) => {
1247+ if context. expecting_match_opcode ( ) {
1248+ context. contribute_arg ( Argument :: MatchOp ( opcode) ) ;
1249+ } else {
1250+ Err ( AmlError :: IllegalOpcode ( opcode as u16 ) ) ?
1251+ }
1252+ }
12151253 Opcode :: Ones => {
12161254 context. contribute_arg ( Argument :: Object ( Object :: Integer ( u64:: MAX ) . wrap ( ) ) ) ;
12171255 }
@@ -1676,6 +1714,7 @@ where
16761714 ResolveBehaviour :: Placeholder => {
16771715 panic ! ( "Invalid resolve behaviour for name to be resolved!" )
16781716 }
1717+ ResolveBehaviour :: MatchOpcode => Err ( AmlError :: InvalidArgType ) ?,
16791718 }
16801719 }
16811720
@@ -1726,14 +1765,17 @@ where
17261765 opcode,
17271766 & [ ResolveBehaviour :: TermArg , ResolveBehaviour :: TermArg , ResolveBehaviour :: Target ] ,
17281767 ) ) ,
1729- /*
1730- * TODO
1731- * Match is a difficult opcode to parse, as it interleaves dynamic arguments and
1732- * random bytes that need to be extracted as you go. I think we'll need to use 1+
1733- * internal in-flight ops to parse the static bytedatas as we go, and then retire
1734- * the real op at the end.
1735- */
1736- Opcode :: Match => todo ! ( ) ,
1768+ Opcode :: Match => context. start ( OpInFlight :: new (
1769+ opcode,
1770+ & [
1771+ ResolveBehaviour :: TermArg ,
1772+ ResolveBehaviour :: MatchOpcode ,
1773+ ResolveBehaviour :: TermArg ,
1774+ ResolveBehaviour :: MatchOpcode ,
1775+ ResolveBehaviour :: TermArg ,
1776+ ResolveBehaviour :: TermArg ,
1777+ ] ,
1778+ ) ) ,
17371779
17381780 Opcode :: CreateBitField
17391781 | Opcode :: CreateByteField
@@ -2955,6 +2997,8 @@ enum ResolveBehaviour {
29552997 /// Used with [`OpInFlight::new_with`] to represent arguments that have already been resolved
29562998 /// when an operation enters flight.
29572999 Placeholder ,
3000+ /// The match statement takes two single byte arguments - the "match opcode".
3001+ MatchOpcode ,
29583002}
29593003
29603004#[ derive( Debug ) ]
@@ -2973,6 +3017,7 @@ enum Argument {
29733017 DWordData ( u32 ) ,
29743018 TrackedPc ( usize ) ,
29753019 PkgLength ( usize ) ,
3020+ MatchOp ( MatchOp ) ,
29763021}
29773022
29783023impl OpInFlight {
@@ -3114,9 +3159,28 @@ impl MethodContext {
31143159 other => other as u16 ,
31153160 } ;
31163161
3162+ // Opcodes Zero and One overlap with the Match Opcodes that are only used in the match
3163+ // expression. It's reasonable to assume that if Zero or One appear at the time we expect a
3164+ // Match Opcode, then they *are* Match Opcodes instead of regular arguments.
31173165 Ok ( match opcode {
3118- 0x00 => Opcode :: Zero ,
3119- 0x01 => Opcode :: One ,
3166+ 0x00 => {
3167+ if self . expecting_match_opcode ( ) {
3168+ Opcode :: MatchOp ( MatchOp :: MTR )
3169+ } else {
3170+ Opcode :: Zero
3171+ }
3172+ }
3173+ 0x01 => {
3174+ if self . expecting_match_opcode ( ) {
3175+ Opcode :: MatchOp ( MatchOp :: MEQ )
3176+ } else {
3177+ Opcode :: One
3178+ }
3179+ }
3180+ 0x02 => Opcode :: MatchOp ( MatchOp :: MLE ) ,
3181+ 0x03 => Opcode :: MatchOp ( MatchOp :: MLT ) ,
3182+ 0x04 => Opcode :: MatchOp ( MatchOp :: MGE ) ,
3183+ 0x05 => Opcode :: MatchOp ( MatchOp :: MGT ) ,
31203184 0x06 => Opcode :: Alias ,
31213185 0x08 => Opcode :: Name ,
31223186 0x0a => Opcode :: BytePrefix ,
@@ -3362,12 +3426,18 @@ impl MethodContext {
33623426
33633427 Ok ( self . current_block . stream ( ) [ self . current_block . pc ] )
33643428 }
3429+
3430+ fn expecting_match_opcode ( & self ) -> bool {
3431+ let resolve_behaviour = self . in_flight . last ( ) . map ( |op| op. resolve_behaviour ( ) ) ;
3432+ resolve_behaviour. is_some_and ( |rb| matches ! ( rb, ResolveBehaviour :: MatchOpcode ) )
3433+ }
33653434}
33663435
33673436#[ derive( Clone , Copy , PartialEq , Debug ) ]
33683437enum Opcode {
33693438 Zero ,
33703439 One ,
3440+ MatchOp ( MatchOp ) ,
33713441 Alias ,
33723442 Name ,
33733443 BytePrefix ,
@@ -3590,6 +3660,12 @@ pub enum AmlError {
35903660
35913661 /// The maximum length of time a loop ([`LOOP_TIMEOUT_NS`]) can execute for has been exceeded.
35923662 LoopTimeout ,
3663+
3664+ /// The provided argument to the current operation is invalid.
3665+ ///
3666+ /// For example, trying to pass an object as the Operation parameter in a Match expression is
3667+ /// invalid.
3668+ InvalidArgType ,
35933669}
35943670
35953671#[ derive( Debug , Clone , Copy , PartialEq ) ]
0 commit comments