Make branches macros and implement all of them

This commit is contained in:
2025-12-26 16:06:30 +01:00
parent 528b519ce9
commit 75e843f5f9
2 changed files with 25 additions and 47 deletions

View File

@@ -69,6 +69,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E
0b000 => rvi::beq(core, instr), 0b000 => rvi::beq(core, instr),
0b001 => rvi::bne(core, instr), 0b001 => rvi::bne(core, instr),
0b100 => rvi::blt(core, instr), 0b100 => rvi::blt(core, instr),
0b101 => rvi::bge(core, instr),
0b110 => rvi::bltu(core, instr), 0b110 => rvi::bltu(core, instr),
0b111 => rvi::bgeu(core, instr), 0b111 => rvi::bgeu(core, instr),
_ => Err(IllegalInstruction), _ => Err(IllegalInstruction),

View File

@@ -106,52 +106,29 @@ pub fn jalr(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> {
Ok(()) Ok(())
} }
pub fn beq(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { macro_rules! instr_branch {
if core.reg_read(instr.rs1()) == core.reg_read(instr.rs2()) { ($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()); core.pc = core.pc.wrapping_add(instr.imm_b());
} else { } else {
core.advance_pc(); core.advance_pc();
} }
Ok(()) Ok(())
}
pub fn bne(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> {
if core.reg_read(instr.rs1()) != core.reg_read(instr.rs2()) {
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)));
};
} }
pub fn blt(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { instr_branch!(beq, |a, b| a == b);
if (core.reg_read(instr.rs1()) as i64) < (core.reg_read(instr.rs2()) as i64) { instr_branch!(bne, |a, b| a != b);
core.pc = core.pc.wrapping_add(instr.imm_b()); instr_branch!(bltu, |a, b| a < b);
} else { instr_branch!(bgeu, |a, b| a >= b);
core.advance_pc(); instr_branch_signed!(blt, |a, b| a < b);
} instr_branch_signed!(bge, |a, b| a >= b);
Ok(())
}
pub fn bgeu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> {
if core.reg_read(instr.rs1()) >= core.reg_read(instr.rs2()) {
core.pc = core.pc.wrapping_add(instr.imm_b());
} else {
core.advance_pc();
}
Ok(())
}
pub fn bltu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> {
if core.reg_read(instr.rs1()) < core.reg_read(instr.rs2()) {
core.pc = core.pc.wrapping_add(instr.imm_b());
} else {
core.advance_pc();
}
Ok(())
}