1fn bit(c: u16, i: u32) -> u32 {
8 ((c >> i) & 1) as u32
9}
10
11fn bits(c: u16, hi: u32, lo: u32) -> u32 {
12 ((c as u32) >> lo) & ((1 << (hi - lo + 1)) - 1)
13}
14
15fn creg(n: u32) -> u32 {
17 8 + n
18}
19
20fn sext(v: u32, width: u32) -> i32 {
21 ((v << (32 - width)) as i32) >> (32 - width)
22}
23
24fn r_type(funct7: u32, rs2: u32, rs1: u32, funct3: u32, rd: u32, opcode: u32) -> u32 {
25 (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) | opcode
26}
27
28fn i_type(imm: i32, rs1: u32, funct3: u32, rd: u32, opcode: u32) -> u32 {
29 (((imm as u32) & 0xfff) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) | opcode
30}
31
32fn s_type(imm: i32, rs2: u32, rs1: u32, funct3: u32, opcode: u32) -> u32 {
33 let imm = imm as u32;
34 (((imm >> 5) & 0x7f) << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | ((imm & 0x1f) << 7) | opcode
35}
36
37fn b_type(imm: i32, rs2: u32, rs1: u32, funct3: u32, opcode: u32) -> u32 {
38 let imm = imm as u32;
39 (((imm >> 12) & 1) << 31)
40 | (((imm >> 5) & 0x3f) << 25)
41 | (rs2 << 20)
42 | (rs1 << 15)
43 | (funct3 << 12)
44 | (((imm >> 1) & 0xf) << 8)
45 | (((imm >> 11) & 1) << 7)
46 | opcode
47}
48
49fn u_type(imm20: u32, rd: u32, opcode: u32) -> u32 {
50 ((imm20 & 0xfffff) << 12) | (rd << 7) | opcode
51}
52
53fn j_type(imm: i32, rd: u32, opcode: u32) -> u32 {
54 let imm = imm as u32;
55 (((imm >> 20) & 1) << 31)
56 | (((imm >> 1) & 0x3ff) << 21)
57 | (((imm >> 11) & 1) << 20)
58 | (((imm >> 12) & 0xff) << 12)
59 | (rd << 7)
60 | opcode
61}
62
63const OP_LOAD: u32 = 0x03;
64const OP_LOAD_FP: u32 = 0x07;
65const OP_IMM: u32 = 0x13;
66const OP_IMM_32: u32 = 0x1b;
67const OP_STORE: u32 = 0x23;
68const OP_STORE_FP: u32 = 0x27;
69const OP: u32 = 0x33;
70const OP_LUI: u32 = 0x37;
71const OP_32: u32 = 0x3b;
72const OP_BRANCH: u32 = 0x63;
73const OP_JALR: u32 = 0x67;
74const OP_JAL: u32 = 0x6f;
75const OP_SYSTEM: u32 = 0x73;
76
77pub fn is_compressed(low_half: u16) -> bool {
79 low_half & 3 != 3
80}
81
82pub fn expand(c: u16) -> Option<u32> {
84 let funct3 = bits(c, 15, 13);
85 let rd = bits(c, 11, 7);
86 let rs2 = bits(c, 6, 2);
87 let rdp = creg(bits(c, 4, 2));
88 let rs1p = creg(bits(c, 9, 7));
89 let imm6 = sext((bit(c, 12) << 5) | bits(c, 6, 2), 6);
90 match c & 3 {
91 0 => match funct3 {
92 0 => {
93 let nzuimm =
95 (bits(c, 12, 11) << 4) | (bits(c, 10, 7) << 6) | (bit(c, 6) << 2) | (bit(c, 5) << 3);
96 (nzuimm != 0).then(|| i_type(nzuimm as i32, 2, 0, rdp, OP_IMM))
97 }
98 1 => {
99 let uimm = (bits(c, 12, 10) << 3) | (bits(c, 6, 5) << 6);
101 Some(i_type(uimm as i32, rs1p, 3, rdp, OP_LOAD_FP))
102 }
103 2 => {
104 let uimm = (bits(c, 12, 10) << 3) | (bit(c, 6) << 2) | (bit(c, 5) << 6);
106 Some(i_type(uimm as i32, rs1p, 2, rdp, OP_LOAD))
107 }
108 3 => {
109 let uimm = (bits(c, 12, 10) << 3) | (bits(c, 6, 5) << 6);
111 Some(i_type(uimm as i32, rs1p, 3, rdp, OP_LOAD))
112 }
113 4 => None,
114 5 => {
115 let uimm = (bits(c, 12, 10) << 3) | (bits(c, 6, 5) << 6);
117 Some(s_type(uimm as i32, rdp, rs1p, 3, OP_STORE_FP))
118 }
119 6 => {
120 let uimm = (bits(c, 12, 10) << 3) | (bit(c, 6) << 2) | (bit(c, 5) << 6);
122 Some(s_type(uimm as i32, rdp, rs1p, 2, OP_STORE))
123 }
124 _ => {
125 let uimm = (bits(c, 12, 10) << 3) | (bits(c, 6, 5) << 6);
127 Some(s_type(uimm as i32, rdp, rs1p, 3, OP_STORE))
128 }
129 },
130 1 => match funct3 {
131 0 => Some(i_type(imm6, rd, 0, rd, OP_IMM)),
133 1 => (rd != 0).then(|| i_type(imm6, rd, 0, rd, OP_IMM_32)),
135 2 => Some(i_type(imm6, 0, 0, rd, OP_IMM)),
137 3 if rd == 2 => {
138 let nzimm = (bit(c, 12) << 9)
140 | (bit(c, 6) << 4)
141 | (bit(c, 5) << 6)
142 | (bits(c, 4, 3) << 7)
143 | (bit(c, 2) << 5);
144 (nzimm != 0).then(|| i_type(sext(nzimm, 10), 2, 0, 2, OP_IMM))
145 }
146 3 => {
147 let nzimm = (bit(c, 12) << 5) | bits(c, 6, 2);
149 (nzimm != 0).then(|| u_type(sext(nzimm, 6) as u32, rd, OP_LUI))
150 }
151 4 => {
152 let shamt = (bit(c, 12) << 5) | bits(c, 6, 2);
153 match bits(c, 11, 10) {
154 0 => Some(i_type(shamt as i32, rs1p, 5, rs1p, OP_IMM)),
156 1 => Some(i_type((0x400 | shamt) as i32, rs1p, 5, rs1p, OP_IMM)),
158 2 => Some(i_type(imm6, rs1p, 7, rs1p, OP_IMM)),
160 _ => {
161 let rs2p = creg(bits(c, 4, 2));
162 match (bit(c, 12), bits(c, 6, 5)) {
163 (0, 0) => Some(r_type(0x20, rs2p, rs1p, 0, rs1p, OP)), (0, 1) => Some(r_type(0, rs2p, rs1p, 4, rs1p, OP)), (0, 2) => Some(r_type(0, rs2p, rs1p, 6, rs1p, OP)), (0, _) => Some(r_type(0, rs2p, rs1p, 7, rs1p, OP)), (_, 0) => Some(r_type(0x20, rs2p, rs1p, 0, rs1p, OP_32)), (_, 1) => Some(r_type(0, rs2p, rs1p, 0, rs1p, OP_32)), _ => None,
170 }
171 }
172 }
173 }
174 5 => {
175 let imm = (bit(c, 12) << 11)
177 | (bit(c, 11) << 4)
178 | (bits(c, 10, 9) << 8)
179 | (bit(c, 8) << 10)
180 | (bit(c, 7) << 6)
181 | (bit(c, 6) << 7)
182 | (bits(c, 5, 3) << 1)
183 | (bit(c, 2) << 5);
184 Some(j_type(sext(imm, 12), 0, OP_JAL))
185 }
186 _ => {
187 let imm = (bit(c, 12) << 8)
189 | (bits(c, 11, 10) << 3)
190 | (bits(c, 6, 5) << 6)
191 | (bits(c, 4, 3) << 1)
192 | (bit(c, 2) << 5);
193 Some(b_type(sext(imm, 9), 0, rs1p, if funct3 == 6 { 0 } else { 1 }, OP_BRANCH))
194 }
195 },
196 2 => match funct3 {
197 0 => {
199 let shamt = (bit(c, 12) << 5) | bits(c, 6, 2);
200 Some(i_type(shamt as i32, rd, 1, rd, OP_IMM))
201 }
202 1 => {
203 let uimm = (bit(c, 12) << 5) | (bits(c, 6, 5) << 3) | (bits(c, 4, 2) << 6);
205 Some(i_type(uimm as i32, 2, 3, rd, OP_LOAD_FP))
206 }
207 2 => {
208 let uimm = (bit(c, 12) << 5) | (bits(c, 6, 4) << 2) | (bits(c, 3, 2) << 6);
210 (rd != 0).then(|| i_type(uimm as i32, 2, 2, rd, OP_LOAD))
211 }
212 3 => {
213 let uimm = (bit(c, 12) << 5) | (bits(c, 6, 5) << 3) | (bits(c, 4, 2) << 6);
215 (rd != 0).then(|| i_type(uimm as i32, 2, 3, rd, OP_LOAD))
216 }
217 4 => match (bit(c, 12), rd, rs2) {
218 (0, 0, 0) => None, (0, _, 0) => Some(i_type(0, rd, 0, 0, OP_JALR)), (0, _, _) => Some(r_type(0, rs2, 0, 0, rd, OP)), (_, 0, 0) => Some(i_type(1, 0, 0, 0, OP_SYSTEM)), (_, _, 0) => Some(i_type(0, rd, 0, 1, OP_JALR)), _ => Some(r_type(0, rs2, rd, 0, rd, OP)), },
225 5 => {
226 let uimm = (bits(c, 12, 10) << 3) | (bits(c, 9, 7) << 6);
228 Some(s_type(uimm as i32, rs2, 2, 3, OP_STORE_FP))
229 }
230 6 => {
231 let uimm = (bits(c, 12, 9) << 2) | (bits(c, 8, 7) << 6);
233 Some(s_type(uimm as i32, rs2, 2, 2, OP_STORE))
234 }
235 _ => {
236 let uimm = (bits(c, 12, 10) << 3) | (bits(c, 9, 7) << 6);
238 Some(s_type(uimm as i32, rs2, 2, 3, OP_STORE))
239 }
240 },
241 _ => None,
242 }
243}