1use ckb_vm_definitions::instructions::{self as insts};
2use ckb_vm_definitions::registers::{RA, ZERO};
3
4use crate::instructions::{
5 Instruction, InstructionFactory, Itype, R4type, R5type, Register, Rtype, Utype, a, b,
6 extract_opcode, i, instruction_length, m, rvc, set_instruction_length_n,
7};
8use crate::machine::VERSION2;
9use crate::memory::Memory;
10use crate::{Error, ISA_A, ISA_B, ISA_MOP, RISCV_PAGESIZE};
11
12const RISCV_PAGESIZE_MASK: u64 = RISCV_PAGESIZE as u64 - 1;
13const INSTRUCTION_CACHE_SIZE: usize = 2048;
14
15pub struct Decoder {
16 factories: Vec<InstructionFactory>,
17 mop: bool,
18 version: u32,
19 instructions_cache: Vec<(u64, u64)>,
25}
26
27impl Decoder {
28 pub fn new(mop: bool, version: u32) -> Decoder {
29 Decoder {
30 factories: vec![],
31 mop,
32 version,
33 instructions_cache: vec![(u64::MAX as u64, 0); INSTRUCTION_CACHE_SIZE],
34 }
35 }
36
37 pub fn add_instruction_factory(&mut self, factory: InstructionFactory) {
38 self.factories.push(factory);
39 }
40
41 fn decode_bits<M: Memory>(&self, memory: &mut M, pc: u64) -> Result<u32, Error> {
76 if pc & RISCV_PAGESIZE_MASK < RISCV_PAGESIZE_MASK - 1 {
79 let mut instruction_bits = memory.execute_load32(pc)?;
80 if instruction_bits & 0x3 != 0x3 {
81 instruction_bits &= 0xffff;
82 }
83 Ok(instruction_bits)
84 } else {
85 let mut instruction_bits = u32::from(memory.execute_load16(pc)?);
86 if instruction_bits & 0x3 == 0x3 {
87 instruction_bits |= u32::from(memory.execute_load16(pc + 2)?) << 16;
88 }
89 Ok(instruction_bits)
90 }
91 }
92
93 pub fn decode_raw<M: Memory>(&mut self, memory: &mut M, pc: u64) -> Result<Instruction, Error> {
94 if pc as usize >= memory.memory_size() {
97 return Err(Error::MemOutOfBound);
98 }
99 let instruction_cache_key = {
100 let pc = pc >> 1;
102 ((pc >> 5) ^ (pc << 1)) as usize % INSTRUCTION_CACHE_SIZE
110 };
111 let cached_instruction = self.instructions_cache[instruction_cache_key];
112 if cached_instruction.0 == pc {
113 return Ok(cached_instruction.1);
114 }
115 let instruction_bits = self.decode_bits(memory, pc)?;
116 for factory in &self.factories {
117 if let Some(instruction) = factory(instruction_bits, self.version) {
118 self.instructions_cache[instruction_cache_key] = (pc, instruction);
119 return Ok(instruction);
120 }
121 }
122 Err(Error::InvalidInstruction {
123 pc,
124 instruction: instruction_bits,
125 })
126 }
127
128 pub fn decode_mop<M: Memory>(&mut self, memory: &mut M, pc: u64) -> Result<Instruction, Error> {
136 let head_instruction = self.decode_raw(memory, pc)?;
137 let head_opcode = extract_opcode(head_instruction);
138 match head_opcode {
139 insts::OP_ADD => {
140 let rule_adc = |decoder: &mut Self,
141 memory: &mut M|
142 -> Result<Option<Instruction>, Error> {
143 let head_inst = Rtype(head_instruction);
144 let head_size = instruction_length(head_instruction);
145 if head_inst.rd() != head_inst.rs1() || head_inst.rs1() == head_inst.rs2() {
146 return Ok(None);
147 }
148 let next_instruction = decoder.decode_raw(memory, pc + head_size as u64)?;
149 let next_opcode = extract_opcode(next_instruction);
150 if next_opcode != insts::OP_SLTU {
151 return Ok(None);
152 }
153 let next_inst = Rtype(next_instruction);
154 let next_size = instruction_length(next_instruction);
155 if next_inst.rd() != head_inst.rs2()
156 || head_inst.rs2() != next_inst.rs2()
157 || next_inst.rs1() != head_inst.rs1()
158 {
159 return Ok(None);
160 }
161 let neck_instruction =
162 decoder.decode_raw(memory, pc + head_size as u64 + next_size as u64)?;
163 let neck_opcode = extract_opcode(neck_instruction);
164 if neck_opcode != insts::OP_ADD {
165 return Ok(None);
166 }
167 let neck_inst = Rtype(neck_instruction);
168 let neck_size = instruction_length(neck_instruction);
169 if neck_inst.rd() != neck_inst.rs1()
170 || neck_inst.rs1() != next_inst.rs1()
171 || neck_inst.rs2() == head_inst.rs1()
172 || neck_inst.rs2() == head_inst.rs2()
173 {
174 return Ok(None);
175 }
176 let body_instruction = decoder.decode_raw(
177 memory,
178 pc + head_size as u64 + next_size as u64 + neck_size as u64,
179 )?;
180 let body_opcode = extract_opcode(body_instruction);
181 if body_opcode != insts::OP_SLTU {
182 return Ok(None);
183 }
184 let body_inst = Rtype(body_instruction);
185 let body_size = instruction_length(body_instruction);
186 if body_inst.rd() != body_inst.rs2()
187 || body_inst.rs2() != neck_inst.rs2()
188 || body_inst.rs1() != neck_inst.rs1()
189 {
190 return Ok(None);
191 }
192 let tail_instruction = decoder.decode_raw(
193 memory,
194 pc + head_size as u64
195 + next_size as u64
196 + neck_size as u64
197 + body_size as u64,
198 )?;
199 let tail_opcode = extract_opcode(tail_instruction);
200 if tail_opcode != insts::OP_OR {
201 return Ok(None);
202 }
203 let tail_inst = Rtype(tail_instruction);
204 let tail_size = instruction_length(tail_instruction);
205 if tail_inst.rd() != tail_inst.rs1()
206 || tail_inst.rs1() != head_inst.rs2()
207 || tail_inst.rs2() != body_inst.rs2()
208 {
209 return Ok(None);
210 }
211 if head_inst.rd() == ZERO || next_inst.rd() == ZERO || body_inst.rd() == ZERO {
212 return Ok(None);
213 }
214 let fuze_inst = Rtype::new(
215 insts::OP_ADC,
216 head_inst.rd(),
217 next_inst.rd(),
218 body_inst.rd(),
219 );
220 let fuze_size = head_size + next_size + neck_size + body_size + tail_size;
221 Ok(Some(set_instruction_length_n(fuze_inst.0, fuze_size)))
222 };
223 let rule_add3 =
224 |decoder: &mut Self, memory: &mut M| -> Result<Option<Instruction>, Error> {
225 if decoder.version < VERSION2 {
226 return Ok(None);
227 }
228
229 let i0 = Rtype(head_instruction);
230 let i0_size = instruction_length(head_instruction);
231
232 let (i1, i1_size) = {
233 let i1 = decoder.decode_raw(memory, pc + i0_size as u64)?;
234 let i1_opcode = extract_opcode(i1);
235 if i1_opcode != insts::OP_SLTU {
236 return Ok(None);
237 }
238 (Rtype(i1), instruction_length(i1))
239 };
240
241 let (i2, i2_size) = {
242 let i2 =
243 decoder.decode_raw(memory, pc + i0_size as u64 + i1_size as u64)?;
244 let i2_opcode = extract_opcode(i2);
245 if i2_opcode != insts::OP_ADD {
246 return Ok(None);
247 }
248 (Rtype(i2), instruction_length(i2))
249 };
250
251 let fuze_size = i0_size + i1_size + i2_size;
252
253 {
254 let r0 = i0.rd();
264 let r1 = i0.rs1();
265 let r2 = i1.rd();
266 let r3 = i2.rd();
267 let r4 = i2.rs2();
268
269 if i0.rd() == r0
270 && i0.rs1() == r1
271 && i0.rs2() == r0
272 && i1.rd() == r2
273 && i1.rs1() == r0
274 && i1.rs2() == r1
275 && i2.rd() == r3
276 && i2.rs1() == r2
277 && i2.rs2() == r4
278 && r0 != r1
279 && r0 != r4
280 && r2 != r4
281 && r0 != ZERO
282 && r2 != ZERO
283 {
284 let fuze_inst = R5type::new(insts::OP_ADD3A, r0, r1, r2, r3, r4);
285 return Ok(Some(set_instruction_length_n(fuze_inst.0, fuze_size)));
286 }
287 }
288
289 {
290 let r0 = i0.rd();
300 let r1 = i0.rs1();
301 let r2 = i0.rs2();
302 let r3 = i2.rd();
303 let r4 = i2.rs2();
304
305 if i0.rd() == r0
306 && i0.rs1() == r1
307 && i0.rs2() == r2
308 && i1.rd() == r1
309 && i1.rs1() == r0
310 && i1.rs2() == r1
311 && i2.rd() == r3
312 && i2.rs1() == r1
313 && i2.rs2() == r4
314 && r0 != r1
315 && r0 != r4
316 && r1 != r4
317 && r0 != ZERO
318 && r1 != ZERO
319 {
320 let fuze_inst = R5type::new(insts::OP_ADD3B, r0, r1, r2, r3, r4);
321 return Ok(Some(set_instruction_length_n(fuze_inst.0, fuze_size)));
322 }
323 }
324 {
325 let r0 = i0.rd();
335 let r1 = i0.rs1();
336 let r2 = i0.rs2();
337 let r3 = i1.rd();
338 let r4 = i2.rs2();
339
340 if i0.rd() == r0
341 && i0.rs1() == r1
342 && i0.rs2() == r2
343 && i1.rd() == r3
344 && i1.rs1() == r0
345 && i1.rs2() == r1
346 && i2.rd() == r3
347 && i2.rs1() == r3
348 && i2.rs2() == r4
349 && r0 != r1
350 && r0 != r4
351 && r3 != r4
352 && r0 != ZERO
353 && r3 != ZERO
354 {
355 let fuze_inst = R5type::new(insts::OP_ADD3C, r0, r1, r2, r3, r4);
356 return Ok(Some(set_instruction_length_n(fuze_inst.0, fuze_size)));
357 }
358 }
359 Ok(None)
360 };
361 let rule_adcs =
362 |decoder: &mut Self, memory: &mut M| -> Result<Option<Instruction>, Error> {
363 if decoder.version < VERSION2 {
374 return Ok(None);
375 }
376
377 let mut i0 = Rtype(head_instruction);
378 let i0_size = instruction_length(head_instruction);
379
380 if i0.rd() == i0.rs1() && i0.rd() != i0.rs2() {
381 i0 = Rtype::new(i0.op(), i0.rd(), i0.rs2(), i0.rs1());
382 }
383
384 let (i1, i1_size) = {
385 let i1 = decoder.decode_raw(memory, pc + i0_size as u64)?;
386 let i1_opcode = extract_opcode(i1);
387 if i1_opcode != insts::OP_SLTU {
388 return Ok(None);
389 }
390 (Rtype(i1), instruction_length(i1))
391 };
392
393 let r0 = i0.rd();
394 let r1 = i0.rs1();
395 let r2 = i0.rs2();
396 let r3 = i1.rd();
397
398 if i0.rd() == r0
399 && i0.rs1() == r1
400 && i0.rs2() == r2
401 && i1.rd() == r3
402 && i1.rs1() == r0
403 && i1.rs2() == r1
404 && r0 != r1
405 && r0 != ZERO
406 {
407 let fuze_inst = R4type::new(insts::OP_ADCS, r0, r1, r2, r3);
408 let fuze_size = i0_size + i1_size;
409 Ok(Some(set_instruction_length_n(fuze_inst.0, fuze_size)))
410 } else {
411 Ok(None)
412 }
413 };
414 if let Ok(Some(i)) = rule_adc(self, memory) {
415 Ok(i)
416 } else if let Ok(Some(i)) = rule_add3(self, memory) {
417 Ok(i)
418 } else if let Ok(Some(i)) = rule_adcs(self, memory) {
419 Ok(i)
420 } else {
421 Ok(head_instruction)
422 }
423 }
424 insts::OP_SUB => {
425 let rule_sbb =
426 |decoder: &mut Self, memory: &mut M| -> Result<Option<Instruction>, Error> {
427 let head_inst = Rtype(head_instruction);
428 let head_size = instruction_length(head_instruction);
429 if head_inst.rd() != head_inst.rs2() || head_inst.rs1() == head_inst.rs2() {
430 return Ok(None);
431 }
432 let next_instruction = decoder.decode_raw(memory, pc + head_size as u64)?;
433 let next_opcode = extract_opcode(next_instruction);
434 if next_opcode != insts::OP_SLTU {
435 return Ok(None);
436 }
437 let next_inst = Rtype(next_instruction);
438 let next_size = instruction_length(next_instruction);
439 if next_inst.rd() == head_inst.rs1()
440 || next_inst.rd() == head_inst.rs2()
441 || next_inst.rs1() != head_inst.rs1()
442 || next_inst.rs2() != next_inst.rs2()
443 {
444 return Ok(None);
445 }
446 let neck_instruction =
447 decoder.decode_raw(memory, pc + head_size as u64 + next_size as u64)?;
448 let neck_opcode = extract_opcode(neck_instruction);
449 if neck_opcode != insts::OP_SUB {
450 return Ok(None);
451 }
452 let neck_inst = Rtype(neck_instruction);
453 let neck_size = instruction_length(neck_instruction);
454 if neck_inst.rd() != head_inst.rs1()
455 || neck_inst.rs1() != head_inst.rs2()
456 || neck_inst.rs2() == head_inst.rs1()
457 || neck_inst.rs2() == head_inst.rs2()
458 || neck_inst.rs2() == next_inst.rd()
459 {
460 return Ok(None);
461 }
462 let body_instruction = decoder.decode_raw(
463 memory,
464 pc + head_size as u64 + next_size as u64 + neck_size as u64,
465 )?;
466 let body_opcode = extract_opcode(body_instruction);
467 if body_opcode != insts::OP_SLTU {
468 return Ok(None);
469 }
470 let body_inst = Rtype(body_instruction);
471 let body_size = instruction_length(body_instruction);
472 if body_inst.rd() != neck_inst.rs2()
473 || body_inst.rs1() != head_inst.rs2()
474 || body_inst.rs2() != head_inst.rs1()
475 {
476 return Ok(None);
477 }
478 let tail_instruction = decoder.decode_raw(
479 memory,
480 pc + head_size as u64
481 + next_size as u64
482 + neck_size as u64
483 + body_size as u64,
484 )?;
485 let tail_opcode = extract_opcode(tail_instruction);
486 if tail_opcode != insts::OP_OR {
487 return Ok(None);
488 }
489 let tail_inst = Rtype(tail_instruction);
490 let tail_size = instruction_length(tail_instruction);
491 if tail_inst.rd() != head_inst.rd()
492 || tail_inst.rs1() != neck_inst.rs2()
493 || tail_inst.rs2() != next_inst.rd()
494 {
495 return Ok(None);
496 }
497 let fuze_inst = R4type::new(
498 insts::OP_SBB,
499 head_inst.rs1(),
500 head_inst.rs2(),
501 neck_inst.rs2(),
502 next_inst.rd(),
503 );
504 if head_inst.rs1() == ZERO
505 || head_inst.rs2() == ZERO
506 || neck_inst.rs2() == ZERO
507 || next_inst.rd() == ZERO
508 {
509 return Ok(None);
510 }
511 let fuze_size = head_size + next_size + neck_size + body_size + tail_size;
512 Ok(Some(set_instruction_length_n(fuze_inst.0, fuze_size)))
513 };
514 let rule_sbbs =
515 |decoder: &mut Self, memory: &mut M| -> Result<Option<Instruction>, Error> {
516 if decoder.version < VERSION2 {
522 return Ok(None);
523 }
524
525 let i0 = Rtype(head_instruction);
526 let i0_size = instruction_length(head_instruction);
527
528 let (i1, i1_size) = {
529 let i1 = decoder.decode_raw(memory, pc + i0_size as u64)?;
530 let i1_opcode = extract_opcode(i1);
531 if i1_opcode != insts::OP_SLTU {
532 return Ok(None);
533 }
534 (Rtype(i1), instruction_length(i1))
535 };
536
537 let r0 = i0.rd();
538 let r1 = i0.rs1();
539 let r2 = i0.rs2();
540 let r3 = i1.rd();
541
542 if i0.rd() == r0
543 && i0.rs1() == r1
544 && i0.rs2() == r2
545 && i1.rd() == r3
546 && i1.rs1() == r1
547 && i1.rs2() == r2
548 && r0 != r1
549 && r0 != r2
550 {
551 let fuze_inst = R4type::new(insts::OP_SBBS, r0, r1, r2, r3);
552 let fuze_size = i0_size + i1_size;
553 Ok(Some(set_instruction_length_n(fuze_inst.0, fuze_size)))
554 } else {
555 Ok(None)
556 }
557 };
558 if let Ok(Some(i)) = rule_sbb(self, memory) {
559 Ok(i)
560 } else if let Ok(Some(i)) = rule_sbbs(self, memory) {
561 Ok(i)
562 } else {
563 Ok(head_instruction)
564 }
565 }
566 insts::OP_LUI => {
567 let head_inst = Utype(head_instruction);
568 let head_size = instruction_length(head_instruction);
569 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
570 Ok(ni) => ni,
571 Err(_) => return Ok(head_instruction),
572 };
573 let next_opcode = extract_opcode(next_instruction);
574 match next_opcode {
575 insts::OP_JALR_VERSION1 => {
576 let next_inst = Itype(next_instruction);
577 let test_condition = if self.version >= VERSION2 {
578 next_inst.rs1() == head_inst.rd()
579 && next_inst.rd() == RA
580 && next_inst.rs1() == RA
581 } else {
582 next_inst.rs1() == head_inst.rd() && next_inst.rd() == RA
583 };
584 if test_condition {
585 let fuze_imm = head_inst
586 .immediate_s()
587 .wrapping_add(next_inst.immediate_s());
588 let fuze_inst = Utype::new_s(insts::OP_FAR_JUMP_ABS, RA, fuze_imm);
589 let next_size = instruction_length(next_instruction);
590 let fuze_size = head_size + next_size;
591 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
592 } else {
593 Ok(head_instruction)
594 }
595 }
596 insts::OP_ADDIW => {
597 let next_inst = Itype(next_instruction);
598 if next_inst.rs1() == next_inst.rd() && next_inst.rd() == head_inst.rd() {
599 let fuze_imm = head_inst
600 .immediate_s()
601 .wrapping_add(next_inst.immediate_s());
602 let fuze_inst =
603 Utype::new_s(insts::OP_CUSTOM_LOAD_IMM, head_inst.rd(), fuze_imm);
604 let next_size = instruction_length(next_instruction);
605 let fuze_size = head_size + next_size;
606 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
607 } else {
608 Ok(head_instruction)
609 }
610 }
611 _ => Ok(head_instruction),
612 }
613 }
614 insts::OP_AUIPC => {
615 let head_inst = Utype(head_instruction);
616 let head_size = instruction_length(head_instruction);
617 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
618 Ok(ni) => ni,
619 Err(_) => return Ok(head_instruction),
620 };
621 let next_opcode = extract_opcode(next_instruction);
622 match next_opcode {
623 insts::OP_JALR_VERSION1 => {
624 let next_inst = Itype(next_instruction);
625 let mut result = head_instruction;
626
627 if self.version >= VERSION2 {
628 if next_inst.rs1() == head_inst.rd()
629 && next_inst.rd() == RA
630 && next_inst.rs1() == RA
631 && let Some(fuze_imm) =
632 head_inst.immediate_s().checked_add(next_inst.immediate_s())
633 {
634 let fuze_inst = Utype::new_s(insts::OP_FAR_JUMP_REL, RA, fuze_imm);
635 let next_size = instruction_length(next_instruction);
636 let fuze_size = head_size + next_size;
637 result = set_instruction_length_n(fuze_inst.0, fuze_size);
638 }
639 } else {
640 if next_inst.rs1() == head_inst.rd() && next_inst.rd() == RA {
641 let fuze_imm = head_inst
642 .immediate_s()
643 .wrapping_add(next_inst.immediate_s());
644 let fuze_inst = Utype::new_s(insts::OP_FAR_JUMP_REL, RA, fuze_imm);
645 let next_size = instruction_length(next_instruction);
646 let fuze_size = head_size + next_size;
647 result = set_instruction_length_n(fuze_inst.0, fuze_size);
648 }
649 }
650 Ok(result)
651 }
652 insts::OP_ADDI if self.version >= VERSION2 => {
653 let next_inst = Itype(next_instruction);
654 let mut result = head_instruction;
655
656 if next_inst.rs1() == next_inst.rd()
657 && next_inst.rd() == head_inst.rd()
658 && let Ok(pc) = i32::try_from(pc)
659 && let Some(fuze_imm) = head_inst
660 .immediate_s()
661 .checked_add(next_inst.immediate_s())
662 .and_then(|s| s.checked_add(pc))
663 {
664 let fuze_inst =
665 Utype::new_s(insts::OP_CUSTOM_LOAD_IMM, head_inst.rd(), fuze_imm);
666 let next_size = instruction_length(next_instruction);
667 let fuze_size = head_size + next_size;
668 result = set_instruction_length_n(fuze_inst.0, fuze_size);
669 }
670 Ok(result)
671 }
672 _ => Ok(head_instruction),
673 }
674 }
675 insts::OP_MULH => {
676 let head_inst = Rtype(head_instruction);
677 let head_size = instruction_length(head_instruction);
678 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
679 Ok(ni) => ni,
680 Err(_) => return Ok(head_instruction),
681 };
682 let next_opcode = extract_opcode(next_instruction);
683 match next_opcode {
684 insts::OP_MUL => {
685 let next_inst = Rtype(next_instruction);
686 if head_inst.rd() != head_inst.rs1()
687 && head_inst.rd() != head_inst.rs2()
688 && head_inst.rs1() == next_inst.rs1()
689 && head_inst.rs2() == next_inst.rs2()
690 && head_inst.rd() != next_inst.rd()
691 {
692 let next_size = instruction_length(next_instruction);
693 let fuze_inst = R4type::new(
694 insts::OP_WIDE_MUL,
695 head_inst.rd(),
696 head_inst.rs1(),
697 head_inst.rs2(),
698 next_inst.rd(),
699 );
700 let fuze_size = head_size + next_size;
701 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
702 } else {
703 Ok(head_instruction)
704 }
705 }
706 _ => Ok(head_instruction),
707 }
708 }
709 insts::OP_MULHU => {
710 let head_inst = Rtype(head_instruction);
711 let head_size = instruction_length(head_instruction);
712 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
713 Ok(ni) => ni,
714 Err(_) => return Ok(head_instruction),
715 };
716 let next_opcode = extract_opcode(next_instruction);
717 match next_opcode {
718 insts::OP_MUL => {
719 let next_inst = Rtype(next_instruction);
720 if head_inst.rd() != head_inst.rs1()
721 && head_inst.rd() != head_inst.rs2()
722 && head_inst.rs1() == next_inst.rs1()
723 && head_inst.rs2() == next_inst.rs2()
724 && head_inst.rd() != next_inst.rd()
725 {
726 let next_size = instruction_length(next_instruction);
727 let fuze_inst = R4type::new(
728 insts::OP_WIDE_MULU,
729 head_inst.rd(),
730 head_inst.rs1(),
731 head_inst.rs2(),
732 next_inst.rd(),
733 );
734 let fuze_size = head_size + next_size;
735 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
736 } else {
737 Ok(head_instruction)
738 }
739 }
740 _ => Ok(head_instruction),
741 }
742 }
743 insts::OP_MULHSU => {
744 let head_inst = Rtype(head_instruction);
745 let head_size = instruction_length(head_instruction);
746 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
747 Ok(ni) => ni,
748 Err(_) => return Ok(head_instruction),
749 };
750 let next_opcode = extract_opcode(next_instruction);
751 match next_opcode {
752 insts::OP_MUL => {
753 let next_inst = Rtype(next_instruction);
754 if head_inst.rd() != head_inst.rs1()
755 && head_inst.rd() != head_inst.rs2()
756 && head_inst.rs1() == next_inst.rs1()
757 && head_inst.rs2() == next_inst.rs2()
758 && head_inst.rd() != next_inst.rd()
759 {
760 let next_size = instruction_length(next_instruction);
761 let fuze_inst = R4type::new(
762 insts::OP_WIDE_MULSU,
763 head_inst.rd(),
764 head_inst.rs1(),
765 head_inst.rs2(),
766 next_inst.rd(),
767 );
768 let fuze_size = head_size + next_size;
769 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
770 } else {
771 Ok(head_instruction)
772 }
773 }
774 _ => Ok(head_instruction),
775 }
776 }
777 insts::OP_DIV => {
778 let head_inst = Rtype(head_instruction);
779 let head_size = instruction_length(head_instruction);
780 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
781 Ok(ni) => ni,
782 Err(_) => return Ok(head_instruction),
783 };
784 let next_opcode = extract_opcode(next_instruction);
785 match next_opcode {
786 insts::OP_REM => {
787 let next_inst = Rtype(next_instruction);
788 if head_inst.rd() != head_inst.rs1()
789 && head_inst.rd() != head_inst.rs2()
790 && head_inst.rs1() == next_inst.rs1()
791 && head_inst.rs2() == next_inst.rs2()
792 && head_inst.rd() != next_inst.rd()
793 {
794 let next_size = instruction_length(next_instruction);
795 let fuze_inst = R4type::new(
796 insts::OP_WIDE_DIV,
797 head_inst.rd(),
798 head_inst.rs1(),
799 head_inst.rs2(),
800 next_inst.rd(),
801 );
802 let fuze_size = head_size + next_size;
803 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
804 } else {
805 Ok(head_instruction)
806 }
807 }
808 _ => Ok(head_instruction),
809 }
810 }
811 insts::OP_DIVU => {
812 let head_inst = Rtype(head_instruction);
813 let head_size = instruction_length(head_instruction);
814 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
815 Ok(ni) => ni,
816 Err(_) => return Ok(head_instruction),
817 };
818 let next_opcode = extract_opcode(next_instruction);
819 match next_opcode {
820 insts::OP_REMU => {
821 let next_inst = Rtype(next_instruction);
822 if head_inst.rd() != head_inst.rs1()
823 && head_inst.rd() != head_inst.rs2()
824 && head_inst.rs1() == next_inst.rs1()
825 && head_inst.rs2() == next_inst.rs2()
826 && head_inst.rd() != next_inst.rd()
827 {
828 let next_size = instruction_length(next_instruction);
829 let fuze_inst = R4type::new(
830 insts::OP_WIDE_DIVU,
831 head_inst.rd(),
832 head_inst.rs1(),
833 head_inst.rs2(),
834 next_inst.rd(),
835 );
836 let fuze_size = head_size + next_size;
837 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
838 } else {
839 Ok(head_instruction)
840 }
841 }
842 _ => Ok(head_instruction),
843 }
844 }
845 _ => Ok(head_instruction),
846 }
847 }
848
849 pub fn decode<M: Memory>(&mut self, memory: &mut M, pc: u64) -> Result<Instruction, Error> {
850 if self.mop {
851 self.decode_mop(memory, pc)
852 } else {
853 self.decode_raw(memory, pc)
854 }
855 }
856
857 pub fn reset_instructions_cache(&mut self) {
858 self.instructions_cache = vec![(u64::MAX, 0); INSTRUCTION_CACHE_SIZE];
859 }
860}
861
862pub fn build_decoder<R: Register>(isa: u8, version: u32) -> Decoder {
863 let mut decoder = Decoder::new(isa & ISA_MOP != 0, version);
864 decoder.add_instruction_factory(rvc::factory::<R>);
865 decoder.add_instruction_factory(i::factory::<R>);
866 decoder.add_instruction_factory(m::factory::<R>);
867 if isa & ISA_B != 0 {
868 decoder.add_instruction_factory(b::factory::<R>);
869 }
870 if isa & ISA_A != 0 {
871 decoder.add_instruction_factory(a::factory::<R>);
872 }
873 decoder
874}