(
insn: &DecodedInsn,
regs: &Registers,
csrs: &CsrFile,
pc: u64,
)
| 98 | // --- Public entry point --- |
| 99 | |
| 100 | pub fn execute( |
| 101 | insn: &DecodedInsn, |
| 102 | regs: &Registers, |
| 103 | csrs: &CsrFile, |
| 104 | pc: u64, |
| 105 | ) -> Result<ExecResult, VmError> { |
| 106 | match insn { |
| 107 | DecodedInsn::Lui { rd, imm } => Ok(ExecResult::WriteInt { |
| 108 | rd: *rd, |
| 109 | val: *imm as u64, |
| 110 | next_pc: pc.wrapping_add(4), |
| 111 | }), |
| 112 | |
| 113 | DecodedInsn::Auipc { rd, imm } => Ok(ExecResult::WriteInt { |
| 114 | rd: *rd, |
| 115 | val: pc.wrapping_add(*imm as u64), |
| 116 | next_pc: pc.wrapping_add(4), |
| 117 | }), |
| 118 | |
| 119 | DecodedInsn::Jal { rd, imm } => Ok(ExecResult::WriteInt { |
| 120 | rd: *rd, |
| 121 | val: pc.wrapping_add(4), |
| 122 | next_pc: pc.wrapping_add(*imm as u64), |
| 123 | }), |
| 124 | |
| 125 | DecodedInsn::Jalr { rd, rs1, imm } => { |
| 126 | let rs1_val = regs.read_x(*rs1); |
| 127 | let target = rs1_val.wrapping_add(*imm as u64) & !1u64; |
| 128 | Ok(ExecResult::WriteInt { |
| 129 | rd: *rd, |
| 130 | val: pc.wrapping_add(4), |
| 131 | next_pc: target, |
| 132 | }) |
| 133 | } |
| 134 | |
| 135 | DecodedInsn::Branch { |
| 136 | funct3, |
| 137 | rs1, |
| 138 | rs2, |
| 139 | imm, |
| 140 | } => { |
| 141 | let lhs = regs.read_x(*rs1); |
| 142 | let rhs = regs.read_x(*rs2); |
| 143 | let taken = match funct3 { |
| 144 | 0 => lhs == rhs, |
| 145 | 1 => lhs != rhs, |
| 146 | 4 => (lhs as i64) < (rhs as i64), |
| 147 | 5 => (lhs as i64) >= (rhs as i64), |
| 148 | 6 => lhs < rhs, |
| 149 | 7 => lhs >= rhs, |
| 150 | _ => return Err(VmError::IllegalInstruction(0)), |
| 151 | }; |
| 152 | let next_pc = if taken { |
| 153 | pc.wrapping_add(*imm as u64) |
| 154 | } else { |
| 155 | pc.wrapping_add(4) |
| 156 | }; |
| 157 | Ok(ExecResult::Jump { next_pc }) |
no test coverage detected