1use riscv_codec_proc_macros::{
2 amo_assemble, b_assemble, ci_assemble, cr_assemble, fr_assemble, i_assemble, l_assemble,
3 r_assemble, s_assemble, sh_assemble, shw_assemble,
4};
5
6use crate::immediates::*;
7use crate::instruction::RoundingMode;
8use crate::register::{CFRegister, CIRegister, FRegister, IRegister};
9use crate::{cinstruction::CInstruction, instruction::Instruction};
10
11fn parse_int(str: &str) -> Result<i64, String> {
12 match str.parse::<i64>() {
13 Ok(e) => Ok(e),
14 Err(_) => Err(format!("unable to parse int:{str}").to_owned()),
15 }
16}
17
18fn parse_address_expression(str: &str) -> Result<(IRegister, i64), String> {
19 let (offset, register): (&str, &str) = if let Some(x) = str.split_once("(") {
20 x
21 } else {
22 panic!("no (");
23 };
24 match register.strip_suffix(")") {
25 Some(y) => {
26 let r = IRegister::from_string(y)?;
27 let i = parse_int(offset)?;
28 Ok((r, i))
29 }
30 _ => Err("Address expression should end in a )".to_owned()),
31 }
32}
33
34fn parse_address_expression_compressed(str: &str) -> Result<(CIRegister, i64), String> {
35 let (offset, register): (&str, &str) = if let Some(x) = str.split_once("(") {
36 x
37 } else {
38 panic!("no (");
39 };
40 match register.strip_suffix(")") {
41 Some(y) => {
42 let r = CIRegister::try_from(y)?;
43 let i = parse_int(offset)?;
44 Ok((r, i))
45 }
46 _ => Err("Address expression should end in a )".to_owned()),
47 }
48}
49
50fn parse_fence_set(s: &str) -> u8 {
52 let mut x = 0;
53 if s.contains("w") {
54 x |= 0b1;
55 }
56 if s.contains("r") {
57 x |= 0b10;
58 }
59 if s.contains("o") {
60 x |= 0b100;
61 }
62 if s.contains("i") {
63 x |= 0b1000;
64 }
65 x
66}
67
68#[derive(Debug, PartialEq)]
69pub enum AssemblyResult {
70 I(Instruction),
71 C(CInstruction),
72}
73impl AssemblyResult {
74 pub fn c(self) -> CInstruction {
75 match self {
76 AssemblyResult::I(_) => panic!("c called on regular instruction"),
77 AssemblyResult::C(cinstruction) => cinstruction,
78 }
79 }
80 pub fn i(self) -> Instruction {
81 match self {
82 AssemblyResult::I(instruction) => instruction,
83 AssemblyResult::C(_) => panic!("i called on compressed instruction"),
84 }
85 }
86}
87
88pub fn assemble_line(line: &str) -> Result<AssemblyResult, String> {
90 let (mnemonic, operands): (&str, &str) = if let Some(x) = line.split_once(" ") {
91 x
92 } else {
93 (line, "")
94 };
95
96 let mnemonics: Vec<&str> = mnemonic.split(".").collect();
97
98 let operands: Vec<&str> = if operands.is_empty() {
99 vec![]
100 } else {
101 operands.split(',').collect()
102 };
103 let operands: Vec<&str> = operands
104 .iter()
105 .map(|operand| operand.to_owned().trim())
106 .collect();
107
108 if mnemonics[0] == "c" {
109 if mnemonics.len() == 1 {
110 Err("compressed instruction must be specified".to_owned())
111 } else {
112 compressed_assemble(&mnemonics[1..], operands).map(AssemblyResult::C)
113 }
114 } else {
115 let x = match mnemonics[0] {
116 "addi" => i_assemble!(ADDI),
118 "addiw" => i_assemble!(ADDIW),
119 "andi" => i_assemble!(ANDI),
120 "ori" => i_assemble!(ORI),
121 "xori" => i_assemble!(XORI),
122 "slti" => i_assemble!(SLTI),
123 "sltiu" => i_assemble!(SLTIU),
124 "slli" => sh_assemble!(SLLI),
125 "srai" => sh_assemble!(SRAI),
126 "sraiw" => shw_assemble!(SRAIW),
127 "srli" => sh_assemble!(SRLI),
128 "srliw" => shw_assemble!(SRLIW),
129 "slliw" => shw_assemble!(SLLIW),
130 "add" => r_assemble!(ADD),
132 "addw" => r_assemble!(ADDW),
133 "subw" => r_assemble!(SUBW),
134 "and" => r_assemble!(AND),
135 "sub" => r_assemble!(SUB),
136 "or" => r_assemble!(OR),
137 "xor" => r_assemble!(XOR),
138 "sllw" => r_assemble!(SLLW),
139 "srl" => r_assemble!(SRL),
140 "sra" => r_assemble!(SRA),
141 "srlw" => r_assemble!(SRLW),
142 "sraw" => r_assemble!(SRAW),
143 "sll" => r_assemble!(SLL),
144 "slt" => r_assemble!(SLT),
145 "sltu" => r_assemble!(SLTU),
146 "mul" => r_assemble!(MUL),
147 "mulh" => r_assemble!(MULH),
148 "mulhsu" => r_assemble!(MULHSU),
149 "mulhu" => r_assemble!(MULHU),
150 "div" => r_assemble!(DIV),
151 "divu" => r_assemble!(DIVU),
152 "rem" => r_assemble!(REM),
153 "remu" => r_assemble!(REMU),
154 "mulw" => r_assemble!(MULW),
155 "divw" => r_assemble!(DIVW),
156 "divuw" => r_assemble!(DIVUW),
157 "remw" => r_assemble!(REMW),
158 "remuw" => r_assemble!(REMUW),
159 "lb" => l_assemble!(LB),
161 "lbu" => l_assemble!(LBU),
162 "lhu" => l_assemble!(LHU),
163 "lw" => l_assemble!(LW),
164 "lwu" => l_assemble!(LWU),
165 "lh" => l_assemble!(LH),
166 "ld" => l_assemble!(LD),
168 "sd" => s_assemble!(SD),
169 "sw" => s_assemble!(SW),
170 "sh" => s_assemble!(SH),
171 "sb" => s_assemble!(SB),
172 "blt" => b_assemble!(BLT),
174 "beq" => b_assemble!(BEQ),
175 "bne" => b_assemble!(BNE),
176 "bge" => b_assemble!(BGE),
177 "bgeu" => b_assemble!(BGEU),
178 "bltu" => b_assemble!(BLTU),
179 "jalr" => {
180 if operands.len() != 2 {
181 Err("jalr instruction requires 2 operands".to_owned())
182 } else {
183 let (base, offset) = parse_address_expression(operands[1])?;
184 Ok(Instruction::JALR {
185 dest: IRegister::from_string(operands[0])?,
186 base,
187 offset: IImmediate::try_from(offset)?,
188 })
189 }
190 }
191 "jal" => {
192 if operands.len() != 2 {
193 Err("jal instruction requires 2 operands".to_owned())
194 } else {
195 Ok(Instruction::JAL {
196 dest: IRegister::from_string(operands[0])?,
197 offset: JImmediate::try_from(parse_int(operands[1])?)?,
198 })
199 }
200 }
201 "lui" => {
202 if operands.len() != 2 {
203 Err("lui instruction requires 2 operands".to_owned())
204 } else {
205 let int: i64 = parse_int(operands[1])?;
206 if int > 2i64.pow(19) - 1 || int < -2i64.pow(19) {
207 Err("UImmediate out of range".to_owned())
208 } else {
209 Ok(Instruction::LUI {
210 dest: IRegister::from_string(operands[0])?,
211 imm: UImmediate::try_from(int)?,
212 })
213 }
214 }
215 }
216 "auipc" => {
217 if operands.len() != 2 {
218 Err("auipc instruction requires 2 operands".to_owned())
219 } else {
220 let int: i64 = parse_int(operands[1])?;
221 if int > 2i64.pow(19) - 1 || int < -2i64.pow(19) {
222 Err("UImmediate out of range".to_owned())
223 } else {
224 Ok(Instruction::AUIPC {
225 dest: IRegister::from_string(operands[0])?,
226 imm: UImmediate::try_from(int)?,
227 })
228 }
229 }
230 }
231 "fence" => {
232 if mnemonics.len() == 1 {
233 if operands.len() != 2 {
234 Err("fence instruction requires 2 operands".to_owned())
235 } else {
236 let ops =
237 parse_fence_set(operands[1]) | (parse_fence_set(operands[0]) << 4);
238 Ok(Instruction::FENCE {
239 rd: IRegister::Zero,
241 rs1: IRegister::Zero,
242 ops,
243 fm: 0, })
245 }
246 } else if mnemonics[1] == "tso" {
247 if operands.len() != 2 {
248 Err("fence.tso instruction requires 2 operands".to_owned())
249 } else {
250 let ops =
251 parse_fence_set(operands[1]) | (parse_fence_set(operands[0]) << 4);
252 if ops != (parse_fence_set("rw") | (parse_fence_set("rw") << 4)) {
253 Err("fence.tso should be rw,rw".to_owned())
254 } else {
255 Ok(Instruction::FENCE {
256 rd: IRegister::Zero,
258 rs1: IRegister::Zero,
259 ops,
260 fm: 0b1000, })
262 }
263 }
264 } else if mnemonics[1] == "i" {
265 if operands.len() != 0 {
266 Err("fence.i requires 0 operands".to_owned())
267 } else {
268 Ok(Instruction::FENCEI)
269 }
270 } else {
271 Err("invalid fence".to_owned())
272 }
273 }
274 "lr" => {
276 if mnemonics.len() == 1 {
277 Err("lr must have size (w/d)".to_owned())
278 } else if mnemonics.len() == 2 {
279 if mnemonics[1] == "w" {
280 Ok(Instruction::LRW {
281 dest: IRegister::from_string(operands[0])?,
282 addr: IRegister::from_string(operands[1])?,
283 aq: false,
284 rl: false,
285 })
286 } else if mnemonics[1] == "d" {
287 Ok(Instruction::LRD {
288 dest: IRegister::from_string(operands[0])?,
289 addr: IRegister::from_string(operands[1])?,
290 aq: false,
291 rl: false,
292 })
293 } else {
294 Err("size of lr isntruction must be word (w) or doubleword (d)".to_owned())
295 }
296 } else if mnemonics.len() == 3 {
297 let (aq, rl) = match mnemonics[2] {
298 "" => (false, false),
299 "aq" => (true, false),
300 "rl" => (false, true),
301 "aqrl" => (true, true),
302 _ => return Err("ordering should be (aq)(rl)".to_owned()),
303 };
304 if mnemonics[1] == "w" {
305 Ok(Instruction::LRW {
306 dest: IRegister::from_string(operands[0])?,
307 addr: IRegister::from_string(operands[1])?,
308 aq,
309 rl,
310 })
311 } else if mnemonics[1] == "d" {
312 Ok(Instruction::LRD {
313 dest: IRegister::from_string(operands[0])?,
314 addr: IRegister::from_string(operands[1])?,
315 aq,
316 rl,
317 })
318 } else {
319 Err("size of lr isntruction must be word (w) or doubleword (d)".to_owned())
320 }
321 } else {
322 Err(
323 "lr instruction has too many suffixes, expected lr.size.ordering"
324 .to_owned(),
325 )
326 }
327 }
328 "sc" => amo_assemble!(SC),
329 "amoswap" => amo_assemble!(AMOSWAP),
330 "amoadd" => amo_assemble!(AMOADD),
331 "amoxor" => amo_assemble!(AMOXOR),
332 "amoand" => amo_assemble!(AMOAND),
333 "amoor" => amo_assemble!(AMOOR),
334 "amomin" => amo_assemble!(AMOMIN),
335 "amomax" => amo_assemble!(AMOMAX),
336 "amominu" => amo_assemble!(AMOMINU),
337 "amomaxu" => amo_assemble!(AMOMAXU),
338 "flw" => {
339 if operands.len() != 2 {
340 println!("{:?}", operands);
341 Err("flw instruction requires 2 operands".to_owned())
342 } else {
343 let (base, offset) = parse_address_expression(operands[1])?;
344 Ok(Instruction::FLW {
345 dest: FRegister::try_from(operands[0])?,
346 base,
347 offset: IImmediate::try_from(offset)?,
348 })
349 }
350 }
351 "fsw" => {
352 if operands.len() != 2 {
353 println!("{:?}", operands);
354 Err("fsw instruction requires 2 operands".to_owned())
355 } else {
356 let (base, offset) = parse_address_expression(operands[1])?;
357 Ok(Instruction::FSW {
358 base,
359 src: FRegister::try_from(operands[0])?,
360 offset: SImmediate::try_from(offset)?,
361 })
362 }
363 }
364 "fsqrt" => {
365 if operands.len() != 2 {
366 Err("fsqrt instruction requires 2 operands".to_owned())
367 } else if mnemonics.len() == 2 {
368 Ok(Instruction::FSQRTS {
369 dest: FRegister::try_from(operands[0])?,
370 src: FRegister::try_from(operands[1])?,
371 rm: RoundingMode::DYN,
372 })
373 } else if mnemonics.len() == 3 {
374 Ok(Instruction::FSQRTS {
375 dest: FRegister::try_from(operands[0])?,
376 src: FRegister::try_from(operands[1])?,
377 rm: RoundingMode::from_str(mnemonics[2])?,
378 })
379 } else {
380 Err("fsqrt instruction requires a suffix {s,d}".to_owned())
381 }
382 }
383 "fadd" => fr_assemble!(FADD),
384 "fsub" => fr_assemble!(FSUB),
385 "fmul" => fr_assemble!(FMUL),
386 "fdiv" => fr_assemble!(FDIV),
387 "fmin" => {
388 if operands.len() != 3 {
389 Err("fmin instruction requires 3 operands".to_owned())
390 } else if mnemonics.len() == 2 {
391 Ok(Instruction::FMINS {
392 dest: FRegister::try_from(operands[0])?,
393 src1: FRegister::try_from(operands[1])?,
394 src2: FRegister::try_from(operands[2])?,
395 })
396 } else {
397 Err("fmin instruction requires a suffix {s,d}".to_owned())
398 }
399 }
400 "fmax" => {
401 if operands.len() != 3 {
402 Err("fmax instruction requires 3 operands".to_owned())
403 } else if mnemonics.len() == 2 {
404 Ok(Instruction::FMAXS {
405 dest: FRegister::try_from(operands[0])?,
406 src1: FRegister::try_from(operands[1])?,
407 src2: FRegister::try_from(operands[2])?,
408 })
409 } else {
410 Err("fmax instruction requires a suffix {s,d}".to_owned())
411 }
412 }
413 "fcvt" => {
414 if operands.len() != 2 {
415 Err("fcvt requires 3 operands".to_owned())
416 } else if mnemonics.len() == 3 {
417 match (mnemonics[1], mnemonics[2]) {
419 ("w", "s") => Ok(Instruction::FCVTWS {
420 dest: IRegister::from_string(operands[0])?,
421 src: FRegister::try_from(operands[1])?,
422 rm: RoundingMode::DYN,
423 }),
424 ("wu", "s") => Ok(Instruction::FCVTWUS {
425 dest: IRegister::from_string(operands[0])?,
426 src: FRegister::try_from(operands[1])?,
427 rm: RoundingMode::DYN,
428 }),
429 ("s", "w") => Ok(Instruction::FCVTSW {
430 dest: FRegister::try_from(operands[0])?,
431 src: IRegister::from_string(operands[1])?,
432 rm: RoundingMode::DYN,
433 }),
434 ("s", "wu") => Ok(Instruction::FCVTSWU {
435 dest: FRegister::try_from(operands[0])?,
436 src: IRegister::from_string(operands[1])?,
437 rm: RoundingMode::DYN,
438 }),
439 ("l", "s") => Ok(Instruction::FCVTLS {
440 dest: IRegister::from_string(operands[0])?,
441 src: FRegister::try_from(operands[1])?,
442 rm: RoundingMode::DYN,
443 }),
444 ("lu", "s") => Ok(Instruction::FCVTLUS {
445 dest: IRegister::from_string(operands[0])?,
446 src: FRegister::try_from(operands[1])?,
447 rm: RoundingMode::DYN,
448 }),
449 ("s", "l") => Ok(Instruction::FCVTSL {
450 dest: FRegister::try_from(operands[0])?,
451 src: IRegister::from_string(operands[1])?,
452 rm: RoundingMode::DYN,
453 }),
454 ("s", "lu") => Ok(Instruction::FCVTSLU {
455 dest: FRegister::try_from(operands[0])?,
456 src: IRegister::from_string(operands[1])?,
457 rm: RoundingMode::DYN,
458 }),
459 _ => Err("invalid fcvt suffixes".to_owned()),
460 }
461 } else if mnemonics.len() == 4 {
462 match (mnemonics[1], mnemonics[2]) {
463 ("w", "s") => Ok(Instruction::FCVTWS {
464 dest: IRegister::from_string(operands[0])?,
465 src: FRegister::try_from(operands[1])?,
466 rm: RoundingMode::from_str(mnemonics[3])?,
467 }),
468 ("wu", "s") => Ok(Instruction::FCVTWUS {
469 dest: IRegister::from_string(operands[0])?,
470 src: FRegister::try_from(operands[1])?,
471 rm: RoundingMode::from_str(mnemonics[3])?,
472 }),
473 ("s", "w") => Ok(Instruction::FCVTSW {
474 dest: FRegister::try_from(operands[0])?,
475 src: IRegister::from_string(operands[1])?,
476 rm: RoundingMode::from_str(mnemonics[3])?,
477 }),
478 ("s", "wu") => Ok(Instruction::FCVTSWU {
479 dest: FRegister::try_from(operands[0])?,
480 src: IRegister::from_string(operands[1])?,
481 rm: RoundingMode::from_str(mnemonics[3])?,
482 }),
483 ("l", "s") => Ok(Instruction::FCVTLS {
484 dest: IRegister::from_string(operands[0])?,
485 src: FRegister::try_from(operands[1])?,
486 rm: RoundingMode::from_str(mnemonics[3])?,
487 }),
488 ("lu", "s") => Ok(Instruction::FCVTLUS {
489 dest: IRegister::from_string(operands[0])?,
490 src: FRegister::try_from(operands[1])?,
491 rm: RoundingMode::from_str(mnemonics[3])?,
492 }),
493 ("s", "l") => Ok(Instruction::FCVTSL {
494 dest: FRegister::try_from(operands[0])?,
495 src: IRegister::from_string(operands[1])?,
496 rm: RoundingMode::from_str(mnemonics[3])?,
497 }),
498 ("s", "lu") => Ok(Instruction::FCVTSLU {
499 dest: FRegister::try_from(operands[0])?,
500 src: IRegister::from_string(operands[1])?,
501 rm: RoundingMode::from_str(mnemonics[3])?,
502 }),
503 _ => Err("invalid fcvt suffixes".to_owned()),
504 }
505 } else {
506 Err("fcvt should have 2 or 3 suffixes".to_owned())
507 }
508 }
509 "fmv" => {
510 if operands.len() != 2 {
511 Err("fmv requires 2 operands".to_owned())
512 } else if mnemonics.len() == 3 {
513 match (mnemonics[1], mnemonics[2]) {
514 ("x", "w") => Ok(Instruction::FMVXW {
515 dest: IRegister::from_string(operands[0])?,
516 src: FRegister::try_from(operands[1])?,
517 }),
518 ("w", "x") => Ok(Instruction::FMVWX {
519 dest: FRegister::try_from(operands[0])?,
520 src: IRegister::from_string(operands[1])?,
521 }),
522 _ => Err("invalid fmv suffixes".to_owned()),
523 }
524 } else {
525 Err("fmv requires 2 suffixes".to_owned())
526 }
527 }
528 "feq" => {
529 if operands.len() != 3 {
530 Err("feq requires 3 operands".to_owned())
531 } else if mnemonics.len() == 2 {
532 match mnemonics[1] {
533 "s" => Ok(Instruction::FEQS {
534 dest: IRegister::from_string(operands[0])?,
535 src1: FRegister::try_from(operands[1])?,
536 src2: FRegister::try_from(operands[2])?,
537 }),
538 "d" => todo!(),
539 "q" => todo!(),
540 "h" => todo!(),
541 _ => Err("feq requires a suffix {s,d}".to_owned()),
542 }
543 } else {
544 Err("feq requires a suffix {s,d}".to_owned())
545 }
546 }
547 "flt" => {
548 if operands.len() != 3 {
549 Err("flt requires 3 operands".to_owned())
550 } else if mnemonics.len() == 2 {
551 match mnemonics[1] {
552 "s" => Ok(Instruction::FLTS {
553 dest: IRegister::from_string(operands[0])?,
554 src1: FRegister::try_from(operands[1])?,
555 src2: FRegister::try_from(operands[2])?,
556 }),
557 "d" => todo!(),
558 "q" => todo!(),
559 "h" => todo!(),
560 _ => Err("flt requires a suffix {s,d}".to_owned()),
561 }
562 } else {
563 Err("flt requires a suffix {s,d}".to_owned())
564 }
565 }
566 "fle" => {
567 if operands.len() != 3 {
568 Err("fle requires 3 operands".to_owned())
569 } else if mnemonics.len() == 2 {
570 match mnemonics[1] {
571 "s" => Ok(Instruction::FLES {
572 dest: IRegister::from_string(operands[0])?,
573 src1: FRegister::try_from(operands[1])?,
574 src2: FRegister::try_from(operands[2])?,
575 }),
576 "d" => todo!(),
577 "q" => todo!(),
578 "h" => todo!(),
579 _ => Err("fle requires a suffix {s,d}".to_owned()),
580 }
581 } else {
582 Err("fle requires a suffix {s,d}".to_owned())
583 }
584 }
585 "fclass" => {
586 if operands.len() != 2 {
587 Err("fclass requires 2 operands".to_owned())
588 } else if mnemonics.len() == 2 {
589 match mnemonics[1] {
590 "s" => Ok(Instruction::FCLASSS {
591 dest: IRegister::from_string(operands[0])?,
592 src: FRegister::try_from(operands[1])?,
593 }),
594 "d" => todo!(),
595 "q" => todo!(),
596 "h" => todo!(),
597 _ => Err("fle requires a suffix {s,d}".to_owned()),
598 }
599 } else {
600 Err("fle requires a suffix {s,d}".to_owned())
601 }
602 }
603 "csrrw" => {
604 if operands.len() != 3 {
605 Err("csrrw requires 3 operands".to_owned())
606 } else {
607 Ok(Instruction::CSRRW {
608 dest: IRegister::from_string(operands[0])?,
609 src: IRegister::from_string(operands[2])?,
610 csr: CSR::try_from(parse_int(operands[1])?)?,
611 })
612 }
613 }
614 "csrrs" => {
615 if operands.len() != 3 {
616 Err("csrrs requires 3 operands".to_owned())
617 } else {
618 Ok(Instruction::CSRRS {
619 dest: IRegister::from_string(operands[0])?,
620 src: IRegister::from_string(operands[2])?,
621 csr: CSR::try_from(parse_int(operands[1])?)?,
622 })
623 }
624 }
625 "csrrc" => {
626 if operands.len() != 3 {
627 Err("csrrc requires 3 operands".to_owned())
628 } else {
629 Ok(Instruction::CSRRC {
630 dest: IRegister::from_string(operands[0])?,
631 src: IRegister::from_string(operands[2])?,
632 csr: CSR::try_from(parse_int(operands[1])?)?,
633 })
634 }
635 }
636 "csrrwi" => {
637 if operands.len() != 3 {
638 Err("csrrwi requires 3 operands".to_owned())
639 } else {
640 Ok(Instruction::CSRRWI {
641 dest: IRegister::from_string(operands[0])?,
642 imm: CSRImmediate::try_from(parse_int(operands[2])?)?,
643 csr: CSR::try_from(parse_int(operands[1])?)?,
644 })
645 }
646 }
647 "csrrsi" => {
648 if operands.len() != 3 {
649 Err("csrrsi requires 3 operands".to_owned())
650 } else {
651 Ok(Instruction::CSRRSI {
652 dest: IRegister::from_string(operands[0])?,
653 imm: CSRImmediate::try_from(parse_int(operands[2])?)?,
654 csr: CSR::try_from(parse_int(operands[1])?)?,
655 })
656 }
657 }
658 "csrrci" => {
659 if operands.len() != 3 {
660 Err("csrrci requires 3 operands".to_owned())
661 } else {
662 Ok(Instruction::CSRRCI {
663 dest: IRegister::from_string(operands[0])?,
664 imm: CSRImmediate::try_from(parse_int(operands[2])?)?,
665 csr: CSR::try_from(parse_int(operands[1])?)?,
666 })
667 }
668 }
669 _ => Err(format!("unknown mnemonic: {}", mnemonic)),
670 };
671 x.map(AssemblyResult::I)
672 }
673}
674
675fn compressed_assemble(mnemonics: &[&str], operands: Vec<&str>) -> Result<CInstruction, String> {
676 match mnemonics[0] {
677 "addi4spn" => {
678 if operands.len() != 2 {
679 Err("c.addi4spn requires 2 operands".to_owned())
680 } else {
681 Ok(CInstruction::ADDI4SPN {
682 dest: CIRegister::try_from(operands[0])?,
683 imm: CWideImmediate::try_from(parse_int(operands[1])?)?,
684 })
685 }
686 }
687 "fld" => {
688 if operands.len() != 2 {
689 Err("c.fld requires 2 operands".to_owned())
690 } else {
691 let (base, imm) = parse_address_expression_compressed(operands[1])?;
692 Ok(CInstruction::FLD {
693 dest: CFRegister::try_from(operands[0])?,
694 base,
695 offset: CDImmediate::try_from(imm)?,
696 })
697 }
698 }
699 "lw" => {
700 if operands.len() != 2 {
701 Err("c.lw requires 2 operands".to_owned())
702 } else {
703 let (base, imm) = parse_address_expression_compressed(operands[1])?;
704 Ok(CInstruction::LW {
705 dest: CIRegister::try_from(operands[0])?,
706 base,
707 offset: CWImmediate::try_from(imm)?,
708 })
709 }
710 }
711 "ld" => {
712 if operands.len() != 2 {
713 Err("c.ld requires 2 operands".to_owned())
714 } else {
715 let (base, imm) = parse_address_expression_compressed(operands[1])?;
716 Ok(CInstruction::LD {
717 dest: CIRegister::try_from(operands[0])?,
718 base,
719 offset: CDImmediate::try_from(imm)?,
720 })
721 }
722 }
723 "fsd" => {
724 if operands.len() != 2 {
725 Err("c.fsd requires 2 operands".to_owned())
726 } else {
727 let (base, imm) = parse_address_expression_compressed(operands[1])?;
728 Ok(CInstruction::FSD {
729 src: CFRegister::try_from(operands[0])?,
730 base,
731 offset: CDImmediate::try_from(imm)?,
732 })
733 }
734 }
735 "sw" => {
736 if operands.len() != 2 {
737 Err("c.sw requires 2 operands".to_owned())
738 } else {
739 let (base, imm) = parse_address_expression_compressed(operands[1])?;
740 Ok(CInstruction::SW {
741 src: CIRegister::try_from(operands[0])?,
742 base,
743 offset: CWImmediate::try_from(imm)?,
744 })
745 }
746 }
747 "sd" => {
748 if operands.len() != 2 {
749 Err("c.sd requires 2 operands".to_owned())
750 } else {
751 let (base, imm) = parse_address_expression_compressed(operands[1])?;
752 Ok(CInstruction::SD {
753 src: CIRegister::try_from(operands[0])?,
754 base,
755 offset: CDImmediate::try_from(imm)?,
756 })
757 }
758 }
759 "addi" => ci_assemble!(ADDI),
760 "addiw" => ci_assemble!(ADDIW),
761 "li" => ci_assemble!(LI),
762 "addi16sp" => {
763 if operands.len() != 1 {
764 Err("c.addi16sp requires 1 operands".to_owned())
765 } else {
766 let i = parse_int(operands[0])?;
767
768 Ok(CInstruction::ADDI16SP {
769 imm: C16SPImmediate::try_from(i)?,
770 })
771 }
772 }
773 "lui" => ci_assemble!(LUI),
774 "srli" => {
775 if operands.len() != 2 {
776 Err("c.srli requires 2 operands".to_owned())
777 } else {
778 Ok(CInstruction::SRLI {
779 dest: CIRegister::try_from(operands[0])?,
780 shamt: CShamt::try_from(parse_int(operands[1])?)?,
781 })
782 }
783 }
784 "srai" => {
785 if operands.len() != 2 {
786 Err("c.srai requires 2 operands".to_owned())
787 } else {
788 Ok(CInstruction::SRAI {
789 dest: CIRegister::try_from(operands[0])?,
790 shamt: CShamt::try_from(parse_int(operands[1])?)?,
791 })
792 }
793 }
794 "andi" => {
795 if operands.len() != 2 {
796 Err("c.andi requires 2 operands".to_owned())
797 } else {
798 Ok(CInstruction::ANDI {
799 dest: CIRegister::try_from(operands[0])?,
800 imm: CIImmediate::try_from(parse_int(operands[1])?)?,
801 })
802 }
803 }
804 "sub" => cr_assemble!(SUB),
805 "xor" => cr_assemble!(XOR),
806 "or" => cr_assemble!(OR),
807 "and" => cr_assemble!(AND),
808 "subw" => cr_assemble!(SUBW),
809 "addw" => cr_assemble!(ADDW),
810 "j" => {
811 if operands.len() != 1 {
812 Err("c.j requires 1 operand".to_owned())
813 } else {
814 Ok(CInstruction::J {
815 offset: CJImmediate::try_from(parse_int(operands[0])?)?,
816 })
817 }
818 }
819 "beqz" => {
820 if operands.len() != 2 {
821 Err("c.beqz requires 2 operands".to_owned())
822 } else {
823 Ok(CInstruction::BEQZ {
824 src: CIRegister::try_from(operands[0])?,
825 offset: CBImmediate::try_from(parse_int(operands[1])?)?,
826 })
827 }
828 }
829 "bnez" => {
830 if operands.len() != 2 {
831 Err("c.bne requires 2 operands".to_owned())
832 } else {
833 Ok(CInstruction::BNEZ {
834 src: CIRegister::try_from(operands[0])?,
835 offset: CBImmediate::try_from(parse_int(operands[1])?)?,
836 })
837 }
838 }
839 "slli" => {
840 if operands.len() != 2 {
841 Err("c.slli requires 2 operands".to_owned())
842 } else {
843 Ok(CInstruction::SLLI {
844 dest: IRegister::from_string(operands[0])?,
845 shamt: CShamt::try_from(parse_int(operands[1])?)?,
846 })
847 }
848 }
849 "fldsp" => {
850 if operands.len() != 2 {
851 Err("c.fldsp requires 2 operands".to_owned())
852 } else {
853 Ok(CInstruction::FLDSP {
854 dest: FRegister::try_from(operands[0])?,
855 offset: CDSPImmediate::try_from(parse_int(operands[1])?)?,
856 })
857 }
858 }
859 "ldsp" => {
860 if operands.len() != 2 {
861 Err("c.ldsp requires 2 operands".to_owned())
862 } else {
863 Ok(CInstruction::LDSP {
864 dest: IRegister::from_string(operands[0])?,
865 offset: CDSPImmediate::try_from(parse_int(operands[1])?)?,
866 })
867 }
868 }
869 "lwsp" => {
870 if operands.len() != 2 {
871 Err("c.lwsp requires 2 operands".to_owned())
872 } else {
873 Ok(CInstruction::LWSP {
874 dest: IRegister::from_string(operands[0])?,
875 offset: CWSPImmediate::try_from(parse_int(operands[1])?)?,
876 })
877 }
878 }
879 "jr" => {
880 if operands.len() != 1 {
881 Err("c.jr requires 1 operand".to_owned())
882 } else {
883 Ok(CInstruction::JR {
884 src: IRegister::from_string(operands[0])?,
885 })
886 }
887 }
888 "jalr" => {
889 if operands.len() != 1 {
890 Err("c.jalr requires 1 operand".to_owned())
891 } else {
892 Ok(CInstruction::JALR {
893 src: IRegister::from_string(operands[0])?,
894 })
895 }
896 }
897 "ebreak" => {
898 if operands.len() != 0 {
899 Err("c.jr requires 0 operands".to_owned())
900 } else {
901 Ok(CInstruction::EBREAK)
902 }
903 }
904 "add" => {
905 if operands.len() != 2 {
906 Err("c.add requires 2 operands".to_owned())
907 } else {
908 Ok(CInstruction::ADD {
909 dest: IRegister::from_string(operands[0])?,
910 src: IRegister::from_string(operands[1])?,
911 })
912 }
913 }
914 "fsdsp" => {
915 if operands.len() != 2 {
916 Err("c.fsdsp requires 2 operands".to_owned())
917 } else {
918 Ok(CInstruction::FSDSP {
919 src: FRegister::try_from(operands[0])?,
920 offset: CSDSPImmediate::try_from(parse_int(operands[1])?)?,
921 })
922 }
923 }
924 "swsp" => {
925 if operands.len() != 2 {
926 Err("c.swsp requires 2 operands".to_owned())
927 } else {
928 Ok(CInstruction::SWSP {
929 src: IRegister::from_string(operands[0])?,
930 offset: CSWSPImmediate::try_from(parse_int(operands[1])?)?,
931 })
932 }
933 }
934 "sdsp" => {
935 if operands.len() != 2 {
936 Err("c.sdsp requires 2 operands".to_owned())
937 } else {
938 Ok(CInstruction::SDSP {
939 src: IRegister::from_string(operands[0])?,
940 offset: CSDSPImmediate::try_from(parse_int(operands[1])?)?,
941 })
942 }
943 }
944 "mv" => {
945 if operands.len() != 2 {
946 Err("c.mv requires 2 operands".to_owned())
947 } else {
948 Ok(CInstruction::MV {
949 dest: IRegister::from_string(operands[0])?,
950 src: IRegister::from_string(operands[1])?,
951 })
952 }
953 }
954 _ => Err(format!(
955 "unknown compressed instruction mnemonic: {}",
956 mnemonics[0]
957 )),
958 }
959}