// 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, DWord}, core::{Core, InstructionResult}, decode::Instruction, mem::PageNum, }; pub fn addi(core: &mut Core, instr: Instruction) -> InstructionResult { core.reg_write( instr.rd(), core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()), ); core.pc = core.pc.wrapping_add(4); InstructionResult::Normal } pub fn addiw(core: &mut Core, instr: Instruction) -> InstructionResult { let res = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()) as i32; core.reg_write(instr.rd(), res as i64 as u64); core.pc = core.pc.wrapping_add(4); InstructionResult::Normal } // TODO: Support misaligned memory access pub fn sd(core: &mut Core, instr: Instruction) -> InstructionResult { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); if !addr.is_multiple_of(std::mem::size_of::() as Addr) { return InstructionResult::Exception(()); } let page = (addr / 4096) as PageNum; let offset = (addr / 8 & ((4096 / 8 as Addr) - 1)) as u16; let value = core.reg_read(instr.rs2()); match core.mem.write_dword(page, offset, value) { Ok(_) => { core.pc = core.pc.wrapping_add(4); InstructionResult::Normal } Err(_) => InstructionResult::Exception(()), } } pub fn sb(core: &mut Core, instr: Instruction) -> InstructionResult { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); let page = (addr / 4096) as PageNum; let offset = (addr & (4096 as Addr - 1)) as u16; let value = core.reg_read(instr.rs2()) as u8; match core.mem.write_byte(page, offset, value) { Ok(_) => { core.pc = core.pc.wrapping_add(4); InstructionResult::Normal } Err(_) => InstructionResult::Exception(()), } } pub fn lui(core: &mut Core, instr: Instruction) -> InstructionResult { core.reg_write(instr.rd(), instr.imm_u()); core.pc = core.pc.wrapping_add(4); InstructionResult::Normal } pub fn jal(core: &mut Core, instr: Instruction) -> InstructionResult { core.reg_write(instr.rd(), core.pc); core.pc = core.pc.wrapping_add(instr.imm_j()); InstructionResult::Normal } pub fn slli(core: &mut Core, instr: Instruction) -> InstructionResult { core.reg_write(instr.rd(), core.reg_read(instr.rs1()) << instr.imm_shamt()); core.pc = core.pc.wrapping_add(4); InstructionResult::Normal }