1use ckb_vm_definitions::instructions::{self as insts};
2use ckb_vm_definitions::registers::{RA, ZERO};
3
4use crate::instructions::{
5 a, b, extract_opcode, i, instruction_length, m, rvc, set_instruction_length_n, Instruction,
6 InstructionFactory, Itype, R4type, R5type, Register, Rtype, Utype,
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 {
632 if let Some(fuze_imm) =
633 head_inst.immediate_s().checked_add(next_inst.immediate_s())
634 {
635 let fuze_inst =
636 Utype::new_s(insts::OP_FAR_JUMP_REL, RA, fuze_imm);
637 let next_size = instruction_length(next_instruction);
638 let fuze_size = head_size + next_size;
639 result = set_instruction_length_n(fuze_inst.0, fuze_size);
640 }
641 }
642 } else {
643 if next_inst.rs1() == head_inst.rd() && next_inst.rd() == RA {
644 let fuze_imm = head_inst
645 .immediate_s()
646 .wrapping_add(next_inst.immediate_s());
647 let fuze_inst = Utype::new_s(insts::OP_FAR_JUMP_REL, RA, fuze_imm);
648 let next_size = instruction_length(next_instruction);
649 let fuze_size = head_size + next_size;
650 result = set_instruction_length_n(fuze_inst.0, fuze_size);
651 }
652 }
653 Ok(result)
654 }
655 insts::OP_ADDI if self.version >= VERSION2 => {
656 let next_inst = Itype(next_instruction);
657 let mut result = head_instruction;
658
659 if next_inst.rs1() == next_inst.rd() && next_inst.rd() == head_inst.rd() {
660 if let Ok(pc) = i32::try_from(pc) {
661 if let Some(fuze_imm) = head_inst
662 .immediate_s()
663 .checked_add(next_inst.immediate_s())
664 .and_then(|s| s.checked_add(pc))
665 {
666 let fuze_inst = Utype::new_s(
667 insts::OP_CUSTOM_LOAD_IMM,
668 head_inst.rd(),
669 fuze_imm,
670 );
671 let next_size = instruction_length(next_instruction);
672 let fuze_size = head_size + next_size;
673 result = set_instruction_length_n(fuze_inst.0, fuze_size);
674 }
675 }
676 }
677 Ok(result)
678 }
679 _ => Ok(head_instruction),
680 }
681 }
682 insts::OP_MULH => {
683 let head_inst = Rtype(head_instruction);
684 let head_size = instruction_length(head_instruction);
685 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
686 Ok(ni) => ni,
687 Err(_) => return Ok(head_instruction),
688 };
689 let next_opcode = extract_opcode(next_instruction);
690 match next_opcode {
691 insts::OP_MUL => {
692 let next_inst = Rtype(next_instruction);
693 if head_inst.rd() != head_inst.rs1()
694 && head_inst.rd() != head_inst.rs2()
695 && head_inst.rs1() == next_inst.rs1()
696 && head_inst.rs2() == next_inst.rs2()
697 && head_inst.rd() != next_inst.rd()
698 {
699 let next_size = instruction_length(next_instruction);
700 let fuze_inst = R4type::new(
701 insts::OP_WIDE_MUL,
702 head_inst.rd(),
703 head_inst.rs1(),
704 head_inst.rs2(),
705 next_inst.rd(),
706 );
707 let fuze_size = head_size + next_size;
708 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
709 } else {
710 Ok(head_instruction)
711 }
712 }
713 _ => Ok(head_instruction),
714 }
715 }
716 insts::OP_MULHU => {
717 let head_inst = Rtype(head_instruction);
718 let head_size = instruction_length(head_instruction);
719 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
720 Ok(ni) => ni,
721 Err(_) => return Ok(head_instruction),
722 };
723 let next_opcode = extract_opcode(next_instruction);
724 match next_opcode {
725 insts::OP_MUL => {
726 let next_inst = Rtype(next_instruction);
727 if head_inst.rd() != head_inst.rs1()
728 && head_inst.rd() != head_inst.rs2()
729 && head_inst.rs1() == next_inst.rs1()
730 && head_inst.rs2() == next_inst.rs2()
731 && head_inst.rd() != next_inst.rd()
732 {
733 let next_size = instruction_length(next_instruction);
734 let fuze_inst = R4type::new(
735 insts::OP_WIDE_MULU,
736 head_inst.rd(),
737 head_inst.rs1(),
738 head_inst.rs2(),
739 next_inst.rd(),
740 );
741 let fuze_size = head_size + next_size;
742 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
743 } else {
744 Ok(head_instruction)
745 }
746 }
747 _ => Ok(head_instruction),
748 }
749 }
750 insts::OP_MULHSU => {
751 let head_inst = Rtype(head_instruction);
752 let head_size = instruction_length(head_instruction);
753 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
754 Ok(ni) => ni,
755 Err(_) => return Ok(head_instruction),
756 };
757 let next_opcode = extract_opcode(next_instruction);
758 match next_opcode {
759 insts::OP_MUL => {
760 let next_inst = Rtype(next_instruction);
761 if head_inst.rd() != head_inst.rs1()
762 && head_inst.rd() != head_inst.rs2()
763 && head_inst.rs1() == next_inst.rs1()
764 && head_inst.rs2() == next_inst.rs2()
765 && head_inst.rd() != next_inst.rd()
766 {
767 let next_size = instruction_length(next_instruction);
768 let fuze_inst = R4type::new(
769 insts::OP_WIDE_MULSU,
770 head_inst.rd(),
771 head_inst.rs1(),
772 head_inst.rs2(),
773 next_inst.rd(),
774 );
775 let fuze_size = head_size + next_size;
776 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
777 } else {
778 Ok(head_instruction)
779 }
780 }
781 _ => Ok(head_instruction),
782 }
783 }
784 insts::OP_DIV => {
785 let head_inst = Rtype(head_instruction);
786 let head_size = instruction_length(head_instruction);
787 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
788 Ok(ni) => ni,
789 Err(_) => return Ok(head_instruction),
790 };
791 let next_opcode = extract_opcode(next_instruction);
792 match next_opcode {
793 insts::OP_REM => {
794 let next_inst = Rtype(next_instruction);
795 if head_inst.rd() != head_inst.rs1()
796 && head_inst.rd() != head_inst.rs2()
797 && head_inst.rs1() == next_inst.rs1()
798 && head_inst.rs2() == next_inst.rs2()
799 && head_inst.rd() != next_inst.rd()
800 {
801 let next_size = instruction_length(next_instruction);
802 let fuze_inst = R4type::new(
803 insts::OP_WIDE_DIV,
804 head_inst.rd(),
805 head_inst.rs1(),
806 head_inst.rs2(),
807 next_inst.rd(),
808 );
809 let fuze_size = head_size + next_size;
810 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
811 } else {
812 Ok(head_instruction)
813 }
814 }
815 _ => Ok(head_instruction),
816 }
817 }
818 insts::OP_DIVU => {
819 let head_inst = Rtype(head_instruction);
820 let head_size = instruction_length(head_instruction);
821 let next_instruction = match self.decode_raw(memory, pc + head_size as u64) {
822 Ok(ni) => ni,
823 Err(_) => return Ok(head_instruction),
824 };
825 let next_opcode = extract_opcode(next_instruction);
826 match next_opcode {
827 insts::OP_REMU => {
828 let next_inst = Rtype(next_instruction);
829 if head_inst.rd() != head_inst.rs1()
830 && head_inst.rd() != head_inst.rs2()
831 && head_inst.rs1() == next_inst.rs1()
832 && head_inst.rs2() == next_inst.rs2()
833 && head_inst.rd() != next_inst.rd()
834 {
835 let next_size = instruction_length(next_instruction);
836 let fuze_inst = R4type::new(
837 insts::OP_WIDE_DIVU,
838 head_inst.rd(),
839 head_inst.rs1(),
840 head_inst.rs2(),
841 next_inst.rd(),
842 );
843 let fuze_size = head_size + next_size;
844 Ok(set_instruction_length_n(fuze_inst.0, fuze_size))
845 } else {
846 Ok(head_instruction)
847 }
848 }
849 _ => Ok(head_instruction),
850 }
851 }
852 _ => Ok(head_instruction),
853 }
854 }
855
856 pub fn decode<M: Memory>(&mut self, memory: &mut M, pc: u64) -> Result<Instruction, Error> {
857 if self.mop {
858 self.decode_mop(memory, pc)
859 } else {
860 self.decode_raw(memory, pc)
861 }
862 }
863
864 pub fn reset_instructions_cache(&mut self) {
865 self.instructions_cache = vec![(u64::MAX, 0); INSTRUCTION_CACHE_SIZE];
866 }
867}
868
869pub fn build_decoder<R: Register>(isa: u8, version: u32) -> Decoder {
870 let mut decoder = Decoder::new(isa & ISA_MOP != 0, version);
871 decoder.add_instruction_factory(rvc::factory::<R>);
872 decoder.add_instruction_factory(i::factory::<R>);
873 decoder.add_instruction_factory(m::factory::<R>);
874 if isa & ISA_B != 0 {
875 decoder.add_instruction_factory(b::factory::<R>);
876 }
877 if isa & ISA_A != 0 {
878 decoder.add_instruction_factory(a::factory::<R>);
879 }
880 decoder
881}