From 34034dd5db07f71b0854de0f2bbb18e39aa3db69 Mon Sep 17 00:00:00 2001 From: taitep Date: Fri, 26 Dec 2025 18:14:32 +0100 Subject: Make macros for R/I-type operations and use them to implement basically every single one i think --- src/instructions/macros.rs | 64 ++++++++++++++++++++++ src/instructions/rvi.rs | 131 ++++++++++++++------------------------------- 2 files changed, 103 insertions(+), 92 deletions(-) create mode 100644 src/instructions/macros.rs (limited to 'src/instructions') diff --git a/src/instructions/macros.rs b/src/instructions/macros.rs new file mode 100644 index 0000000..c88114c --- /dev/null +++ b/src/instructions/macros.rs @@ -0,0 +1,64 @@ +// 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. + +#[macro_export] +macro_rules! instr_branch { + ($name:ident, $cond:expr) => { + pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + let a = core.reg_read(instr.rs1()); + let b = core.reg_read(instr.rs2()); + if $cond(a, b) { + core.pc = core.pc.wrapping_add(instr.imm_b()); + } else { + core.advance_pc(); + } + Ok(()) + } + }; +} + +#[macro_export] +macro_rules! instr_branch_signed { + ($name:ident, $cond:expr) => { + instr_branch!($name, |a, b| $cond((a as i64), (b as i64))); + }; +} + +#[macro_export] +macro_rules! instr_op_r { + ($name:ident, $op:expr) => { + pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + let a = core.reg_read(instr.rs1()); + let b = core.reg_read(instr.rs2()); + let res = $op(a, b); + core.reg_write(instr.rd(), res); + core.advance_pc(); + Ok(()) + } + }; +} + +#[macro_export] +macro_rules! instr_op_i { + ($name:ident, $op:expr) => { + pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + let a = core.reg_read(instr.rs1()); + let b = instr.imm_i(); + let res = $op(a, b); + core.reg_write(instr.rd(), res); + core.advance_pc(); + Ok(()) + } + }; +} + +#[macro_export] +macro_rules! instr_op { + ($name:ident, $name_imm:ident, $op:expr) => { + instr_op_r!($name, $op); + instr_op_i!($name_imm, $op); + }; +} diff --git a/src/instructions/rvi.rs b/src/instructions/rvi.rs index a348596..c35098f 100644 --- a/src/instructions/rvi.rs +++ b/src/instructions/rvi.rs @@ -4,83 +4,50 @@ // 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::{core::Core, decode::Instruction, exceptions::ExceptionType}; +use crate::{consts::RegValue, core::Core, decode::Instruction, exceptions::ExceptionType}; + +use std::ops::{BitAnd, BitOr, BitXor}; mod mem; pub use mem::*; -pub fn add(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write( - instr.rd(), - core.reg_read(instr.rs1()) - .wrapping_add(core.reg_read(instr.rs2())), - ); - core.advance_pc(); - Ok(()) -} - -pub fn sub(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write( - instr.rd(), - core.reg_read(instr.rs1()) - .wrapping_sub(core.reg_read(instr.rs2())), - ); - core.advance_pc(); - Ok(()) -} - -pub fn addi(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write( - instr.rd(), - core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()), - ); - core.advance_pc(); - Ok(()) -} - -pub fn addiw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - 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.advance_pc(); - Ok(()) -} - -pub fn and(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write( - instr.rd(), - core.reg_read(instr.rs1()) & core.reg_read(instr.rs2()), - ); - core.advance_pc(); - Ok(()) -} - -pub fn andi(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write(instr.rd(), core.reg_read(instr.rs1()) & instr.imm_i()); - core.advance_pc(); - Ok(()) -} - -pub fn or(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write( - instr.rd(), - core.reg_read(instr.rs1()) | core.reg_read(instr.rs2()), - ); - core.advance_pc(); - Ok(()) -} - -pub fn slli(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write(instr.rd(), core.reg_read(instr.rs1()) << instr.imm_shamt()); - core.advance_pc(); - Ok(()) -} - -pub fn srli(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - core.reg_write(instr.rd(), core.reg_read(instr.rs1()) >> instr.imm_shamt()); - core.advance_pc(); - Ok(()) -} +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<(), ExceptionType> { core.reg_write(instr.rd(), instr.imm_u()); @@ -106,26 +73,6 @@ pub fn jalr(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -macro_rules! instr_branch { - ($name:ident, $cond:expr) => { - pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { - let a = core.reg_read(instr.rs1()); - let b = core.reg_read(instr.rs2()); - if $cond(a, b) { - core.pc = core.pc.wrapping_add(instr.imm_b()); - } else { - core.advance_pc(); - } - Ok(()) - } - }; -} -macro_rules! instr_branch_signed { - ($name:ident, $cond:expr) => { - instr_branch!($name, |a, b| $cond((a as i64), (b as i64))); - }; -} - instr_branch!(beq, |a, b| a == b); instr_branch!(bne, |a, b| a != b); instr_branch!(bltu, |a, b| a < b); -- cgit v1.2.3