opcode: ST, STI, STR
- reorganized stuff - explicit wrap (no overflows)
This commit is contained in:
parent
519fe5a536
commit
f98719879a
@ -4,6 +4,10 @@
|
||||
|
||||
use crate::vm::VM;
|
||||
|
||||
////////////////
|
||||
// Main part
|
||||
////////////////
|
||||
|
||||
#[derive(Debug)]
|
||||
enum OpCode {
|
||||
// branch
|
||||
@ -72,15 +76,15 @@ pub fn execute_instruction(vm: &mut VM, instr: u16) {
|
||||
OpCode::BR => todo!("BR"),
|
||||
OpCode::ADD => todo!("ADD"),
|
||||
OpCode::LD => op_ld(vm, instr),
|
||||
OpCode::ST => todo!("ST"),
|
||||
OpCode::ST => op_st(vm, instr),
|
||||
OpCode::JSR => op_jsr(vm, instr),
|
||||
OpCode::AND => todo!("AND"),
|
||||
OpCode::LDR => op_ldr(vm, instr),
|
||||
OpCode::STR => todo!("STR"),
|
||||
OpCode::STR => op_str(vm, instr),
|
||||
OpCode::RTI => todo!("RTI"),
|
||||
OpCode::NOT => todo!("NOT"),
|
||||
OpCode::LDI => op_ldi(vm, instr),
|
||||
OpCode::STI => todo!("STI"),
|
||||
OpCode::STI => op_sti(vm, instr),
|
||||
OpCode::JMP => todo!("JMP"),
|
||||
OpCode::RES => todo!("RES"),
|
||||
OpCode::LEA => op_lea(vm, instr),
|
||||
@ -100,24 +104,30 @@ fn sign_extend(x: u16, bits: usize) -> u16 {
|
||||
|
||||
fn no_op(vm: &mut VM, instr: u16) {}
|
||||
|
||||
////////////////
|
||||
// Load ops
|
||||
////////////////
|
||||
|
||||
fn op_lea(vm: &mut VM, instr: u16) {
|
||||
let dr = (instr >> 9) & 0b111;
|
||||
let offset = sign_extend(instr & 0x1ff, 9);
|
||||
|
||||
vm.registers.set_reg_with_cond(dr, vm.registers.pc + offset);
|
||||
vm.registers
|
||||
.set_reg_with_cond(dr, vm.registers.pc.wrapping_add(offset));
|
||||
}
|
||||
|
||||
fn op_ld(vm: &mut VM, instr: u16) {
|
||||
let dr = (instr >> 9) & 0b111;
|
||||
let offset = sign_extend(instr & 0x1ff, 9);
|
||||
|
||||
vm.registers.set_reg_with_cond(dr, vm.mem.get_mem(vm.registers.pc + offset));
|
||||
vm.registers
|
||||
.set_reg_with_cond(dr, vm.mem.get_mem(vm.registers.pc.wrapping_add(offset)));
|
||||
}
|
||||
|
||||
fn op_ldi(vm: &mut VM, instr: u16) {
|
||||
let dr = (instr >> 9) & 0b111;
|
||||
let offset = sign_extend(instr & 0x1ff, 9);
|
||||
let indirect = vm.mem.get_mem(vm.registers.pc + offset);
|
||||
let indirect = vm.mem.get_mem(vm.registers.pc.wrapping_add(offset));
|
||||
|
||||
vm.registers.set_reg_with_cond(dr, vm.mem.get_mem(indirect));
|
||||
}
|
||||
@ -127,7 +137,7 @@ fn op_ldr(vm: &mut VM, instr: u16) {
|
||||
let base_r = (instr >> 6) & 0b111;
|
||||
let offset = sign_extend(instr & 0x3f, 6);
|
||||
|
||||
let addr = vm.registers.get_reg(base_r) + offset;
|
||||
let addr = vm.registers.get_reg(base_r).wrapping_add(offset);
|
||||
vm.registers.set_reg_with_cond(dr, vm.mem.get_mem(addr));
|
||||
}
|
||||
|
||||
@ -140,10 +150,51 @@ fn op_jsr(vm: &mut VM, instr: u16) {
|
||||
vm.registers.pc = vm.registers.get_reg(base_r);
|
||||
} else {
|
||||
let offset = sign_extend(instr & 0x7ff, 11);
|
||||
vm.registers.pc += offset;
|
||||
vm.registers.pc = vm.registers.pc.wrapping_add(offset);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Store ops
|
||||
////////////////
|
||||
|
||||
fn op_st(vm: &mut VM, instr: u16) {
|
||||
let sr = (instr >> 9) & 0b111;
|
||||
let offset = sign_extend(instr & 0x1ff, 9);
|
||||
vm.mem.set_mem(
|
||||
vm.registers.pc.wrapping_add(offset),
|
||||
vm.registers.get_reg(sr),
|
||||
);
|
||||
}
|
||||
|
||||
fn op_sti(vm: &mut VM, instr: u16) {
|
||||
let sr = (instr >> 9) & 0b111;
|
||||
let offset = sign_extend(instr & 0x1ff, 9);
|
||||
|
||||
let addr = vm.mem.get_mem(vm.registers.pc.wrapping_add(offset));
|
||||
vm.mem.set_mem(addr, vm.registers.get_reg(sr));
|
||||
}
|
||||
|
||||
fn op_str(vm: &mut VM, instr: u16) {
|
||||
let sr = (instr >> 9) & 0b111;
|
||||
let base_r = (instr >> 6) & 0b111;
|
||||
let offset = sign_extend(instr & 0x3f, 6);
|
||||
|
||||
// NOTE:
|
||||
// this is how rodrigo did it:
|
||||
//
|
||||
// let addr = (vm.registers.get_reg(base_r) as u32 + offset as u32) as u16;
|
||||
//
|
||||
// apparently narrowing casts automatically wrap integers
|
||||
// this is more explicit
|
||||
let addr = vm.registers.get_reg(base_r).wrapping_add(offset);
|
||||
vm.mem.set_mem(addr, vm.registers.get_reg(sr));
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Trap/trap routines
|
||||
////////////////
|
||||
|
||||
fn op_trap(vm: &mut VM, instr: u16) {
|
||||
// conform to spec
|
||||
// (we don't actually need it in this implementation)
|
||||
|
Loading…
Reference in New Issue
Block a user