ckb_vm_contrib/
decoder.rs1use ckb_vm::{
2 ckb_vm_definitions::instructions as insts,
3 decoder::Decoder,
4 instructions::{
5 extract_opcode, instruction_length, set_instruction_length_n, Instruction, Itype, Utype,
6 },
7 Error, Memory,
8};
9
10pub struct AuxDecoder {
13 inner: Decoder,
14}
15
16impl AuxDecoder {
17 pub fn new(inner: Decoder) -> Self {
18 Self { inner }
19 }
20
21 pub fn decode<M: Memory>(&mut self, memory: &mut M, pc: u64) -> Result<Instruction, Error> {
22 let head_inst = self.inner.decode(memory, pc)?;
23 match extract_opcode(head_inst) {
24 insts::OP_AUIPC => {
25 let i = Utype(head_inst);
26 let head_len = instruction_length(head_inst);
27 let mut rule_auipc = || -> Result<Option<Instruction>, Error> {
28 let next_instruction = self.inner.decode(memory, pc + head_len as u64)?;
29 let next_opcode = extract_opcode(next_instruction);
30 match next_opcode {
31 insts::OP_ADDI => {
32 let ni = Itype(next_instruction);
33 if i.rd() == ni.rd() && ni.rd() == ni.rs1() {
34 let value = pc
35 .wrapping_add(i64::from(i.immediate_s()) as u64)
36 .wrapping_add(i64::from(ni.immediate_s()) as u64);
37 if let Ok(value) = value.try_into() {
38 return Ok(Some(set_instruction_length_n(
39 Utype::new(insts::OP_CUSTOM_LOAD_IMM, i.rd(), value).0,
40 head_len + instruction_length(next_instruction),
41 )));
42 }
43 }
44 }
45 _ => (),
46 };
47 Ok(None)
48 };
49 if let Ok(Some(i)) = rule_auipc() {
50 return Ok(i);
51 } else {
52 let value = pc.wrapping_add(i64::from(i.immediate_s()) as u64);
53 if let Ok(value) = value.try_into() {
54 return Ok(set_instruction_length_n(
55 Utype::new(insts::OP_CUSTOM_LOAD_UIMM, i.rd(), value).0,
56 head_len,
57 ));
58 }
59 }
60 }
61 _ => (),
62 };
63
64 Ok(head_inst)
65 }
66}