rusty_dex/dex/
instructions.rs

1//! Dalvik instructions
2//!
3//! This module contains the definition of all instructions types, including
4//! special instructions such as `PackedSwitch` which have their payload
5//! at the end of the `CodeItem` of a method.
6
7use crate::dex::opcodes::OpCode;
8use crate::dex::reader::DexReader;
9use crate::error::DexError;
10
11/// `Instruction10t` instruction type
12#[derive(Debug, Clone)]
13pub struct Instruction10t  { opcode: OpCode, length: usize, bytes: [u16; 1] }
14/// `Instruction10x` instruction type
15#[derive(Debug, Clone)]
16pub struct Instruction10x  { opcode: OpCode, length: usize, bytes: [u16; 1] }
17/// `Instruction11n` instruction type
18#[derive(Debug, Clone)]
19pub struct Instruction11n  { opcode: OpCode, length: usize, bytes: [u16; 1] }
20/// `Instruction11x` instruction type
21#[derive(Debug, Clone)]
22pub struct Instruction11x  { opcode: OpCode, length: usize, bytes: [u16; 1] }
23/// `Instruction12x` instruction type
24#[derive(Debug, Clone)]
25pub struct Instruction12x  { opcode: OpCode, length: usize, bytes: [u16; 1] }
26/// `Instruction20t` instruction type
27#[derive(Debug, Clone)]
28pub struct Instruction20t  { opcode: OpCode, length: usize, bytes: [u16; 2] }
29/// `Instruction21c` instruction type
30#[derive(Debug, Clone)]
31pub struct Instruction21c  { opcode: OpCode, length: usize, bytes: [u16; 2] }
32/// `Instruction21h` instruction type
33#[derive(Debug, Clone)]
34pub struct Instruction21h  { opcode: OpCode, length: usize, bytes: [u16; 2] }
35/// `Instruction21s` instruction type
36#[derive(Debug, Clone)]
37pub struct Instruction21s  { opcode: OpCode, length: usize, bytes: [u16; 2] }
38/// `Instruction21t` instruction type
39#[derive(Debug, Clone)]
40pub struct Instruction21t  { opcode: OpCode, length: usize, bytes: [u16; 2] }
41/// `Instruction22b` instruction type
42#[derive(Debug, Clone)]
43pub struct Instruction22b  { opcode: OpCode, length: usize, bytes: [u16; 2] }
44/// `Instruction22c` instruction type
45#[derive(Debug, Clone)]
46pub struct Instruction22c  { opcode: OpCode, length: usize, bytes: [u16; 2] }
47/// `Instruction22s` instruction type
48#[derive(Debug, Clone)]
49pub struct Instruction22s  { opcode: OpCode, length: usize, bytes: [u16; 2] }
50/// `Instruction22t` instruction type
51#[derive(Debug, Clone)]
52pub struct Instruction22t  { opcode: OpCode, length: usize, bytes: [u16; 2] }
53/// `Instruction22x` instruction type
54#[derive(Debug, Clone)]
55pub struct Instruction22x  { opcode: OpCode, length: usize, bytes: [u16; 2] }
56/// `Instruction23x` instruction type
57#[derive(Debug, Clone)]
58pub struct Instruction23x  { opcode: OpCode, length: usize, bytes: [u16; 2] }
59/// `Instruction30t` instruction type
60#[derive(Debug, Clone)]
61pub struct Instruction30t  { opcode: OpCode, length: usize, bytes: [u16; 3] }
62/// `Instruction31c` instruction type
63#[derive(Debug, Clone)]
64pub struct Instruction31c  { opcode: OpCode, length: usize, bytes: [u16; 3] }
65/// `Instruction31i` instruction type
66#[derive(Debug, Clone)]
67pub struct Instruction31i  { opcode: OpCode, length: usize, bytes: [u16; 3] }
68/// `Instruction31t` instruction type
69#[derive(Debug, Clone)]
70pub struct Instruction31t  { opcode: OpCode, length: usize, bytes: [u16; 3] }
71/// `Instruction32x` instruction type
72#[derive(Debug, Clone)]
73pub struct Instruction32x  { opcode: OpCode, length: usize, bytes: [u16; 3] }
74/// `Instruction35c` instruction type
75#[derive(Debug, Clone)]
76pub struct Instruction35c  { opcode: OpCode, length: usize, bytes: [u16; 3] }
77/// `Instruction3rc` instruction type
78#[derive(Debug, Clone)]
79pub struct Instruction3rc  { opcode: OpCode, length: usize, bytes: [u16; 3] }
80/// `Instruction45cc` instruction type
81#[derive(Debug, Clone)]
82pub struct Instruction45cc { opcode: OpCode, length: usize, bytes: [u16; 4] }
83/// `Instruction4rcc` instruction type
84#[derive(Debug, Clone)]
85pub struct Instruction4rcc { opcode: OpCode, length: usize, bytes: [u16; 4] }
86/// `Instruction51l` instruction type
87#[derive(Debug, Clone)]
88pub struct Instruction51l  { opcode: OpCode, length: usize, bytes: [u16; 5] }
89/// `PackedSwitchPayload` instruction type
90#[derive(Debug, Clone)]
91pub struct PackedSwitchPayload {
92    opcode: OpCode,
93    size: u16,
94    first_key: i32,
95    targets: Vec<i32>
96}
97/// `SparseSwitchPayload` instruction type
98#[derive(Debug, Clone)]
99pub struct SparseSwitchPayload {
100    opcode: OpCode,
101    size: u16,
102    keys: Vec<i32>,
103    targets: Vec<i32>
104}
105/// `FillArrayDataPayload` instruction type
106#[derive(Debug, Clone)]
107pub struct FillArrayDataPayload {
108    opcode: OpCode,
109    element_width: u16,
110    size: u32,
111    data: Vec<u8>
112}
113
114impl PackedSwitchPayload {
115    /// Create a `PackedSwitchPayload` instruction from the reader
116    fn build(reader: &mut DexReader) -> Result<Self, DexError> {
117        let size = reader.read_u16()?;
118        let first_key = reader.read_i32()?;
119
120        let mut targets = Vec::with_capacity(size.into());
121        for _ in 0..size {
122            targets.push(reader.read_i32()?);
123        }
124
125        Ok(PackedSwitchPayload {
126            opcode: OpCode::PACKED_SWITCH_PAYLOAD,
127            size,
128            first_key,
129            targets
130        })
131    }
132
133    fn get_size(&self) -> usize {
134        self.size as usize
135    }
136
137    fn get_first_key(&self) -> i32 {
138        self.first_key
139    }
140
141    fn get_targets(&self) -> &[i32] {
142        &self.targets
143    }
144
145    fn length(&self) -> usize {
146        // nb of entries in bytes + size of (opcode and size)
147        ((self.size * 2) + 4).into()
148    }
149
150    fn opcode(&self) -> OpCode {
151        OpCode::PACKED_SWITCH_PAYLOAD
152    }
153
154    // TODO: find a better fallback. This instruction
155    // does not have "bytes" like the others but we
156    // need to implement this function as part of the
157    // trait implementation.
158    fn bytes(&self) -> &[u16] {
159        &[]
160    }
161
162    fn inst_format(&self) -> &str {
163        "PackedSwitchPayload"
164    }
165}
166
167impl SparseSwitchPayload {
168    /// Create a `SparseSwitchPayload` instruction from the reader
169    fn build(reader: &mut DexReader) -> Result<Self, DexError> {
170        let size = reader.read_u16()?;
171
172        let mut keys = Vec::with_capacity(size.into());
173        for _ in 0..size {
174            keys.push(reader.read_i32()?);
175        }
176
177        let mut targets = Vec::with_capacity(size.into());
178        for _ in 0..size {
179            targets.push(reader.read_i32()?);
180        }
181
182        Ok(SparseSwitchPayload {
183            opcode: OpCode::SPARSE_SWITCH_PAYLOAD,
184            size,
185            keys,
186            targets
187        })
188    }
189
190    fn get_size(&self) -> usize {
191        self.size as usize
192    }
193
194    fn get_keys(&self) -> &[i32] {
195        &self.keys
196    }
197
198    fn get_targets(&self) -> &[i32] {
199        &self.targets
200    }
201
202    fn length(&self) -> usize {
203        ((self.size * 4) + 2).into()
204    }
205
206    fn opcode(&self) -> OpCode {
207        OpCode::SPARSE_SWITCH_PAYLOAD
208    }
209
210    // TODO: find a better fallback. This instruction
211    // does not have "bytes" like the others but we
212    // need to implement this function as part of the
213    // trait implementation.
214    fn bytes(&self) -> &[u16] {
215        &[]
216    }
217
218    fn inst_format(&self) -> &str {
219        "SparseSwitchPayload"
220    }
221}
222
223impl FillArrayDataPayload {
224    /// Create a `FillArrayDataPayload` instruction from the reader
225    fn build(reader: &mut DexReader) -> Result<Self, DexError> {
226        // FIXME the bytes come up empty, check the bounds of the for loop
227        let element_width = reader.read_u16()?;
228        let size = reader.read_u32()?;
229
230        let mut data = Vec::with_capacity((size * element_width as u32) as usize);
231        for _ in 0..size {
232            for _ in 0..element_width {
233                data.push(reader.read_u8()?);
234            }
235        }
236
237        Ok(FillArrayDataPayload {
238            opcode: OpCode::FILL_ARRAY_DATA_PAYLOAD,
239            element_width,
240            size,
241            data
242        })
243    }
244
245    fn get_element_width(&self) -> u16 {
246        self.element_width
247    }
248
249    fn get_size(&self) -> u32 {
250        self.size
251    }
252
253    fn get_data(&self) -> &[u8] {
254        &self.data
255    }
256
257    fn length(&self) -> usize {
258        ((self.size * self.element_width as u32) / 2 + 4) as usize
259    }
260
261    fn opcode(&self) -> OpCode {
262        OpCode::FILL_ARRAY_DATA_PAYLOAD
263    }
264
265    // TODO: find a better fallback. This instruction
266    // does not have "bytes" like the others but we
267    // need to implement this function as part of the
268    // trait implementation.
269    fn bytes(&self) -> &[u16] {
270        &[]
271    }
272
273    fn inst_format(&self) -> &str {
274        "FillArrayDataPayload"
275    }
276}
277
278
279/// Enumeration of all possible instruction types
280#[derive(Debug, Clone)]
281pub enum Instructions {
282    Instruction10t(Instruction10t),
283    Instruction10x(Instruction10x),
284    Instruction11n(Instruction11n),
285    Instruction11x(Instruction11x),
286    Instruction12x(Instruction12x),
287    Instruction20t(Instruction20t),
288    Instruction21c(Instruction21c),
289    Instruction21h(Instruction21h),
290    Instruction21s(Instruction21s),
291    Instruction21t(Instruction21t),
292    Instruction22b(Instruction22b),
293    Instruction22c(Instruction22c),
294    Instruction22s(Instruction22s),
295    Instruction22t(Instruction22t),
296    Instruction22x(Instruction22x),
297    Instruction23x(Instruction23x),
298    Instruction30t(Instruction30t),
299    Instruction31c(Instruction31c),
300    Instruction31i(Instruction31i),
301    Instruction31t(Instruction31t),
302    Instruction32x(Instruction32x),
303    Instruction35c(Instruction35c),
304    Instruction3rc(Instruction3rc),
305    Instruction45cc(Instruction45cc),
306    Instruction4rcc(Instruction4rcc),
307    Instruction51l(Instruction51l),
308    PackedSwitchPayload(PackedSwitchPayload),
309    SparseSwitchPayload(SparseSwitchPayload),
310    FillArrayDataPayload(FillArrayDataPayload),
311}
312
313
314impl Instructions {
315    /// Get the length of a given instruction
316    pub fn length(&self) -> usize {
317        match self {
318            Instructions::Instruction10t(inst) => inst.length,
319            Instructions::Instruction10x(inst) => inst.length,
320            Instructions::Instruction11n(inst) => inst.length,
321            Instructions::Instruction11x(inst) => inst.length,
322            Instructions::Instruction12x(inst) => inst.length,
323            Instructions::Instruction20t(inst) => inst.length,
324            Instructions::Instruction21c(inst) => inst.length,
325            Instructions::Instruction21h(inst) => inst.length,
326            Instructions::Instruction21s(inst) => inst.length,
327            Instructions::Instruction21t(inst) => inst.length,
328            Instructions::Instruction22b(inst) => inst.length,
329            Instructions::Instruction22c(inst) => inst.length,
330            Instructions::Instruction22s(inst) => inst.length,
331            Instructions::Instruction22t(inst) => inst.length,
332            Instructions::Instruction22x(inst) => inst.length,
333            Instructions::Instruction23x(inst) => inst.length,
334            Instructions::Instruction30t(inst) => inst.length,
335            Instructions::Instruction31c(inst) => inst.length,
336            Instructions::Instruction31i(inst) => inst.length,
337            Instructions::Instruction31t(inst) => inst.length,
338            Instructions::Instruction32x(inst) => inst.length,
339            Instructions::Instruction35c(inst) => inst.length,
340            Instructions::Instruction3rc(inst) => inst.length,
341            Instructions::Instruction45cc(inst) => inst.length,
342            Instructions::Instruction4rcc(inst) => inst.length,
343            Instructions::Instruction51l(inst) => inst.length,
344            Instructions::PackedSwitchPayload(inst) => inst.length(),
345            Instructions::SparseSwitchPayload(inst) => inst.length(),
346            Instructions::FillArrayDataPayload(inst) => inst.length(),
347        }
348    }
349
350    /// Get the opcode of a given instruction
351    pub fn opcode(&self) -> OpCode {
352        match self {
353            Instructions::Instruction10t(inst) => inst.opcode,
354            Instructions::Instruction10x(inst) => inst.opcode,
355            Instructions::Instruction11n(inst) => inst.opcode,
356            Instructions::Instruction11x(inst) => inst.opcode,
357            Instructions::Instruction12x(inst) => inst.opcode,
358            Instructions::Instruction20t(inst) => inst.opcode,
359            Instructions::Instruction21c(inst) => inst.opcode,
360            Instructions::Instruction21h(inst) => inst.opcode,
361            Instructions::Instruction21s(inst) => inst.opcode,
362            Instructions::Instruction21t(inst) => inst.opcode,
363            Instructions::Instruction22b(inst) => inst.opcode,
364            Instructions::Instruction22c(inst) => inst.opcode,
365            Instructions::Instruction22s(inst) => inst.opcode,
366            Instructions::Instruction22t(inst) => inst.opcode,
367            Instructions::Instruction22x(inst) => inst.opcode,
368            Instructions::Instruction23x(inst) => inst.opcode,
369            Instructions::Instruction30t(inst) => inst.opcode,
370            Instructions::Instruction31c(inst) => inst.opcode,
371            Instructions::Instruction31i(inst) => inst.opcode,
372            Instructions::Instruction31t(inst) => inst.opcode,
373            Instructions::Instruction32x(inst) => inst.opcode,
374            Instructions::Instruction35c(inst) => inst.opcode,
375            Instructions::Instruction3rc(inst) => inst.opcode,
376            Instructions::Instruction45cc(inst) => inst.opcode,
377            Instructions::Instruction4rcc(inst) => inst.opcode,
378            Instructions::Instruction51l(inst) => inst.opcode,
379            Instructions::PackedSwitchPayload(inst) => inst.opcode,
380            Instructions::SparseSwitchPayload(inst) => inst.opcode,
381            Instructions::FillArrayDataPayload(inst) => inst.opcode,
382        }
383    }
384
385    /// Get the bytes of a given instruction
386    pub fn bytes(&self) -> &[u16] {
387        match self {
388            Instructions::Instruction10t(inst) => &inst.bytes,
389            Instructions::Instruction10x(inst) => &inst.bytes,
390            Instructions::Instruction11n(inst) => &inst.bytes,
391            Instructions::Instruction11x(inst) => &inst.bytes,
392            Instructions::Instruction12x(inst) => &inst.bytes,
393            Instructions::Instruction20t(inst) => &inst.bytes,
394            Instructions::Instruction21c(inst) => &inst.bytes,
395            Instructions::Instruction21h(inst) => &inst.bytes,
396            Instructions::Instruction21s(inst) => &inst.bytes,
397            Instructions::Instruction21t(inst) => &inst.bytes,
398            Instructions::Instruction22b(inst) => &inst.bytes,
399            Instructions::Instruction22c(inst) => &inst.bytes,
400            Instructions::Instruction22s(inst) => &inst.bytes,
401            Instructions::Instruction22t(inst) => &inst.bytes,
402            Instructions::Instruction22x(inst) => &inst.bytes,
403            Instructions::Instruction23x(inst) => &inst.bytes,
404            Instructions::Instruction30t(inst) => &inst.bytes,
405            Instructions::Instruction31c(inst) => &inst.bytes,
406            Instructions::Instruction31i(inst) => &inst.bytes,
407            Instructions::Instruction31t(inst) => &inst.bytes,
408            Instructions::Instruction32x(inst) => &inst.bytes,
409            Instructions::Instruction35c(inst) => &inst.bytes,
410            Instructions::Instruction3rc(inst) => &inst.bytes,
411            Instructions::Instruction45cc(inst) => &inst.bytes,
412            Instructions::Instruction4rcc(inst) => &inst.bytes,
413            Instructions::Instruction51l(inst) => &inst.bytes,
414            Instructions::PackedSwitchPayload(_) => &[],  // FIXME
415            Instructions::SparseSwitchPayload(_) => &[],  // FIXME
416            Instructions::FillArrayDataPayload(_) => &[],  // FIXME
417        }
418    }
419}
420
421/////////////////////////////////////////////////////////////////
422
423/// Parse an instruction from the reader
424pub fn parse_instruction(reader: &mut DexReader, container: &mut Vec<Instructions>) -> Result<usize, DexError> {
425    let raw_opcode = reader.read_u16()?;
426
427    let opcode = match OpCode::parse((raw_opcode & 0xff).try_into().unwrap()) {
428        // Deal with the special cases of fill-array-data-payload,
429        // packed-switch-payload, and sparse-switch-payload
430        Some(OpCode::NOP) => match raw_opcode >> 8 {
431            0x01 => OpCode::PACKED_SWITCH_PAYLOAD,
432            0x02 => OpCode::SPARSE_SWITCH_PAYLOAD,
433            0x03 => OpCode::FILL_ARRAY_DATA_PAYLOAD,
434            _    => OpCode::NOP
435        },
436        Some(code) => code,
437        None => return Err(DexError::InvalidOpCode)
438    };
439
440    match opcode {
441        OpCode::GOTO => {
442            let mut bytes = [0u16; 1];
443            bytes[0] = raw_opcode;
444            container.push(Instructions::Instruction10t(Instruction10t {
445                opcode,
446                bytes,
447                length: 1
448            }));
449            Ok(1)
450        },
451
452        OpCode::NOP | OpCode::RETURN_VOID => {
453            let mut bytes = [0u16; 1];
454            bytes[0] = raw_opcode;
455            container.push(Instructions::Instruction10x(Instruction10x{
456                opcode,
457                bytes,
458                length: 1
459            }));
460            Ok(1)
461        },
462
463        OpCode::CONST_4 => {
464            let mut bytes = [0u16; 1];
465            bytes[0] = raw_opcode;
466            container.push(Instructions::Instruction11n(Instruction11n{
467                opcode,
468                bytes,
469                length: 1
470            }));
471            Ok(1)
472        },
473
474        OpCode::MONITOR_ENTER            | OpCode::MONITOR_EXIT
475            | OpCode::MOVE_EXCEPTION     | OpCode::MOVE_RESULT
476            | OpCode::MOVE_RESULT_OBJECT | OpCode::MOVE_RESULT_WIDE
477            | OpCode::RETURN             | OpCode::RETURN_OBJECT
478            | OpCode::RETURN_WIDE        | OpCode::THROW
479            => {
480                let mut bytes = [0u16; 1];
481                bytes[0] = raw_opcode;
482                container.push(Instructions::Instruction11x(Instruction11x{
483                    opcode,
484                    bytes,
485                    length: 1
486                }));
487                Ok(1)
488            },
489
490        OpCode::ADD_DOUBLE_2ADDR      | OpCode::ADD_FLOAT_2ADDR
491            | OpCode::ADD_INT_2ADDR   | OpCode::ADD_LONG_2ADDR
492            | OpCode::AND_INT_2ADDR   | OpCode::AND_LONG_2ADDR
493            | OpCode::ARRAY_LENGTH    | OpCode::DIV_DOUBLE_2ADDR
494            | OpCode::DIV_FLOAT_2ADDR | OpCode::DIV_INT_2ADDR
495            | OpCode::DIV_LONG_2ADDR  | OpCode::DOUBLE_TO_FLOAT
496            | OpCode::DOUBLE_TO_INT   | OpCode::DOUBLE_TO_LONG
497            | OpCode::FLOAT_TO_DOUBLE | OpCode::FLOAT_TO_INT
498            | OpCode::FLOAT_TO_LONG   | OpCode::INT_TO_BYTE
499            | OpCode::INT_TO_CHAR     | OpCode::INT_TO_DOUBLE
500            | OpCode::INT_TO_FLOAT    | OpCode::INT_TO_LONG
501            | OpCode::INT_TO_SHORT    | OpCode::LONG_TO_DOUBLE
502            | OpCode::LONG_TO_FLOAT   | OpCode::LONG_TO_INT
503            | OpCode::MOVE            | OpCode::MOVE_OBJECT
504            | OpCode::MOVE_WIDE       | OpCode::MUL_DOUBLE_2ADDR
505            | OpCode::MUL_FLOAT_2ADDR | OpCode::MUL_INT_2ADDR
506            | OpCode::MUL_LONG_2ADDR  | OpCode::NEG_DOUBLE
507            | OpCode::NEG_FLOAT       | OpCode::NEG_INT
508            | OpCode::NEG_LONG        | OpCode::NOT_INT
509            | OpCode::NOT_LONG        | OpCode::OR_INT_2ADDR
510            | OpCode::OR_LONG_2ADDR   | OpCode::REM_DOUBLE_2ADDR
511            | OpCode::REM_FLOAT_2ADDR | OpCode::REM_INT_2ADDR
512            | OpCode::REM_LONG_2ADDR  | OpCode::SHL_INT_2ADDR
513            | OpCode::SHL_LONG_2ADDR  | OpCode::SHR_INT_2ADDR
514            | OpCode::SHR_LONG_2ADDR  | OpCode::SUB_DOUBLE_2ADDR
515            | OpCode::SUB_FLOAT_2ADDR | OpCode::SUB_INT_2ADDR
516            | OpCode::SUB_LONG_2ADDR  | OpCode::USHR_INT_2ADDR
517            | OpCode::USHR_LONG_2ADDR | OpCode::XOR_INT_2ADDR
518            | OpCode::XOR_LONG_2ADDR
519            => {
520                let mut bytes = [0u16; 1];
521                bytes[0] = raw_opcode;
522                container.push(Instructions::Instruction12x(Instruction12x{
523                    opcode,
524                    bytes,
525                    length: 1
526                }));
527                Ok(1)
528            },
529
530        OpCode::GOTO_16 => {
531            let mut bytes = [0u16; 2];
532            bytes[0] = raw_opcode;
533            bytes[1] = reader.read_u16()?;
534            container.push(Instructions::Instruction20t(Instruction20t{
535                opcode,
536                bytes,
537                length: 2
538            }));
539            Ok(2)
540        },
541
542        OpCode::CHECK_CAST                | OpCode::CONST_CLASS
543            | OpCode::CONST_METHOD_HANDLE | OpCode::CONST_METHOD_TYPE
544            | OpCode::CONST_STRING        | OpCode::NEW_INSTANCE
545            | OpCode::SGET_BOOLEAN        | OpCode::SGET_BYTE
546            | OpCode::SGET_CHAR           | OpCode::SGET
547            | OpCode::SGET_OBJECT         | OpCode::SGET_SHORT
548            | OpCode::SGET_WIDE           | OpCode::SPUT_BOOLEAN
549            | OpCode::SPUT_BYTE           | OpCode::SPUT_CHAR
550            | OpCode::SPUT                | OpCode::SPUT_OBJECT
551            | OpCode::SPUT_SHORT          | OpCode::SPUT_WIDE
552            => {
553                let mut bytes = [0u16; 2];
554                bytes[0] = raw_opcode;
555                bytes[1] = reader.read_u16()?;
556                container.push(Instructions::Instruction21c(Instruction21c {
557                    opcode,
558                    bytes,
559                    length: 2
560                }));
561                Ok(2)
562            },
563
564        OpCode::CONST_HIGH16 | OpCode::CONST_WIDE_HIGH16
565            => {
566                let mut bytes = [0u16; 2];
567                bytes[0] = raw_opcode;
568                bytes[1] = reader.read_u16()?;
569                container.push(Instructions::Instruction21h(Instruction21h {
570                    opcode,
571                    bytes,
572                    length: 2
573                }));
574                Ok(2)
575            },
576
577        OpCode::CONST_16 | OpCode::CONST_WIDE_16
578            => {
579                let mut bytes = [0u16; 2];
580                bytes[0] = raw_opcode;
581                bytes[1] = reader.read_u16()?;
582                container.push(Instructions::Instruction21s(Instruction21s {
583                    opcode,
584                    bytes,
585                    length: 2
586                }));
587                Ok(2)
588            },
589
590        OpCode::IF_EQZ       | OpCode::IF_GEZ
591            | OpCode::IF_GTZ | OpCode::IF_LEZ
592            | OpCode::IF_LTZ | OpCode::IF_NEZ
593            => {
594                let mut bytes = [0u16; 2];
595                bytes[0] = raw_opcode;
596                bytes[1] = reader.read_u16()?;
597                container.push(Instructions::Instruction21t(Instruction21t {
598                    opcode,
599                    bytes,
600                    length: 2
601                }));
602                Ok(2)
603            },
604
605        OpCode::ADD_INT_LIT8        | OpCode::AND_INT_LIT8
606            | OpCode::DIV_INT_LIT8  | OpCode::MUL_INT_LIT8
607            | OpCode::OR_INT_LIT8   | OpCode::REM_INT_LIT8
608            | OpCode::RSUB_INT_LIT8 | OpCode::SHL_INT_LIT8
609            | OpCode::SHR_INT_LIT8  | OpCode::USHR_INT_LIT8
610            | OpCode::XOR_INT_LIT8
611            => {
612                let mut bytes = [0u16; 2];
613                bytes[0] = raw_opcode;
614                bytes[1] = reader.read_u16()?;
615                container.push(Instructions::Instruction22b(Instruction22b {
616                    opcode,
617                    bytes,
618                    length: 2
619                }));
620                Ok(2)
621            },
622
623        OpCode::IGET_BOOLEAN       | OpCode::IGET_BYTE
624            | OpCode::IGET_CHAR    | OpCode::IGET
625            | OpCode::IGET_OBJECT  | OpCode::IGET_SHORT
626            | OpCode::IGET_WIDE    | OpCode::INSTANCE_OF
627            | OpCode::IPUT_BOOLEAN | OpCode::IPUT_BYTE
628            | OpCode::IPUT_CHAR    | OpCode::IPUT
629            | OpCode::IPUT_OBJECT  | OpCode::IPUT_SHORT
630            | OpCode::IPUT_WIDE    | OpCode::NEW_ARRAY
631            => {
632                let mut bytes = [0u16; 2];
633                bytes[0] = raw_opcode;
634                bytes[1] = reader.read_u16()?;
635                container.push(Instructions::Instruction22c(Instruction22c {
636                    opcode,
637                    bytes,
638                    length: 2
639                }));
640                Ok(2)
641            },
642
643        OpCode::ADD_INT_LIT16       | OpCode::AND_INT_LIT16
644            | OpCode::DIV_INT_LIT16 | OpCode::MUL_INT_LIT16
645            | OpCode::OR_INT_LIT16  | OpCode::REM_INT_LIT16
646            | OpCode::RSUB_INT      | OpCode::XOR_INT_LIT16
647            => {
648                let mut bytes = [0u16; 2];
649                bytes[0] = raw_opcode;
650                bytes[1] = reader.read_u16()?;
651                container.push(Instructions::Instruction22s(Instruction22s {
652                    opcode,
653                    bytes,
654                    length: 2
655                }));
656                Ok(2)
657            },
658
659        OpCode::IF_EQ       | OpCode::IF_GE
660            | OpCode::IF_GT | OpCode::IF_LE
661            | OpCode::IF_LT | OpCode::IF_NE
662            => {
663                let mut bytes = [0u16; 2];
664                bytes[0] = raw_opcode;
665                bytes[1] = reader.read_u16()?;
666                container.push(Instructions::Instruction22t(Instruction22t {
667                    opcode,
668                    bytes,
669                    length: 2
670                }));
671                Ok(2)
672            },
673
674        OpCode::MOVE_FROM16 | OpCode::MOVE_OBJECT_FROM16
675            | OpCode::MOVE_WIDE_FROM16
676            => {
677                let mut bytes = [0u16; 2];
678                bytes[0] = raw_opcode;
679                bytes[1] = reader.read_u16()?;
680                container.push(Instructions::Instruction22x(Instruction22x {
681                    opcode,
682                    bytes,
683                    length: 2
684                }));
685                Ok(2)
686            },
687
688        OpCode::ADD_DOUBLE         | OpCode::ADD_FLOAT
689            | OpCode::ADD_INT      | OpCode::ADD_LONG
690            | OpCode::AGET_BOOLEAN | OpCode::AGET_BYTE
691            | OpCode::AGET_CHAR    | OpCode::AGET
692            | OpCode::AGET_OBJECT  | OpCode::AGET_SHORT
693            | OpCode::AGET_WIDE    | OpCode::AND_INT
694            | OpCode::AND_LONG     | OpCode::APUT_BOOLEAN
695            | OpCode::APUT_BYTE    | OpCode::APUT_CHAR
696            | OpCode::APUT         | OpCode::APUT_OBJECT
697            | OpCode::APUT_SHORT   | OpCode::APUT_WIDE
698            | OpCode::CMPG_DOUBLE  | OpCode::CMPG_FLOAT
699            | OpCode::CMPL_DOUBLE  | OpCode::CMPL_FLOAT
700            | OpCode::CMP_LONG     | OpCode::DIV_DOUBLE
701            | OpCode::DIV_FLOAT    | OpCode::DIV_INT
702            | OpCode::DIV_LONG     | OpCode::MUL_DOUBLE
703            | OpCode::MUL_FLOAT    | OpCode::MUL_INT
704            | OpCode::MUL_LONG     | OpCode::OR_INT
705            | OpCode::OR_LONG      | OpCode::REM_DOUBLE
706            | OpCode::REM_FLOAT    | OpCode::REM_INT
707            | OpCode::REM_LONG     | OpCode::SHL_INT
708            | OpCode::SHL_LONG     | OpCode::SHR_INT
709            | OpCode::SHR_LONG     | OpCode::SUB_DOUBLE
710            | OpCode::SUB_FLOAT    | OpCode::SUB_INT
711            | OpCode::SUB_LONG     | OpCode::USHR_INT
712            | OpCode::USHR_LONG    | OpCode::XOR_INT
713            | OpCode::XOR_LONG
714            => {
715                let mut bytes = [0u16; 2];
716                bytes[0] = raw_opcode;
717                bytes[1] = reader.read_u16()?;
718                container.push(Instructions::Instruction23x(Instruction23x {
719                    opcode,
720                    bytes,
721                    length: 2
722                }));
723                Ok(2)
724            },
725
726        OpCode::GOTO_32 => {
727            let mut bytes = [0u16; 3];
728            bytes[0] = raw_opcode;
729            bytes[1] = reader.read_u16()?;
730            bytes[2] = reader.read_u16()?;
731            container.push(Instructions::Instruction30t(Instruction30t {
732                opcode,
733                bytes,
734                length: 3
735            }));
736            Ok(3)
737        },
738
739        OpCode::CONST_STRING_JUMBO => {
740            let mut bytes = [0u16; 3];
741            bytes[0] = raw_opcode;
742            bytes[1] = reader.read_u16()?;
743            bytes[2] = reader.read_u16()?;
744            container.push(Instructions::Instruction31c(Instruction31c {
745                opcode,
746                bytes,
747                length: 3
748            }));
749            Ok(3)
750        },
751
752        OpCode::CONST | OpCode::CONST_WIDE_32
753            => {
754                let mut bytes = [0u16; 3];
755                bytes[0] = raw_opcode;
756                bytes[1] = reader.read_u16()?;
757                bytes[2] = reader.read_u16()?;
758                container.push(Instructions::Instruction31i(Instruction31i {
759                    opcode,
760                    bytes,
761                    length: 3
762                }));
763                Ok(3)
764            },
765
766        OpCode::FILL_ARRAY_DATA | OpCode::PACKED_SWITCH
767            | OpCode::SPARSE_SWITCH => {
768                let mut bytes = [0u16; 3];
769                bytes[0] = raw_opcode;
770                bytes[1] = reader.read_u16()?;
771                bytes[2] = reader.read_u16()?;
772                container.push(Instructions::Instruction31t(Instruction31t {
773                    opcode,
774                    bytes,
775                    length: 3
776                }));
777                Ok(3)
778            },
779
780        OpCode::MOVE_16 | OpCode::MOVE_OBJECT_16
781            | OpCode::MOVE_WIDE_16 => {
782                let mut bytes = [0u16; 3];
783                bytes[0] = raw_opcode;
784                bytes[1] = reader.read_u16()?;
785                bytes[2] = reader.read_u16()?;
786                container.push(Instructions::Instruction32x(Instruction32x {
787                    opcode,
788                    bytes,
789                    length: 3
790                }));
791                Ok(3)
792            },
793
794        OpCode::FILLED_NEW_ARRAY    | OpCode::INVOKE_CUSTOM
795            | OpCode::INVOKE_DIRECT | OpCode::INVOKE_INTERFACE
796            | OpCode::INVOKE_STATIC | OpCode::INVOKE_SUPER
797            | OpCode::INVOKE_VIRTUAL
798            => {
799                let mut bytes = [0u16; 3];
800                bytes[0] = raw_opcode;
801                bytes[1] = reader.read_u16()?;
802                bytes[2] = reader.read_u16()?;
803                container.push(Instructions::Instruction35c(Instruction35c {
804                    opcode,
805                    bytes,
806                    length: 3
807                }));
808                Ok(3)
809            },
810
811        OpCode::FILLED_NEW_ARRAY_RANGE    | OpCode::INVOKE_CUSTOM_RANGE
812            | OpCode::INVOKE_DIRECT_RANGE | OpCode::INVOKE_INTERFACE_RANGE
813            | OpCode::INVOKE_STATIC_RANGE | OpCode::INVOKE_SUPER_RANGE
814            | OpCode::INVOKE_VIRTUAL_RANGE
815            => {
816                let mut bytes = [0u16; 3];
817                bytes[0] = raw_opcode;
818                bytes[1] = reader.read_u16()?;
819                bytes[2] = reader.read_u16()?;
820                container.push(Instructions::Instruction3rc(Instruction3rc {
821                    opcode,
822                    bytes,
823                    length: 3
824                }));
825                Ok(3)
826            },
827
828        OpCode::INVOKE_POLYMORPHIC => {
829            let mut bytes = [0u16; 4];
830            bytes[0] = raw_opcode;
831            bytes[1] = reader.read_u16()?;
832            bytes[2] = reader.read_u16()?;
833            bytes[3] = reader.read_u16()?;
834            container.push(Instructions::Instruction45cc(Instruction45cc {
835                opcode,
836                bytes,
837                length: 4
838            }));
839            Ok(4)
840        },
841
842        OpCode::INVOKE_POLYMORPHIC_RANGE => {
843            let mut bytes = [0u16; 4];
844            bytes[0] = raw_opcode;
845            bytes[1] = reader.read_u16()?;
846            bytes[2] = reader.read_u16()?;
847            bytes[3] = reader.read_u16()?;
848            container.push(Instructions::Instruction4rcc(Instruction4rcc {
849                opcode,
850                bytes,
851                length: 4
852            }));
853            Ok(4)
854        },
855
856        OpCode::CONST_WIDE => {
857            let mut bytes = [0u16; 5];
858            bytes[0] = raw_opcode;
859            bytes[1] = reader.read_u16()?;
860            bytes[2] = reader.read_u16()?;
861            bytes[3] = reader.read_u16()?;
862            bytes[4] = reader.read_u16()?;
863            container.push(Instructions::Instruction51l(Instruction51l {
864                opcode,
865                bytes,
866                length: 5
867            }));
868            Ok(5)
869        },
870
871        OpCode::PACKED_SWITCH_PAYLOAD => {
872            let inst = PackedSwitchPayload::build(reader)?;
873            let len = inst.length();
874            container.push(Instructions::PackedSwitchPayload(inst));
875            reader.align_cursor()?;
876            Ok(len)
877        },
878
879        OpCode::SPARSE_SWITCH_PAYLOAD => {
880            let inst = SparseSwitchPayload::build(reader)?;
881            let len = inst.length();
882            container.push(Instructions::SparseSwitchPayload(inst));
883            reader.align_cursor()?;
884            Ok(len)
885        },
886
887        OpCode::FILL_ARRAY_DATA_PAYLOAD => {
888            let inst = FillArrayDataPayload::build(reader)?;
889            let len = inst.length();
890            container.push(Instructions::FillArrayDataPayload(inst));
891            reader.align_cursor()?;
892            Ok(len)
893        }
894    }
895}