// Copyright (c) 2025 taitep // SPDX-License-Identifier: BSD-2-Clause // // 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::RegValue, core::Core, decode::Instruction, exceptions::Exception}; use std::ops::{BitAnd, BitOr, BitXor}; mod mem; pub use mem::*; instr_op!(add, addi, RegValue::wrapping_add); instr_op!( addw, addiw, |a, b| RegValue::wrapping_add(a, b) as i32 as i64 as RegValue ); instr_op_r!(sub, RegValue::wrapping_sub); instr_op_r!(subw, |a, b| RegValue::wrapping_sub(a, b) as i32 as i64 as RegValue); instr_op!(and, andi, RegValue::bitand); instr_op!(or, ori, RegValue::bitor); instr_op!(xor, xori, RegValue::bitxor); instr_op!(sll, slli, |x, shamt| x << (shamt & 0b111111)); instr_op!( sllw, slliw, |x, shamt| (x << (shamt & 0b11111)) as i32 as i64 as RegValue ); instr_op!(srl, srli, |x, shamt| x >> (shamt & 0b111111)); instr_op!( srlw, srliw, |x, shamt| (x >> (shamt & 0b11111)) as i32 as i64 as RegValue ); instr_op!(sra, srai, |x, shamt| (x as i64 >> (shamt & 0b111111)) as RegValue); instr_op!( sraw, sraiw, |x, shamt| (x as i32 >> (shamt & 0b11111)) as i64 as RegValue ); instr_op!(sltu, sltiu, |a, b| (a < b) as RegValue); instr_op!(slt, slti, |a, b| ((a as i64) < (b as i64)) as RegValue); pub fn lui(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), instr.imm_u()); core.advance_pc(); Ok(()) } pub fn auipc(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), core.pc.wrapping_add(instr.imm_u())); core.advance_pc(); Ok(()) } pub fn jal(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), core.pc.wrapping_add(4)); core.pc = core.pc.wrapping_add(instr.imm_j()); Ok(()) } pub fn jalr(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), core.pc.wrapping_add(4)); core.pc = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); Ok(()) } instr_branch!(beq, |a, b| a == b); instr_branch!(bne, |a, b| a != b); instr_branch!(bltu, |a, b| a < b); instr_branch!(bgeu, |a, b| a >= b); instr_branch_signed!(blt, |a, b| a < b); instr_branch_signed!(bge, |a, b| a >= b);