feat: add addressing mode constraints

this can be used as a helper function, but comments placed suggest to copy paste and then eliminate cases which aren't used in each opcode
This commit is contained in:
Goblin Oats
2023-08-28 17:39:13 +01:00
parent e23961b004
commit 6212a12117
2 changed files with 244 additions and 55 deletions

View File

@@ -28,140 +28,322 @@
//Y = 8202
//A = 8200
fn wrapping_add_u16(a: Field, b: Field) -> Field {
let max = 65535;
if ((value as u16) + (b as u16)) > 65535 {
(value + b) - 65535
} else {
value + b
}
}
// Please see cpu/instr.rs in tetanes/ for reference
// Note:
// This function may be used as a helper, but it's probably not very efficient, because many opcodes use only a subset of addressing modes
// perhaps it's better to copy paste this function into each opcode and then just eliminate the addressing modes which aren't used
fn run(
mode: Field,
op_sorted_step: [Field; 7],
op_sorted_addr: [Field; 7],
op_sorted_val: [Field; 7],
op_sorted_op_rw: [Field; 7],
// Returns (Address, Value — for ABY,ABX, and IDY)
) -> [Field; 2] {
op_sorted_addr: [Field; 8],
op_sorted_val: [Field; 8],
op_sorted_op_rw: [Field; 8],
// Returns (Address, Value, Offset — for ABY,ABX, and IDY)
) -> [Field; 3] {
if mode == 0 {
[0,0]
} else if mode == 1 { // ACC
// also kind of a do nothing mode
// PC is read,
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
// value at PC is read and thrown away
[0,0]
[0,0,1]
} else if mode == 2 { // IMP
//kind of a do nothing mode
// PC is read,
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
// value at PC is read and thrown away
[0,0]
[0,0,1]
} else if mode == 3 { // IMM
// read pc and set as address
// pc is set to PC + 1
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let address = op_sorted_val[0];
// pc is set to PC + 1
assert(op_sorted_addr[1] == 8203);
assert(op_sorted_op_rw[1] == 1);
assert(op_sorted_val[1] == wrapping_add_u16(address, 1));
// the value is read later
[address, 0, 2]
} else if mode == 4 { // ZP0
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let address = op_sorted_val[0];
// read value from PC
assert(op_sorted_addr[1] == address);
assert(op_sorted_op_rw[1] == 0);
let value = op_sorted_val[1];
// set PC to PC + 1
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
assert(op_sorted_val[2] == wrapping_add_u16(address, 1));
// value is returned as Addr
[value, 0, 3]
} else if mode == 5 { // ZPX
} else if (mode == 5) | (mode == 6) { // ZPX && ZPY
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let address = op_sorted_val[0];
// read value from PC
assert(op_sorted_addr[1] == address);
assert(op_sorted_op_rw[1] == 0);
let value = op_sorted_val[1];
// set PC to PC + 1
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
assert(op_sorted_val[2] == wrapping_add_u16(address, 1));
// read addr at value (is thrown away)
// read from x
// add x to value
//result is returned as Addr
} else if mode == 6 { // ZPY
// read PC
// read value from PC
// set PC to PC + 1
// read addr at value (is thrown away)
// read from y
// add y to value
assert(op_sorted_addr[3] == value);
assert(op_sorted_op_rw[3] == 0);
// read from x or y
if mode == 5 {
//ZPX
assert(op_sorted_addr[4] == 8201);
} else {
//ZPY
assert(op_sorted_addr[4] == 8202);
}
assert(op_sorted_op_rw[4] == 0);
let indexValue = op_sorted_val[4];
// add x or y to value
//result is returned as Addr
[wrapping_add_u16(value + indexValue), 0, 5]
} else if mode == 7 { // REL
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let address = op_sorted_val[0];
// read value from PC
assert(op_sorted_addr[1] == address);
assert(op_sorted_op_rw[1] == 0);
let value = op_sorted_val[1];
// set PC to PC + 1
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
assert(op_sorted_val[2] == wrapping_add_u16(address, 1));
// value is returned as Addr
[value, 0, 3]
} else if mode == 8 { // ABS
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let address = op_sorted_val[0];
// read value into lo
assert(op_sorted_addr[1] == address);
assert(op_sorted_op_rw[1] == 0);
let lo = op_sorted_val[1];
// set PC to PC + 1
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
assert(op_sorted_val[2] == wrapping_add_u16(address, 1));
// read PC
assert(op_sorted_addr[3] == 8203);
assert(op_sorted_op_rw[3] == 0);
address = op_sorted_val[3];
// read value into hi
assert(op_sorted_addr[4] == address);
assert(op_sorted_op_rw[4] == 0);
let hi = op_sorted_val[4];
// set PC to PC + 1
assert(op_sorted_addr[5] == 8203);
assert(op_sorted_op_rw[5] == 1);
assert(op_sorted_val[5] == wrapping_add_u16(address, 1));
// return hi << 8 | lo
let abs = (hi as u8) << 8 | (lo as u8);
[abs, 0, 6]
} else if (mode == 9) | (mode == 10) { // ABX && ABY
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let address = op_sorted_val[0];
// read value into lo
assert(op_sorted_addr[1] == address);
assert(op_sorted_op_rw[1] == 0);
let lo = op_sorted_val[1];
// set PC to PC + 1
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
assert(op_sorted_val[2] == wrapping_add_u16(address, 1));
// read PC
assert(op_sorted_addr[3] == 8203);
assert(op_sorted_op_rw[3] == 0);
address = op_sorted_val[3];
// read value into hi
assert(op_sorted_addr[4] == address);
assert(op_sorted_op_rw[4] == 0);
let hi = op_sorted_val[4];
// set PC to PC + 1
assert(op_sorted_addr[5] == 8203);
assert(op_sorted_op_rw[5] == 1);
assert(op_sorted_val[5] == wrapping_add_u16(address, 1));
} else if mode == 9 { // ABX
// read PC
// read value into lo
// set PC to PC + 1
// read PC
// read value into hi
// set PC to PC + 1
// calculate addr as hi << 8 | lo
// calculate joint value
let joint = (hi as u8) << 8 | (lo as u8);
// read value of x
// add value of x to addr
// value of Addr is addr + x
if (mode == 9) {
// ABX
assert(op_sorted_addr[6] == 8201);
} else {
// ABY
assert(op_sorted_addr[6] == 8202);
}
assert(op_sorted_op_rw[6] == 0);
let index = op_sorted_val[6];
// add value of x or y to addr
let abs_addr = wrapping_add_u16(joint, index);
// value of Addr is addr + x or y
let data_addr = ((joint as u16) & 65280) | ((abs_addr as u16) & 255);
// read addr & 0xFF00 | Addr & 0x00FF and return as Value
assert(op_sorted_addr[7] == data_addr);
assert(op_sorted_op_rw[7] == 0);
// return Addr, Value
} else if mode == 10 { // ABY
// read PC
// read value into lo
// set PC to PC + 1
// read PC
// read value into hi
// set PC to PC + 1
// calculate addr as hi << 8 | lo
// read value of y
// add value of y to addr
// value of Addr is addr + y
// read addr & 0xFF00 | Addr & 0x00FF and return as Value
// return Addr, Value
[abs_addr, op_sorted_val[7], 8]
} else if mode == 11 { // IND (JMP)
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let address = op_sorted_val[0];
// read value into lo
assert(op_sorted_addr[1] == address);
assert(op_sorted_op_rw[1] == 0);
let lo = op_sorted_val[1];
// set PC to PC + 1
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
assert(op_sorted_val[2] == wrapping_add_u16(address, 1));
// read PC
assert(op_sorted_addr[3] == 8203);
assert(op_sorted_op_rw[3] == 0);
address = op_sorted_val[3];
// read value into hi
assert(op_sorted_addr[4] == address);
assert(op_sorted_op_rw[4] == 0);
let hi = op_sorted_val[4];
// set PC to PC + 1
assert(op_sorted_addr[5] == 8203);
assert(op_sorted_op_rw[5] == 1);
assert(op_sorted_val[5] == wrapping_add_u16(address, 1));
// addr is hi << 8 | lo
let joint_addr = (hi as u8) << 8 | (lo as u8);
// if addr & 0xFF == 0xFF
// read value from addr lo byte
// read value from addr hi byte
// return value from hi << 8 | value from lo as Addr
// else
// read value from addr and set to lo
// read value from addr + 1 and set to hi
// return hi << 8 | lo from Addr
if ((joint_addr as u16) & 255) == 255 {
// read value from addr lo byte
// read value from addr hi byte
// return value from hi << 8 | value from lo as Addr
assert(op_sorted_addr[6] == joint_addr);
assert(op_sorted_op_rw[6] == 0);
lo = op_sorted_val[6];
assert(op_sorted_addr[7] == ((joint_addr as u16) & 65280));
assert(op_sorted_op_rw[7] == 0);
hi = op_sorted_val[7];
[(hi as u8) << 8 | (lo as u8), 0, 8]
} else {
// read value from addr and set to lo
// read value from addr + 1 and set to hi
// return hi << 8 | lo from Addr
assert(op_sorted_addr[6] == joint_addr);
assert(op_sorted_op_rw[6] == 0);
lo = op_sorted_val[6];
assert(op_sorted_addr[7] == wrapping_add_u16(joint_addr, 1));
assert(op_sorted_op_rw[7] == 0);
hi = op_sorted_val[7];
[(hi as u8) << 8 | (lo as u8), 0, 8]
}
} else if mode == 12 { // IDX
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let pc_address = op_sorted_val[0];
// read value from PC
assert(op_sorted_addr[1] == pc_address);
assert(op_sorted_op_rw[1] == 0);
let addr = op_sorted_val[1];
// set PC to PC + 1
// read from addr and throw away value
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
assert(op_sorted_val[2] == wrapping_add_u16(address, 1));
// read addr at value (is thrown away)
assert(op_sorted_addr[3] == value);
assert(op_sorted_op_rw[3] == 0);
// read x value
assert(op_sorted_addr[4] == 8201);
assert(op_sorted_op_rw[4] == 0);
let xvalue = op_sorted_val[4];
// add x value to addr
addr = wrapping_add_u16(addr, xvalue);
// read addr and set to lo
assert(op_sorted_addr[5] == addr);
assert(op_sorted_op_rw[5] == 0);
let lo = op_sorted_val[5];
// add 1 to addr and set to hi
assert(op_sorted_addr[5] == wrapping_add_u16(addr, 1));
assert(op_sorted_op_rw[5] == 0);
let hi = op_sorted_val[6];
// return Addr as hi << 8 | lo
[(hi as u16) << 8 | (lo as u16), 0, 7]
} else if mode == 13 { // IDY
// read PC
assert(op_sorted_addr[0] == 8203);
assert(op_sorted_op_rw[0] == 0);
let pc_address = op_sorted_val[0];
// read value from PC
assert(op_sorted_addr[1] == pc_address);
assert(op_sorted_op_rw[1] == 0);
let addr = op_sorted_val[1];
// set PC to PC + 1
assert(op_sorted_addr[2] == 8203);
assert(op_sorted_op_rw[2] == 1);
// read addr at value and set to lo
assert(op_sorted_addr[3] == addr);
assert(op_sorted_op_rw[3] == 0);
let lo = op_sorted_val[3];
// add 1 to value and read addr and set to hi
assert(op_sorted_addr[4] == wrapping_add_u16(addr, 1));
assert(op_sorted_op_rw[4] == 0);
let hi = op_sorted_val[4];
addr = (hi as u16) << 8 | lo;
// Read y value
assert(op_sorted_addr[5] == 8202);
assert(op_sorted_op_rw[5] == 0);
let yvalue = op_sorted_val[5];
// set Addr to (addr << 8 | lo) + y
let abs_addr = wrapping_add_u16(addr + yvalue);
// read addr & 0xFF00 | Addr & 0x00FF and return as Value
let data_addr = ((joint as u16) & 65280) | ((abs_addr as u16) & 255);
assert(op_sorted_addr[6] == data_addr);
assert(op_sorted_op_rw[6] == 0);
let data_value = op_sorted_val[6];
// return Addr, Value
[abs_addr, data_value, 7]
} else {
//something horrible has happened

7
engine/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "engine"
version = "0.1.0"