summaryrefslogtreecommitdiffstats
path: root/bytecode
diff options
context:
space:
mode:
Diffstat (limited to 'bytecode')
-rw-r--r--bytecode/src/encoding.rs58
-rw-r--r--bytecode/src/main.rs39
2 files changed, 96 insertions, 1 deletions
diff --git a/bytecode/src/encoding.rs b/bytecode/src/encoding.rs
index eb6633d..8bec753 100644
--- a/bytecode/src/encoding.rs
+++ b/bytecode/src/encoding.rs
@@ -40,6 +40,34 @@ pub struct Exit {
}
#[derive(Debug, Clone, Copy)]
+pub struct Add {
+ pub out: u8,
+ pub val1: Arg,
+ pub val2: Arg,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Sub {
+ pub out: u8,
+ pub val1: Arg,
+ pub val2: Arg,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Mul {
+ pub out: u8,
+ pub val1: Arg,
+ pub val2: Arg,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Div {
+ pub out: u8,
+ pub val1: Arg,
+ pub val2: Arg,
+}
+
+#[derive(Debug, Clone, Copy)]
pub enum Op {
Alloc(Alloc),
Call,
@@ -47,6 +75,10 @@ pub enum Op {
Peek(Peek),
Shuf(Shuf),
Exit(Exit),
+ Add(Add),
+ Sub(Sub),
+ Mul(Mul),
+ Div(Div),
}
struct Reader<'a> {
@@ -106,7 +138,7 @@ impl Op {
let code_byte = r.parse_byte()?;
let code = code_byte >> 2;
let arg1_const = code_byte & 2 != 0;
- // let arg2_const = code_byte & 1 != 0;
+ let arg2_const = code_byte & 1 != 0;
let op = match code {
1 => {
@@ -142,6 +174,30 @@ impl Op {
let val = r.parse_arg(arg1_const)?;
Op::Exit(Exit { val })
}
+ 7 => {
+ let out = r.parse_local()?;
+ let val1 = r.parse_arg(arg1_const)?;
+ let val2 = r.parse_arg(arg2_const)?;
+ Op::Add(Add { out, val1, val2 })
+ }
+ 8 => {
+ let out = r.parse_local()?;
+ let val1 = r.parse_arg(arg1_const)?;
+ let val2 = r.parse_arg(arg2_const)?;
+ Op::Sub(Sub { out, val1, val2 })
+ }
+ 9 => {
+ let out = r.parse_local()?;
+ let val1 = r.parse_arg(arg1_const)?;
+ let val2 = r.parse_arg(arg2_const)?;
+ Op::Mul(Mul { out, val1, val2 })
+ }
+ 10 => {
+ let out = r.parse_local()?;
+ let val1 = r.parse_arg(arg1_const)?;
+ let val2 = r.parse_arg(arg2_const)?;
+ Op::Div(Div { out, val1, val2 })
+ }
_ => {
return Err(Box::from(format!("invalid code {}", code)));
}
diff --git a/bytecode/src/main.rs b/bytecode/src/main.rs
index a4970e0..bbc0ddd 100644
--- a/bytecode/src/main.rs
+++ b/bytecode/src/main.rs
@@ -57,6 +57,45 @@ impl State {
};
std::process::exit(i as i32);
}
+ Op::Add(op) => {
+ let Some(v1) = self.read_arg(op.val1).to_int() else {
+ return Err(Box::from("add needs an int"));
+ };
+ let Some(v2) = self.read_arg(op.val2).to_int() else {
+ return Err(Box::from("add needs an int"));
+ };
+ self.heap.locals[usize::from(op.out)] = Value::from_int(v1.wrapping_add(v2));
+ }
+ Op::Sub(op) => {
+ let Some(v1) = self.read_arg(op.val1).to_int() else {
+ return Err(Box::from("sub needs an int"));
+ };
+ let Some(v2) = self.read_arg(op.val2).to_int() else {
+ return Err(Box::from("sub needs an int"));
+ };
+ self.heap.locals[usize::from(op.out)] = Value::from_int(v1.wrapping_sub(v2));
+ }
+ Op::Mul(op) => {
+ let Some(v1) = self.read_arg(op.val1).to_int() else {
+ return Err(Box::from("mul needs an int"));
+ };
+ let Some(v2) = self.read_arg(op.val2).to_int() else {
+ return Err(Box::from("mul needs an int"));
+ };
+ self.heap.locals[usize::from(op.out)] = Value::from_int(v1.wrapping_mul(v2));
+ }
+ Op::Div(op) => {
+ let Some(v1) = self.read_arg(op.val1).to_int() else {
+ return Err(Box::from("div needs an int"));
+ };
+ let Some(v2) = self.read_arg(op.val2).to_int() else {
+ return Err(Box::from("div needs an int"));
+ };
+ let Some(res) = v1.checked_div(v2) else {
+ return Err(Box::from("division by zero"));
+ };
+ self.heap.locals[usize::from(op.out)] = Value::from_int(res);
+ }
}
Ok(())
}