#![allow(clippy::unreadable_literal)]
use rysk_tools_macro::base_instructions;
#[derive(Debug, Clone)]
pub enum MachineInstruction {
Normal([u8; 4]),
Compressed([u8; 2])
}
#[derive(Copy, Clone, Debug)]
pub enum Instruction {
BaseInstruction(BaseInstruction),
PseudoInstruction(PseudoInstruction)
}
impl Instruction {
pub fn make_pseudo(instructions: &mut [Self]) -> (Self, &mut [Self]) {
(instructions[0], &mut instructions[1..])
}
}
macro_rules! destination {
($instruction:ident) => {
((($instruction[0] & 0x80) >> 7) | (($instruction[1] & 0x0F) << 1)) as _
};
}
macro_rules! source1 {
($instruction:ident) => {
((($instruction[1] & 0x80) >> 7) | (($instruction[2] & 0x0F) << 1)) as _
};
}
macro_rules! source2 {
($instruction:ident) => {
((($instruction[2] & 0xF0) >> 4) | (($instruction[3] & 0x01) << 4)) as _
};
}
macro_rules! immediate_i {
($instruction:ident) => {
{
let extra = if $instruction[3] & 0x80 != 0 { 0xFF } else { 0 };
i32::from_le_bytes([(($instruction[2] & 0xF0) >> 4) | (($instruction[3] & 0x0F) << 4), (($instruction[3] & 0xF0) >> 4) | (extra & 0xF0), extra, extra])
}
};
}
macro_rules! immediate_s {
($instruction:ident) => {
{
let extra = if $instruction[3] & 0x80 != 0 { 0xFF } else { 0 };
i32::from_le_bytes([(($instruction[0] & 0x80) >> 7) | (($instruction[1] & 0x0F) << 1) | (($instruction[3] & 0x0E) << 4), (($instruction[3] & 0xF0) >> 4) | (extra & 0xF0), extra, extra])
}
};
}
macro_rules! immediate_b {
($instruction:ident) => {
{
let extra = if $instruction[3] & 0x80 != 0 { 0xFF } else { 0 };
i32::from_le_bytes([
(($instruction[1] & 0xF) << 1) | (($instruction[3] & 0x0E) << 4),
(($instruction[3] & 0x70) >> 4) | (($instruction[0] & 0x80) >> 4) | (($instruction[3] & 0x80) >> 3) | (extra & 0xE0),
extra,
extra
])
}
};
}
macro_rules! immediate_u {
($instruction:ident) => {
i32::from_le_bytes([0, $instruction[1] & 0xF0, $instruction[2], $instruction[3]])
};
}
macro_rules! immediate_j {
($instruction:ident) => {
{
let signed = $instruction[3] & 0x80 != 0;
i32::from_le_bytes([
(($instruction[2] & 0xE0) >> 4)
| (($instruction[3] & 0x0F) << 4),
(($instruction[3] & 0x70) >> 4)
| (($instruction[2] & 0x10) >> 1)
| ($instruction[1] & 0xF0),
($instruction[2] & 0x0F)
| (($instruction[3] & 0x80) >> 3)
| if signed {0xE0} else {0},
if signed {0xFF} else {0}
])
}
};
}
base_instructions!{
LUI -> U(0b0110111) { "Load Upper Immediate" },
AUIPC -> U(0b0010111) { "Add Upper Immediate to Program Counter" },
JAL -> J(0b1101111) { "Jump and Link" },
JALR -> I(0b1100111, 0b000) { "Jump and Link Register" },
BEQ -> B(0b1100011, 0b000) { "Branch if Equal" },
BNE -> B(0b1100011, 0b001) { "Branch if Not Equal" },
BLT -> B(0b1100011, 0b100) { "Branch if Less Than" },
BGE -> B(0b1100011, 0b101) { "Branch if Greater Than or Equal" },
BLTU -> B(0b1100011, 0b110) { "Branch if Less Than Unsigned" },
BGEU -> B(0b1100011, 0b111) { "Branch if Greater Than or Equal Unsigned" },
LB -> I(0b0000011, 0b000) { "Load Byte" },
LH -> I(0b0000011, 0b001) { "Load Half" },
LW -> I(0b0000011, 0b010) { "Load Word" },
LBU -> I(0b0000011, 0b100) { "Load Byte Unsigned" },
LHU -> I(0b0000011, 0b101) { "Load Half Unsigned" },
SB -> S(0b0100011, 0b000) { "Store Byte" },
SH -> S(0b0100011, 0b001) { "Store Half" },
SW -> S(0b0100011, 0b010) { "Store Word" },
ADDI -> I(0b0010011, 0b000) { "Add Immediate" },
SLTI -> I(0b0010011, 0b010) { "Set if Less Than Immediate" },
SLTIU -> I(0b0010011, 0b011) { "Set if Less Than Immediate Unsigned" },
XORI -> I(0b0010011, 0b100) { "Exclusive Or Immediate" },
ORI -> I(0b0010011, 0b110) { "Or Immediate" },
ANDI -> I(0b0010011, 0b111) { "And Immediate" },
SLLI -> SH(0b0010011, 0b001, 0b00000) { "Shift Left Logical Immediate" },
SRLI -> SH(0b0010011, 0b101, 0b00000) { "Shift Right Logical Immediate" },
SRAI -> SH(0b0010011, 0b101, 0b01000) { "Shift Right Arithmetic Immediate" },
ADD -> R(0b0110011, 0b000, 0b0000000) { "Add" },
SUB -> R(0b0110011, 0b000, 0b0100000) { "Subtract" },
SLL -> R(0b0110011, 0b001, 0b0000000) { "Shift Left Logical" },
SLT -> R(0b0110011, 0b010, 0b0000000) { "Set if Less Than" },
SLTU -> R(0b0110011, 0b011, 0b0000000) { "Set if Less Than Unsigned" },
XOR -> R(0b0110011, 0b100, 0b0000000) { "Exclusive Or" },
SRL -> R(0b0110011, 0b101, 0b0100000) { "Shift Right Logical" },
SRA -> R(0b0110011, 0b101, 0b0100000) { "Shift Right Arithmetic" },
OR -> R(0b0110011, 0b110, 0b0000000) { "Or" },
AND -> R(0b0110011, 0b111, 0b0000000) { "And" },
FENCE -> I(0b1110011, 0b000) { "Fence" },
}
#[derive(Copy, Clone, Debug)]
pub enum PseudoInstruction {
}