@@ -77,24 +77,19 @@ impl Interpreter {
77
77
*/
78
78
while let Some ( op) = context. in_flight . pop_if ( |op| op. arguments . len ( ) == op. expected_arguments ) {
79
79
match op. op {
80
- Opcode :: Add => {
81
- let [ Argument :: Object ( left) , Argument :: Object ( right) , Argument :: Object ( target) ] =
82
- & op. arguments [ ..]
83
- else {
84
- panic ! ( )
85
- } ;
86
- let Object :: Integer ( left) = * * left else { panic ! ( ) } ;
87
- let Object :: Integer ( right) = * * right else { panic ! ( ) } ;
88
-
89
- * target. gain_mut ( ) = Object :: Integer ( left + right) ;
90
-
91
- // TODO: this is probs a slightly scuffed way of working out if the
92
- // prev op wants our result
93
- if let Some ( prev_op) = context. in_flight . last_mut ( ) {
94
- if prev_op. arguments . len ( ) < prev_op. expected_arguments {
95
- prev_op. arguments . push ( Argument :: Object ( Arc :: new ( Object :: Integer ( left + right) ) ) ) ;
96
- }
97
- }
80
+ Opcode :: Add
81
+ | Opcode :: Subtract
82
+ | Opcode :: Multiply
83
+ | Opcode :: Divide
84
+ | Opcode :: ShiftLeft
85
+ | Opcode :: ShiftRight
86
+ | Opcode :: Mod
87
+ | Opcode :: Nand
88
+ | Opcode :: And
89
+ | Opcode :: Or
90
+ | Opcode :: Nor
91
+ | Opcode :: Xor => {
92
+ self . do_binary_maths ( & mut context, op) ?;
98
93
}
99
94
Opcode :: Increment | Opcode :: Decrement => {
100
95
let [ Argument :: Object ( operand) ] = & op. arguments [ ..] else { panic ! ( ) } ;
@@ -781,6 +776,59 @@ impl Interpreter {
781
776
}
782
777
}
783
778
}
779
+
780
+ fn do_binary_maths ( & self , context : & mut MethodContext , op : OpInFlight ) -> Result < ( ) , AmlError > {
781
+ let [ Argument :: Object ( left) , Argument :: Object ( right) , Argument :: Object ( target) ] = & op. arguments [ 0 ..2 ]
782
+ else {
783
+ Err ( AmlError :: InvalidOperationOnObject ) ?
784
+ } ;
785
+ let target2 = if op. op == Opcode :: Divide {
786
+ let Argument :: Object ( target2) = & op. arguments [ 3 ] else { panic ! ( ) } ;
787
+ Some ( target2)
788
+ } else {
789
+ None
790
+ } ;
791
+
792
+ let Object :: Integer ( left) = * left. clone ( ) . unwrap_transparent_reference ( ) else {
793
+ Err ( AmlError :: InvalidOperationOnObject ) ?
794
+ } ;
795
+ let Object :: Integer ( right) = * right. clone ( ) . unwrap_transparent_reference ( ) else {
796
+ Err ( AmlError :: InvalidOperationOnObject ) ?
797
+ } ;
798
+
799
+ let value = match op. op {
800
+ Opcode :: Add => left. wrapping_add ( right) ,
801
+ Opcode :: Subtract => left. wrapping_sub ( right) ,
802
+ Opcode :: Multiply => left. wrapping_mul ( right) ,
803
+ Opcode :: Divide => {
804
+ if let Some ( remainder) = target2 {
805
+ * remainder. gain_mut ( ) = Object :: Integer ( left. wrapping_rem ( right) ) ;
806
+ }
807
+ left. wrapping_div_euclid ( right)
808
+ }
809
+ Opcode :: ShiftLeft => left. wrapping_shl ( right as u32 ) ,
810
+ Opcode :: ShiftRight => left. wrapping_shr ( right as u32 ) ,
811
+ Opcode :: Mod => left. wrapping_rem ( right) ,
812
+ Opcode :: Nand => !( left & right) ,
813
+ Opcode :: And => left & right,
814
+ Opcode :: Or => left | right,
815
+ Opcode :: Nor => !( left | right) ,
816
+ Opcode :: Xor => left ^ right,
817
+ _ => panic ! ( ) ,
818
+ } ;
819
+
820
+ * target. gain_mut ( ) = Object :: Integer ( value) ;
821
+
822
+ // TODO: this is probs a slightly scuffed way of working out if the
823
+ // prev op wants our result
824
+ if let Some ( prev_op) = context. in_flight . last_mut ( ) {
825
+ if prev_op. arguments . len ( ) < prev_op. expected_arguments {
826
+ prev_op. arguments . push ( Argument :: Object ( Arc :: new ( Object :: Integer ( left + right) ) ) ) ;
827
+ }
828
+ }
829
+
830
+ Ok ( ( ) )
831
+ }
784
832
fn do_store (
785
833
& self ,
786
834
context : & mut MethodContext ,
0 commit comments