Skip to content

Commit

Permalink
Add a macro for binary ops and use it for ADD2, SUB2, MUL2 and DIV2 (#14
Browse files Browse the repository at this point in the history
)
  • Loading branch information
belen-albeza authored Jul 19, 2024
1 parent f0cae77 commit f5c99a5
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 25 deletions.
82 changes: 58 additions & 24 deletions coco-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ use core::cmp;
use core::fmt;

mod stack;
use opcodes::short_mode;
use stack::Stack;

pub mod opcodes;
use opcodes::FLAG_SHORT;

/// The trait to implement for COCO virtual machines.
pub trait Machine {
Expand All @@ -20,6 +22,22 @@ pub trait Ports {
const BASE: u8;
}

macro_rules! binary_op {
($self:ident, $flags:ident, $f:expr) => {
if short_mode($flags) {
let b = $self.stack.pop_short();
let a = $self.stack.pop_short();
let f: fn(u16, u16) -> u16 = $f;
$self.stack.push_short(f(a, b))
} else {
let b = $self.stack.pop_byte();
let a = $self.stack.pop_byte();
let f: fn(u8, u8) -> u8 = $f;
$self.stack.push_byte(f(a, b))
}
};
}

/// COCO-8 CPU.
#[derive(Debug)]
pub struct Cpu {
Expand Down Expand Up @@ -65,10 +83,14 @@ impl Cpu {
opcodes::DEI => self.op_dei(machine),
opcodes::DEO => self.op_deo(machine),
opcodes::DEO2 => self.op_deo2(machine),
opcodes::ADD => self.op_add(),
opcodes::SUB => self.op_sub(),
opcodes::MUL => self.op_mul(),
opcodes::DIV => self.op_div(),
opcodes::ADD => self.op_add::<0x00>(),
opcodes::ADD2 => self.op_add::<FLAG_SHORT>(),
opcodes::SUB => self.op_sub::<0x00>(),
opcodes::SUB2 => self.op_sub::<FLAG_SHORT>(),
opcodes::MUL => self.op_mul::<0x00>(),
opcodes::MUL2 => self.op_mul::<FLAG_SHORT>(),
opcodes::DIV => self.op_div::<0x00>(),
opcodes::DIV2 => self.op_div::<FLAG_SHORT>(),
opcodes::PUSH => self.op_push(),
opcodes::PUSH2 => self.op_push2(),
_ => {}
Expand Down Expand Up @@ -179,35 +201,23 @@ impl Cpu {
}

#[inline]
fn op_add(&mut self) {
let b = self.stack.pop_byte();
let a = self.stack.pop_byte();
let value = a.wrapping_add(b);
self.stack.push_byte(value);
fn op_add<const FLAGS: u8>(&mut self) {
binary_op!(self, FLAGS, |a, b| a.wrapping_add(b))
}

#[inline]
fn op_sub(&mut self) {
let b = self.stack.pop_byte();
let a = self.stack.pop_byte();
let value = a.wrapping_sub(b);
self.stack.push_byte(value);
fn op_sub<const FLAGS: u8>(&mut self) {
binary_op!(self, FLAGS, |a, b| a.wrapping_sub(b))
}

#[inline]
fn op_mul(&mut self) {
let b = self.stack.pop_byte();
let a = self.stack.pop_byte();
let value = a.wrapping_mul(b);
self.stack.push_byte(value);
fn op_mul<const FLAGS: u8>(&mut self) {
binary_op!(self, FLAGS, |a, b| a.wrapping_mul(b))
}

#[inline]
fn op_div(&mut self) {
let b = self.stack.pop_byte();
let a = self.stack.pop_byte();
let value = a.wrapping_div(b);
self.stack.push_byte(value);
fn op_div<const FLAGS: u8>(&mut self) {
binary_op!(self, FLAGS, |a, b| a.wrapping_div(b))
}
}

Expand Down Expand Up @@ -384,6 +394,18 @@ mod tests {
assert_eq!(cpu.stack.byte_at(0), 0xad);
}

#[test]
fn add2_opcode() {
let rom = rom_from(&[PUSH2, 0xab, 0xcd, PUSH2, 0x11, 0x11, ADD2, BRK]);
let mut cpu = Cpu::new(&rom);

let pc = cpu.run(0x100, &mut AnyMachine {});

assert_eq!(pc, 0x108);
assert_eq!(cpu.stack.len(), 2);
assert_eq!(cpu.stack.short_at(0), 0xbcde);
}

#[test]
fn sub_opcode() {
let rom = rom_from(&[PUSH, 0xab, PUSH, 0x02, SUB, BRK]);
Expand All @@ -396,6 +418,18 @@ mod tests {
assert_eq!(cpu.stack.byte_at(0), 0xa9);
}

#[test]
fn sub2_opcode() {
let rom = rom_from(&[PUSH2, 0xab, 0xcd, PUSH2, 0x11, 0x11, SUB2, BRK]);
let mut cpu = Cpu::new(&rom);

let pc = cpu.run(0x100, &mut AnyMachine {});

assert_eq!(pc, 0x108);
assert_eq!(cpu.stack.len(), 2);
assert_eq!(cpu.stack.short_at(0), 0x9abc);
}

#[test]
fn mul_opcode() {
let rom = rom_from(&[PUSH, 0x03, PUSH, 0x02, MUL, BRK]);
Expand Down
22 changes: 21 additions & 1 deletion coco-core/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,30 @@ pub const DUP: u8 = 0x06;
pub const DUP2: u8 = 0x26;
pub const DEI: u8 = 0x16;
pub const DEO: u8 = 0x17;
pub const DEO2: u8 = 0x37;
pub const ADD: u8 = 0x18;
pub const ADD2: u8 = 0x38;
pub const SUB: u8 = 0x19;
pub const SUB2: u8 = 0x39;
pub const MUL: u8 = 0x1a;
pub const MUL2: u8 = 0x3a;
pub const DIV: u8 = 0x1b;
pub const DEO2: u8 = 0x37;
pub const DIV2: u8 = 0x3b;
pub const PUSH: u8 = 0x80;
pub const PUSH2: u8 = 0xa0;

pub const FLAG_SHORT: u8 = 0b0010_0000;
pub const FLAG_RET: u8 = 0b0100_0000;
pub const FLAG_KEEP: u8 = 0b1000_0000;

pub fn short_mode(opcode: u8) -> bool {
(opcode & FLAG_SHORT) == FLAG_SHORT
}

pub fn ret_mode(opcode: u8) -> bool {
(opcode & FLAG_RET) == FLAG_RET
}

pub fn keep_mode(opcode: u8) -> bool {
(opcode & FLAG_KEEP) == FLAG_KEEP
}
Binary file modified coco-ui/vendor/coco_ui_bg.wasm
Binary file not shown.

0 comments on commit f5c99a5

Please sign in to comment.