diff options
Diffstat (limited to 'bytecode')
| -rw-r--r-- | bytecode/src/encoding.rs | 58 | ||||
| -rw-r--r-- | bytecode/src/main.rs | 39 |
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(()) } |
