Skip to content

Commit 763bc74

Browse files
committed
aml: binary maths
1 parent 5d4a75d commit 763bc74

File tree

1 file changed

+66
-18
lines changed

1 file changed

+66
-18
lines changed

aml/src/lib.rs

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,19 @@ impl Interpreter {
7777
*/
7878
while let Some(op) = context.in_flight.pop_if(|op| op.arguments.len() == op.expected_arguments) {
7979
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)?;
9893
}
9994
Opcode::Increment | Opcode::Decrement => {
10095
let [Argument::Object(operand)] = &op.arguments[..] else { panic!() };
@@ -781,6 +776,59 @@ impl Interpreter {
781776
}
782777
}
783778
}
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+
}
784832
fn do_store(
785833
&self,
786834
context: &mut MethodContext,

0 commit comments

Comments
 (0)