// Copyright (c) 2025 taitep // SPDX-License-Identifier: MIT // // This file is part of TRVE (https://gitea.taitep.se/taitep/trve) // See LICENSE file in the project root for full license text. use crate::{ consts::{Addr, RegId, RegValue}, decode::Instruction, exceptions::ExceptionType, instructions::find_and_exec, mem::MemConfig, }; pub struct Core { pub(crate) x_regs: [RegValue; 32], pub(crate) pc: Addr, pub(crate) mem: MemConfig, } impl Core { pub fn new(mem: MemConfig) -> Self { Self { x_regs: [0; 32], pc: 0, mem, } } pub fn run(&mut self) { loop { let page = (self.pc / 4096) as usize; let offset = (self.pc % 4096 / 4) as u16; if !self.pc.is_multiple_of(4) { self.throw_exception(ExceptionType::InstructionAccessMisaligned); break; } let instr = match self.mem.read_word(page, offset) { Ok(i) => i, Err(_) => { self.throw_exception(ExceptionType::InstructionAccessFault); break; } }; if instr == 0 { self.throw_exception(ExceptionType::IllegalInstruction); break; } if instr & 3 != 3 { // Compressed instruction - (currently) unsupported self.throw_exception(ExceptionType::IllegalInstruction); break; } let instr = Instruction(instr); if let Err(e) = find_and_exec(instr, self) { self.throw_exception(e); eprintln!("instr: {:08x}", instr.0); break; } } } fn throw_exception(&mut self, exception_type: ExceptionType) { eprintln!("Exception: {exception_type:?}"); dbg!(self.pc, self.x_regs); } pub fn reset(&mut self, pc: Addr) { self.pc = pc; } pub(crate) fn reg_read(&self, id: RegId) -> RegValue { self.x_regs[id as usize] } pub(crate) fn reg_write(&mut self, id: RegId, value: RegValue) { if id == 0 { return; } self.x_regs[id as usize] = value; } pub(crate) fn advance_pc(&mut self) { self.pc = self.pc.wrapping_add(4); } }