1#![allow(clippy::unreadable_literal)]
2use rysk_tools_macro::base_instructions;
3
4#[derive(Debug, Clone)]
5pub enum MachineInstruction {
6 Normal([u8; 4]),
7 Compressed([u8; 2])
8}
9
10#[derive(Copy, Clone, Debug)]
11pub enum Instruction {
12 BaseInstruction(BaseInstruction),
13 PseudoInstruction(PseudoInstruction)
14}
15impl Instruction {
16 pub fn make_pseudo(instructions: &mut [Self]) -> (Self, &mut [Self]) {
18 (instructions[0], &mut instructions[1..])
19 }
20}
21
22macro_rules! destination {
24 ($instruction:ident) => {
25 ((($instruction[0] & 0x80) >> 7) | (($instruction[1] & 0x0F) << 1)) as _
26 };
27}
28macro_rules! source1 {
30 ($instruction:ident) => {
31 ((($instruction[1] & 0x80) >> 7) | (($instruction[2] & 0x0F) << 1)) as _
32 };
33}
34macro_rules! source2 {
36 ($instruction:ident) => {
37 ((($instruction[2] & 0xF0) >> 4) | (($instruction[3] & 0x01) << 4)) as _
38 };
39}
40
41macro_rules! immediate_i {
42 ($instruction:ident) => {
43 {
44 let extra = if $instruction[3] & 0x80 != 0 { 0xFF } else { 0 };
45 i32::from_le_bytes([(($instruction[2] & 0xF0) >> 4) | (($instruction[3] & 0x0F) << 4), (($instruction[3] & 0xF0) >> 4) | (extra & 0xF0), extra, extra])
46 }
47 };
48}
49macro_rules! immediate_s {
50 ($instruction:ident) => {
51 {
52 let extra = if $instruction[3] & 0x80 != 0 { 0xFF } else { 0 };
53 i32::from_le_bytes([(($instruction[0] & 0x80) >> 7) | (($instruction[1] & 0x0F) << 1) | (($instruction[3] & 0x0E) << 4), (($instruction[3] & 0xF0) >> 4) | (extra & 0xF0), extra, extra])
54 }
55 };
56}
57macro_rules! immediate_b {
58 ($instruction:ident) => {
59 {
60 let extra = if $instruction[3] & 0x80 != 0 { 0xFF } else { 0 };
61 i32::from_le_bytes([
62 (($instruction[1] & 0xF) << 1) | (($instruction[3] & 0x0E) << 4),
63 (($instruction[3] & 0x70) >> 4) | (($instruction[0] & 0x80) >> 4) | (($instruction[3] & 0x80) >> 3) | (extra & 0xE0),
64 extra,
65 extra
66 ])
67 }
68 };
69}
70macro_rules! immediate_u {
71 ($instruction:ident) => {
72 i32::from_le_bytes([0, $instruction[1] & 0xF0, $instruction[2], $instruction[3]])
73 };
74}
75macro_rules! immediate_j {
76 ($instruction:ident) => {
77 {
78 let signed = $instruction[3] & 0x80 != 0;
79 i32::from_le_bytes([
80 (($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},
88 if signed {0xFF} else {0}
89 ])
90 }
91 };
92}
93
94base_instructions!{
96 LUI -> U(0b0110111) { "Load Upper Immediate" },
97 AUIPC -> U(0b0010111) { "Add Upper Immediate to Program Counter" },
98
99 JAL -> J(0b1101111) { "Jump and Link" },
100 JALR -> I(0b1100111, 0b000) { "Jump and Link Register" },
101 BEQ -> B(0b1100011, 0b000) { "Branch if Equal" },
102 BNE -> B(0b1100011, 0b001) { "Branch if Not Equal" },
103 BLT -> B(0b1100011, 0b100) { "Branch if Less Than" },
104 BGE -> B(0b1100011, 0b101) { "Branch if Greater Than or Equal" },
105 BLTU -> B(0b1100011, 0b110) { "Branch if Less Than Unsigned" },
106 BGEU -> B(0b1100011, 0b111) { "Branch if Greater Than or Equal Unsigned" },
107
108 LB -> I(0b0000011, 0b000) { "Load Byte" },
109 LH -> I(0b0000011, 0b001) { "Load Half" },
110 LW -> I(0b0000011, 0b010) { "Load Word" },
111 LBU -> I(0b0000011, 0b100) { "Load Byte Unsigned" },
112 LHU -> I(0b0000011, 0b101) { "Load Half Unsigned" },
113 SB -> S(0b0100011, 0b000) { "Store Byte" },
114 SH -> S(0b0100011, 0b001) { "Store Half" },
115 SW -> S(0b0100011, 0b010) { "Store Word" },
116
117 ADDI -> I(0b0010011, 0b000) { "Add Immediate" },
118 SLTI -> I(0b0010011, 0b010) { "Set if Less Than Immediate" },
119 SLTIU -> I(0b0010011, 0b011) { "Set if Less Than Immediate Unsigned" },
120 XORI -> I(0b0010011, 0b100) { "Exclusive Or Immediate" },
121 ORI -> I(0b0010011, 0b110) { "Or Immediate" },
122 ANDI -> I(0b0010011, 0b111) { "And Immediate" },
123
124 SLLI -> SH(0b0010011, 0b001, 0b00000) { "Shift Left Logical Immediate" },
125 SRLI -> SH(0b0010011, 0b101, 0b00000) { "Shift Right Logical Immediate" },
126 SRAI -> SH(0b0010011, 0b101, 0b01000) { "Shift Right Arithmetic Immediate" },
127
128 ADD -> R(0b0110011, 0b000, 0b0000000) { "Add" },
129 SUB -> R(0b0110011, 0b000, 0b0100000) { "Subtract" },
130 SLL -> R(0b0110011, 0b001, 0b0000000) { "Shift Left Logical" },
131 SLT -> R(0b0110011, 0b010, 0b0000000) { "Set if Less Than" },
132 SLTU -> R(0b0110011, 0b011, 0b0000000) { "Set if Less Than Unsigned" },
133 XOR -> R(0b0110011, 0b100, 0b0000000) { "Exclusive Or" },
134 SRL -> R(0b0110011, 0b101, 0b0100000) { "Shift Right Logical" },
135 SRA -> R(0b0110011, 0b101, 0b0100000) { "Shift Right Arithmetic" },
136 OR -> R(0b0110011, 0b110, 0b0000000) { "Or" },
137 AND -> R(0b0110011, 0b111, 0b0000000) { "And" },
138
139 FENCE -> I(0b1110011, 0b000) { "Fence" },
140}
141
142#[derive(Copy, Clone, Debug)]
143pub enum PseudoInstruction {
144
145}