use super::super::machine::Machine;
use crate::RISCV_GENERAL_REGISTER_NUMBER;
use ckb_vm_definitions::instructions::{self as insts, InstructionOpcode};
#[inline(always)]
pub fn x(instruction_bits: u32, lower: usize, length: usize, shifts: usize) -> u32 {
((instruction_bits >> lower) & ((1 << length) - 1)) << shifts
}
#[inline(always)]
pub fn xs(instruction_bits: u32, lower: usize, length: usize, shifts: usize) -> u32 {
((instruction_bits as i32) << (32 - lower - length) >> (32 - length) << shifts) as u32
}
#[inline(always)]
pub fn opcode(instruction_bits: u32) -> u32 {
x(instruction_bits, 0, 7, 0)
}
#[inline(always)]
pub fn funct3(instruction_bits: u32) -> u32 {
x(instruction_bits, 12, 3, 0)
}
#[inline(always)]
pub fn funct7(instruction_bits: u32) -> u32 {
x(instruction_bits, 25, 7, 0)
}
#[inline(always)]
pub fn rd(instruction_bits: u32) -> usize {
x(instruction_bits, 7, 5, 0) as usize
}
#[inline(always)]
pub fn rs1(instruction_bits: u32) -> usize {
x(instruction_bits, 15, 5, 0) as usize
}
#[inline(always)]
pub fn rs2(instruction_bits: u32) -> usize {
x(instruction_bits, 20, 5, 0) as usize
}
#[inline(always)]
pub fn btype_immediate(instruction_bits: u32) -> i32 {
(x(instruction_bits, 8, 4, 1)
| x(instruction_bits, 25, 6, 5)
| x(instruction_bits, 7, 1, 11)
| xs(instruction_bits, 31, 1, 12)) as i32
}
#[inline(always)]
pub fn jtype_immediate(instruction_bits: u32) -> i32 {
(x(instruction_bits, 21, 10, 1)
| x(instruction_bits, 20, 1, 11)
| x(instruction_bits, 12, 8, 12)
| xs(instruction_bits, 31, 1, 20)) as i32
}
#[inline(always)]
pub fn itype_immediate(instruction_bits: u32) -> i32 {
xs(instruction_bits, 20, 12, 0) as i32
}
#[inline(always)]
pub fn stype_immediate(instruction_bits: u32) -> i32 {
(x(instruction_bits, 7, 5, 0) | xs(instruction_bits, 25, 7, 5)) as i32
}
#[inline(always)]
pub fn utype_immediate(instruction_bits: u32) -> i32 {
xs(instruction_bits, 12, 20, 12) as i32
}
pub fn update_register<M: Machine>(machine: &mut M, register_index: usize, value: M::REG) {
let register_index = register_index % RISCV_GENERAL_REGISTER_NUMBER;
if register_index > 0 {
machine.set_register(register_index, value);
}
}
#[inline(always)]
pub fn jalr(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_JALR_VERSION1
} else {
insts::OP_JALR_VERSION0
}
}
#[inline(always)]
pub fn lb(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_LB_VERSION1
} else {
insts::OP_LB_VERSION0
}
}
#[inline(always)]
pub fn lbu(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_LBU_VERSION1
} else {
insts::OP_LBU_VERSION0
}
}
#[inline(always)]
pub fn ld(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_LD_VERSION1
} else {
insts::OP_LD_VERSION0
}
}
#[inline(always)]
pub fn lh(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_LH_VERSION1
} else {
insts::OP_LH_VERSION0
}
}
#[inline(always)]
pub fn lhu(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_LHU_VERSION1
} else {
insts::OP_LHU_VERSION0
}
}
#[inline(always)]
pub fn lw(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_LW_VERSION1
} else {
insts::OP_LW_VERSION0
}
}
#[inline(always)]
pub fn lwu(version: u32) -> InstructionOpcode {
if version >= 1 {
insts::OP_LWU_VERSION1
} else {
insts::OP_LWU_VERSION0
}
}