1use crate::register::Register;
2
3pub trait Variant {
10 fn decode(instruction: [u8; 4]) -> Self;
11}
12
13#[inline(always)]
15fn destination(instruction: [u8; 4]) -> usize {
16 (((instruction[0] & 0x80) >> 7) | ((instruction[1] & 0x0F) << 1)) as _
17}
18#[inline(always)]
20fn source1(instruction: [u8; 4]) -> usize {
21 (((instruction[1] & 0x80) >> 7) | ((instruction[2] & 0x0F) << 1)) as _
22}
23#[inline(always)]
25fn source2(instruction: [u8; 4]) -> usize {
26 (((instruction[2] & 0xF0) >> 4) | ((instruction[3] & 0x01) << 4)) as _
27}
28
29pub struct R {
31 pub destination: usize,
32 pub source1: usize,
33 pub source2: usize
34}
35impl Variant for R {
36 fn decode(instruction: [u8; 4]) -> Self {
37 Self {
38 destination: destination(instruction),
39 source1: source1(instruction),
40 source2: source2(instruction),
41 }
42 }
43}
44
45pub struct I<R: Register> {
48 pub destination: usize,
49 pub source: usize,
50 pub immediate: R
51}
52impl<R: Register> Variant for I<R> {
53 fn decode(instruction: [u8; 4]) -> Self {
54 let signed = instruction[3] & 0x80 != 0;
55 Self {
56 destination: destination(instruction),
57 source: source1(instruction),
58 immediate: R::sign_extended_half([((instruction[2] & 0xF0) >> 4) | ((instruction[3] & 0x0F) << 4), ((instruction[3] & 0xF0) >> 4) | if signed { 0xF0 } else { 0 }])
59 }
60 }
61}
62
63pub struct C {
65 pub destination: usize,
66 pub source: usize,
67 pub csr: usize
68}
69impl Variant for C {
70 fn decode(instruction: [u8; 4]) -> Self {
71 Self {
72 destination: destination(instruction),
73 source: source1(instruction),
74 csr: ((instruction[2] & 0xF0) >> 4) as usize | ((instruction[3] & 0x0F) << 4) as usize | ((instruction[3] & 0xF0) << 4) as usize
75 }
76 }
77}
78
79pub struct S<R: Register> {
81 pub source1: usize,
82 pub source2: usize,
83 pub immediate: R
84}
85impl<R: Register> Variant for S<R> {
86 fn decode(instruction: [u8; 4]) -> Self {
87 let signed = instruction[3] & 0x80 != 0;
88 Self {
89 source1: source1(instruction),
90 source2: source2(instruction),
91 immediate: R::sign_extended_half([((instruction[0] & 0x80) >> 7) | ((instruction[1] & 0x0F) << 1) | ((instruction[3] & 0x0E) << 4), ((instruction[3] & 0xF0) >> 4) | if signed { 0xF0 } else { 0 }])
92 }
93 }
94}
95
96pub struct B<R: Register> {
99 pub source1: usize,
100 pub source2: usize,
101 pub immediate: R
102}
103impl<R: Register> Variant for B<R> {
104 fn decode(instruction: [u8; 4]) -> Self {
105 let signed = instruction[3] & 0x80 != 0;
106 Self {
107 source1: source1(instruction),
108 source2: source2(instruction),
109 immediate: R::sign_extended_half([
110 ((instruction[1] & 0xF) << 1) | ((instruction[3] & 0x0E) << 4),
111 ((instruction[3] & 0x70) >> 4) | ((instruction[0] & 0x80) >> 4) | ((instruction[3] & 0x80) >> 3) | if signed { 0xE0 } else { 0 },
112 ])
113 }
114 }
115}
116
117pub struct U<R: Register> {
119 pub destination: usize,
120 pub immediate: R
121}
122impl<R: Register> Variant for U<R> {
123 fn decode(instruction: [u8; 4]) -> Self {
124 Self {
125 destination: destination(instruction),
126 immediate: R::sign_extended_word([0, instruction[1] & 0xF0, instruction[2], instruction[3]])
127 }
128 }
129}
130
131pub struct J<R: Register> {
134 pub destination: usize,
135 pub immediate: R
136}
137impl<R: Register> Variant for J<R> {
138 fn decode(instruction: [u8; 4]) -> Self {
139 let signed = instruction[3] & 0x80 != 0;
140 Self {
141 destination: destination(instruction),
142 immediate: R::sign_extended_word([
143 ((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},
151 if signed {0xFF} else {0}
152 ])
153 }
154 }
155}