Skip to main content

objdiff_core/arch/superh/
disasm.rs

1use alloc::{format, vec::Vec};
2
3use crate::{diff::display::InstructionPart, obj::ResolvedInstructionRef};
4
5static REG_NAMES: [&str; 16] = [
6    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14",
7    "r15",
8];
9
10enum Ops {
11    // match_ni_f
12    AddImmRn,
13    MovImmRn,
14    // match_i_f
15    AndBImmAtR0Gbr,
16    OrBImmAtR0Gbr,
17    TstBImmAtR0Gbr,
18    XorBImmAtR0Gbr,
19    AndImmR0,
20    CmpEqImmR0,
21    OrImmR0,
22    TstImmR0,
23    XorImmR0,
24    Trapa,
25
26    // match_nd8_f
27    MovWAtDispPcRn,
28    MovLAtDispPcRn,
29
30    // match_d12_f
31    Bra,
32    Bsr,
33
34    // match_d_f
35    MovBR0AtDispGbr,
36    MovWR0AtDispGbr,
37    MovLR0AtDispGbr,
38    MovBAtDispGbrR0,
39    MovWAtDispGbrR0,
40    MovLAtDispGbrR0,
41    Bf,
42    Bfs,
43    Bt,
44    Bts,
45
46    // match_nmd_f
47    MovLRmAtDispRn,
48    MovLRDispRmRn,
49
50    // match_ff00
51    MovBAtDispRnR0,
52    MovWAtDispRnR0,
53    MovBR0AtDispRn,
54    MovWR0AtDispRn,
55
56    // match_f00f
57    AddRmRn,
58    AddcRmRn,
59    AddvRmRn,
60    AndRmRn,
61    CmpEqRmRn,
62    CmpHsRmRn,
63    CmpGeRmRn,
64    CmpHiRmRn,
65    CmpGtRmRn,
66    CmpStrRmRn,
67    Div1RmRn,
68    Div0sRmRn,
69    DmulsLRmRn,
70    DmuluLRmRn,
71    ExtsBRmRn,
72    ExtsWRmRn,
73    ExtuBRmRn,
74    ExtuWRmRn,
75    MovRmRn,
76    MulLRmRn,
77    MulsRmRn,
78    MuluRmRn,
79    NegRmRn,
80    NegcRmRn,
81    NotRmRn,
82    OrRmRn,
83    SubRmRn,
84    SubcRmRn,
85    SubvRmRn,
86    SwapBRmRn,
87    SwapWRmRn,
88    TstRmRn,
89    XorRmRn,
90    XtrctRmRn,
91    MovBRmAtRn,
92    MovWRmAtRn,
93    MovLRmAtRn,
94    MovBAtRmRn,
95    MovWAtRmRn,
96    MovLAtRmRn,
97    MacLAtRmIncAtRnInc,
98    MacWAtRmIncAtRnInc,
99    MovBAtRmIncRn,
100    MovWAtRmIncRn,
101    MovLAtRmIncRn,
102    MovBRmAtDecRn,
103    MovWRmAtDecRn,
104    MovLRmAtDecRn,
105    MovBRmAtR0Rn,
106    MovWRmAtR0Rn,
107    MovLRmAtR0Rn,
108    MovBAtR0RmRn,
109    MovWAtR0RmRn,
110    MovLAtR0RmRn,
111
112    // match_f0ff
113    CmpPlRn,
114    CmpPzRn,
115    DtRn,
116    MovtRn,
117    RotlRn,
118    RotrRn,
119    RotclRn,
120    RotcrRn,
121    ShalRn,
122    SharRn,
123    ShllRn,
124    ShlrRn,
125    Shll2Rn,
126    Shlr2Rn,
127    Shll8Rn,
128    Shlr8Rn,
129    Shll16Rn,
130    Shlr16Rn,
131    StcSrRn,
132    StcGbrRn,
133    StcVbrRn,
134    StsMachRn,
135    StsMaclRn,
136    StsPrRn,
137    TasB,
138    StcLSrAtDecrementRn,
139    StcLGbrAtDecrementRn,
140    StcLVbrAtDecrementRn,
141    StsLMachAtDecrementRn,
142    StsLMaclAtDecrementRn,
143    StsLPrAtDecrementRn,
144    LdcRnSr,
145    LdcRnGbr,
146    LdcRnVbr,
147    LdsRnMach,
148    LdsRnMacl,
149    LdsRnPr,
150    JmpAtRn,
151    JsrAtRn,
152    LdcLAtRnIncSr,
153    LdcLAtRnIncGbr,
154    LdcLAtRnIncVbr,
155    LdsLAtRnIncMach,
156    LdsLAtRnIncMacl,
157    LdsLAtRnIncPr,
158    BrafRn,
159    BsrfRn,
160
161    //sh2_disasm
162    Clrt,
163    Clrmac,
164    Div0u,
165    Nop,
166    Rte,
167    Rts,
168    Sett,
169    Sleep,
170}
171fn match_ni_f(
172    _v_addr: u32,
173    op: u16,
174    _mode: bool,
175    parts: &mut Vec<InstructionPart>,
176    _resolved: &ResolvedInstructionRef,
177    _branch_dest: &mut Option<u64>,
178) {
179    match op & 0xf000 {
180        0x7000 => {
181            // ADD #imm,Rn
182            let reg = REG_NAMES[((op >> 8) & 0xf) as usize];
183            parts.push(InstructionPart::opcode("add", Ops::AddImmRn as u16));
184            parts.push(InstructionPart::basic("#"));
185            parts.push(InstructionPart::unsigned(op & 0xff));
186            parts.push(InstructionPart::separator());
187            parts.push(InstructionPart::basic(reg));
188        }
189        0xe000 => {
190            // MOV #imm,Rn
191            let reg = REG_NAMES[((op >> 8) & 0xf) as usize];
192            parts.push(InstructionPart::opcode("mov", Ops::MovImmRn as u16));
193            parts.push(InstructionPart::basic("#"));
194            parts.push(InstructionPart::unsigned(op & 0xff));
195            parts.push(InstructionPart::separator());
196            parts.push(InstructionPart::opaque(reg));
197        }
198        _ => {
199            parts.push(InstructionPart::basic(".word 0x"));
200            parts.push(InstructionPart::basic(format!("{op:04X}")));
201            parts.push(InstructionPart::basic(" /* unknown instruction */"));
202        }
203    }
204}
205
206fn match_i_f(
207    v_addr: u32,
208    op: u16,
209    mode: bool,
210    parts: &mut Vec<InstructionPart>,
211    resolved: &ResolvedInstructionRef,
212    branch_dest: &mut Option<u64>,
213) {
214    match op & 0xff00 {
215        0xcd00 => {
216            // AND.B #imm,@(R0,GBR)
217            parts.push(InstructionPart::opcode("and.b", Ops::AndBImmAtR0Gbr as u16));
218            parts.push(InstructionPart::basic("#"));
219            parts.push(InstructionPart::unsigned(op & 0xff));
220            parts.push(InstructionPart::separator());
221            parts.push(InstructionPart::basic("@("));
222            parts.push(InstructionPart::opaque("r0"));
223            parts.push(InstructionPart::separator());
224            parts.push(InstructionPart::opaque("gbr"));
225            parts.push(InstructionPart::basic(")"));
226        }
227        0xcf00 => {
228            // OR.B #imm,@(R0,GBR)
229            parts.push(InstructionPart::opcode("or.b", Ops::OrBImmAtR0Gbr as u16));
230            parts.push(InstructionPart::basic("#"));
231            parts.push(InstructionPart::unsigned(op & 0xff));
232            parts.push(InstructionPart::separator());
233            parts.push(InstructionPart::basic("@("));
234            parts.push(InstructionPart::opaque("r0"));
235            parts.push(InstructionPart::separator());
236            parts.push(InstructionPart::opaque("gbr"));
237            parts.push(InstructionPart::basic(")"));
238        }
239        0xcc00 => {
240            // TST.B #imm,@(R0,GBR)
241            parts.push(InstructionPart::opcode("tst.b", Ops::TstBImmAtR0Gbr as u16));
242            parts.push(InstructionPart::basic("#"));
243            parts.push(InstructionPart::unsigned(op & 0xff));
244            parts.push(InstructionPart::separator());
245            parts.push(InstructionPart::basic("@("));
246            parts.push(InstructionPart::opaque("r0"));
247            parts.push(InstructionPart::separator());
248            parts.push(InstructionPart::opaque("gbr"));
249            parts.push(InstructionPart::basic(")"));
250        }
251        0xce00 => {
252            // XOR.B #imm,@(R0,GBR)
253            parts.push(InstructionPart::opcode("xor.b", Ops::XorBImmAtR0Gbr as u16));
254            parts.push(InstructionPart::basic("#"));
255            parts.push(InstructionPart::unsigned(op & 0xff));
256            parts.push(InstructionPart::separator());
257            parts.push(InstructionPart::basic("@("));
258            parts.push(InstructionPart::opaque("r0"));
259            parts.push(InstructionPart::separator());
260            parts.push(InstructionPart::opaque("gbr"));
261            parts.push(InstructionPart::basic(")"));
262        }
263        0xc900 => {
264            // AND #imm, R0
265            parts.push(InstructionPart::opcode("and", Ops::AndImmR0 as u16));
266            parts.push(InstructionPart::basic("#"));
267            parts.push(InstructionPart::unsigned(op & 0xff));
268            parts.push(InstructionPart::separator());
269            parts.push(InstructionPart::opaque("r0"));
270        }
271        0x8800 => {
272            parts.push(InstructionPart::opcode("cmp/eq", Ops::CmpEqImmR0 as u16));
273            parts.push(InstructionPart::basic("#"));
274            parts.push(InstructionPart::unsigned(op & 0xff));
275            parts.push(InstructionPart::separator());
276            parts.push(InstructionPart::opaque("r0"));
277        }
278        0xcb00 => {
279            parts.push(InstructionPart::opcode("or", Ops::OrImmR0 as u16));
280            parts.push(InstructionPart::basic("#"));
281            parts.push(InstructionPart::unsigned(op & 0xff));
282            parts.push(InstructionPart::separator());
283            parts.push(InstructionPart::opaque("r0"));
284        }
285        0xc800 => {
286            parts.push(InstructionPart::opcode("tst", Ops::TstImmR0 as u16));
287            parts.push(InstructionPart::basic("#"));
288            parts.push(InstructionPart::unsigned(op & 0xff));
289            parts.push(InstructionPart::separator());
290            parts.push(InstructionPart::opaque("r0"));
291        }
292        0xca00 => {
293            parts.push(InstructionPart::opcode("xor", Ops::XorImmR0 as u16));
294            parts.push(InstructionPart::basic("#"));
295            parts.push(InstructionPart::unsigned(op & 0xff));
296            parts.push(InstructionPart::separator());
297            parts.push(InstructionPart::opaque("r0"));
298        }
299        0xc300 => {
300            parts.push(InstructionPart::opcode("trapa", Ops::Trapa as u16));
301            parts.push(InstructionPart::basic("#"));
302            parts.push(InstructionPart::unsigned(op & 0xff));
303        }
304        _ => match_ni_f(v_addr, op, mode, parts, resolved, branch_dest),
305    }
306}
307
308fn match_nd8_f(
309    v_addr: u32,
310    op: u16,
311    mode: bool,
312    parts: &mut Vec<InstructionPart>,
313    resolved: &ResolvedInstructionRef,
314    branch_dest: &mut Option<u64>,
315) {
316    match op & 0xf000 {
317        0x9000 => {
318            parts.push(InstructionPart::opcode("mov.w", Ops::MovWAtDispPcRn as u16));
319            parts.push(InstructionPart::basic("@("));
320            if resolved.relocation.is_some() {
321                parts.push(InstructionPart::reloc());
322            } else {
323                parts.push(InstructionPart::unsigned((op & 0xff) * 2 + 4));
324            }
325            parts.push(InstructionPart::separator());
326            parts.push(InstructionPart::opaque("pc"));
327            parts.push(InstructionPart::basic(")"));
328            parts.push(InstructionPart::separator());
329            parts.push(InstructionPart::opaque(format!("r{}", (op >> 8) & 0xf)));
330        }
331        0xd000 => {
332            let mut target_a = (op as u32 & 0xff) * 4 + 4;
333            let test = (op as u32 & 0xff) * 4 + 4 + v_addr;
334
335            if (test & 3) == 2 {
336                target_a -= 2;
337            }
338            parts.push(InstructionPart::opcode("mov.l", Ops::MovLAtDispPcRn as u16));
339            parts.push(InstructionPart::basic("@("));
340            if resolved.relocation.is_some() {
341                parts.push(InstructionPart::reloc());
342            } else {
343                parts.push(InstructionPart::unsigned(target_a));
344            }
345            parts.push(InstructionPart::separator());
346            parts.push(InstructionPart::opaque("pc"));
347            parts.push(InstructionPart::basic(")"));
348            parts.push(InstructionPart::separator());
349            parts.push(InstructionPart::opaque(format!("r{}", (op >> 8) & 0xf)));
350        }
351        _ => match_i_f(v_addr, op, mode, parts, resolved, branch_dest),
352    }
353}
354
355fn match_d12_f(
356    v_addr: u32,
357    op: u16,
358    mode: bool,
359    parts: &mut Vec<InstructionPart>,
360    resolved: &ResolvedInstructionRef,
361    branch_dest: &mut Option<u64>,
362) {
363    match op & 0xf000 {
364        0xa000 => {
365            if (op & 0x800) == 0x800 {
366                let addr = ((op as u32 & 0xfff) + 0xfffff000)
367                    .wrapping_mul(2)
368                    .wrapping_add(v_addr)
369                    .wrapping_add(4);
370                *branch_dest = Some(addr as u64);
371                if resolved.relocation.is_some() {
372                    // Use the label
373                    parts.push(InstructionPart::opcode("bra", Ops::Bra as u16));
374                    parts.push(InstructionPart::reloc());
375                } else {
376                    // use an address
377                    parts.push(InstructionPart::opcode("bra", Ops::Bra as u16));
378                    parts.push(InstructionPart::unsigned(addr));
379                }
380            } else {
381                let addr = (op as u32 & 0xfff) * 2 + v_addr + 4;
382                *branch_dest = Some(addr as u64);
383
384                if resolved.relocation.is_some() {
385                    // Use the label
386                    parts.push(InstructionPart::opcode("bra", Ops::Bra as u16));
387                    parts.push(InstructionPart::reloc());
388                } else {
389                    // use an address
390                    parts.push(InstructionPart::opcode("bra", Ops::Bra as u16));
391                    parts.push(InstructionPart::unsigned(addr));
392                }
393            }
394        }
395        0xb000 => {
396            if (op & 0x800) == 0x800 {
397                let addr =
398                    ((op as u32 & 0xfff) + 0xfffff000).wrapping_mul(2).wrapping_add(v_addr) + 4;
399                *branch_dest = Some(addr as u64);
400                if resolved.relocation.is_some() {
401                    // Use the label
402                    parts.push(InstructionPart::opcode("bsr", Ops::Bsr as u16));
403                    parts.push(InstructionPart::reloc());
404                } else {
405                    // use an address
406                    parts.push(InstructionPart::opcode("bsr", Ops::Bsr as u16));
407                    parts.push(InstructionPart::unsigned(addr));
408                }
409            } else {
410                let addr = (op as u32 & 0xfff) * 2 + v_addr + 4;
411                *branch_dest = Some(addr as u64);
412                if resolved.relocation.is_some() {
413                    // Use the label
414                    parts.push(InstructionPart::opcode("bsr", Ops::Bsr as u16));
415                    parts.push(InstructionPart::reloc());
416                } else {
417                    // use an address
418                    parts.push(InstructionPart::opcode("bsr", Ops::Bsr as u16));
419                    parts.push(InstructionPart::unsigned(addr));
420                }
421            }
422        }
423        _ => match_nd8_f(v_addr, op, mode, parts, resolved, branch_dest),
424    }
425}
426
427fn match_d_f(
428    v_addr: u32,
429    op: u16,
430    mode: bool,
431    parts: &mut Vec<InstructionPart>,
432    resolved: &ResolvedInstructionRef,
433    branch_dest: &mut Option<u64>,
434) {
435    match op & 0xff00 {
436        0xc000 => {
437            parts.push(InstructionPart::opcode("mov.b", Ops::MovBR0AtDispGbr as u16));
438            parts.push(InstructionPart::opaque("r0"));
439            parts.push(InstructionPart::separator());
440            parts.push(InstructionPart::basic("@("));
441            parts.push(InstructionPart::unsigned(op & 0xff));
442            parts.push(InstructionPart::separator());
443            parts.push(InstructionPart::opaque("gbr"));
444            parts.push(InstructionPart::basic(")"));
445        }
446        0xc100 => {
447            parts.push(InstructionPart::opcode("mov.w", Ops::MovWR0AtDispGbr as u16));
448            parts.push(InstructionPart::opaque("r0"));
449            parts.push(InstructionPart::separator());
450            parts.push(InstructionPart::basic("@("));
451            parts.push(InstructionPart::unsigned((op & 0xff) * 2));
452            parts.push(InstructionPart::separator());
453            parts.push(InstructionPart::opaque("gbr"));
454            parts.push(InstructionPart::basic(")"));
455        }
456        0xc200 => {
457            parts.push(InstructionPart::opcode("mov.l", Ops::MovLR0AtDispGbr as u16));
458            parts.push(InstructionPart::opaque("r0"));
459            parts.push(InstructionPart::separator());
460            parts.push(InstructionPart::basic("@("));
461            parts.push(InstructionPart::unsigned((op & 0xff) * 4));
462            parts.push(InstructionPart::separator());
463            parts.push(InstructionPart::opaque("gbr"));
464            parts.push(InstructionPart::basic(")"));
465        }
466        0xc400 => {
467            parts.push(InstructionPart::opcode("mov.b", Ops::MovBAtDispGbrR0 as u16));
468            parts.push(InstructionPart::basic("@("));
469            parts.push(InstructionPart::unsigned(op & 0xff));
470            parts.push(InstructionPart::separator());
471            parts.push(InstructionPart::opaque("gbr"));
472            parts.push(InstructionPart::basic(")"));
473            parts.push(InstructionPart::separator());
474            parts.push(InstructionPart::opaque("r0"));
475        }
476        0xc500 => {
477            parts.push(InstructionPart::opcode("mov.w", Ops::MovWAtDispGbrR0 as u16));
478            parts.push(InstructionPart::basic("@("));
479            parts.push(InstructionPart::unsigned((op & 0xff) * 2));
480            parts.push(InstructionPart::separator());
481            parts.push(InstructionPart::opaque("gbr"));
482            parts.push(InstructionPart::basic(")"));
483            parts.push(InstructionPart::separator());
484            parts.push(InstructionPart::opaque("r0"));
485        }
486        0xc600 => {
487            parts.push(InstructionPart::opcode("mov.l", Ops::MovLAtDispGbrR0 as u16));
488            parts.push(InstructionPart::basic("@("));
489            parts.push(InstructionPart::unsigned((op & 0xff) * 4));
490            parts.push(InstructionPart::separator());
491            parts.push(InstructionPart::opaque("gbr"));
492            parts.push(InstructionPart::basic(")"));
493            parts.push(InstructionPart::separator());
494            parts.push(InstructionPart::opaque("r0"));
495        }
496        0x8b00 => {
497            let addr: u32 = if (op & 0x80) == 0x80 {
498                (((op as u32 & 0xff).wrapping_add(0xffffff00)).wrapping_mul(2))
499                    .wrapping_add(v_addr)
500                    .wrapping_add(4)
501            } else {
502                ((op as u32 & 0xff) * 2).wrapping_add(v_addr).wrapping_add(4)
503            };
504            *branch_dest = Some(addr as u64);
505            parts.push(InstructionPart::opcode("bf", Ops::Bf as u16));
506            if resolved.relocation.is_some() {
507                parts.push(InstructionPart::reloc());
508            } else {
509                parts.push(InstructionPart::unsigned(addr));
510            }
511        }
512        0x8f00 => {
513            let addr = if (op & 0x80) == 0x80 {
514                (((op as u32 & 0xff).wrapping_add(0xffffff00)).wrapping_mul(2))
515                    .wrapping_add(v_addr)
516                    .wrapping_add(4)
517            } else {
518                ((op as u32 & 0xff) * 2).wrapping_add(v_addr).wrapping_add(4)
519            };
520            *branch_dest = Some(addr as u64);
521            parts.push(InstructionPart::opcode("bf.s", Ops::Bfs as u16));
522            if resolved.relocation.is_some() {
523                parts.push(InstructionPart::reloc());
524            } else {
525                parts.push(InstructionPart::unsigned(addr));
526            }
527        }
528        0x8900 => {
529            let addr = if (op & 0x80) == 0x80 {
530                (((op as u32 & 0xff).wrapping_add(0xffffff00)).wrapping_mul(2))
531                    .wrapping_add(v_addr)
532                    .wrapping_add(4)
533            } else {
534                ((op as u32 & 0xff) * 2).wrapping_add(v_addr).wrapping_add(4)
535            };
536            *branch_dest = Some(addr as u64);
537            parts.push(InstructionPart::opcode("bt", Ops::Bt as u16));
538            if resolved.relocation.is_some() {
539                parts.push(InstructionPart::reloc());
540            } else {
541                parts.push(InstructionPart::unsigned(addr));
542            }
543        }
544        0x8d00 => {
545            let addr = if (op & 0x80) == 0x80 {
546                (((op as u32 & 0xff).wrapping_add(0xffffff00)).wrapping_mul(2))
547                    .wrapping_add(v_addr)
548                    .wrapping_add(4)
549            } else {
550                ((op as u32 & 0xff) * 2).wrapping_add(v_addr).wrapping_add(4)
551            };
552            *branch_dest = Some(addr as u64);
553            parts.push(InstructionPart::opcode("bt.s", Ops::Bts as u16));
554            if resolved.relocation.is_some() {
555                parts.push(InstructionPart::reloc());
556            } else {
557                parts.push(InstructionPart::unsigned(addr));
558            }
559        }
560        _ => match_d12_f(v_addr, op, mode, parts, resolved, branch_dest),
561    }
562}
563
564fn match_nmd_f(
565    v_addr: u32,
566    op: u16,
567    mode: bool,
568    parts: &mut Vec<InstructionPart>,
569    resolved: &ResolvedInstructionRef,
570    branch_dest: &mut Option<u64>,
571) {
572    let reg_m = REG_NAMES[((op >> 4) & 0xf) as usize];
573    let reg_n = REG_NAMES[((op >> 8) & 0xf) as usize];
574    match op & 0xf000 {
575        0x1000 => {
576            parts.push(InstructionPart::opcode("mov.l", Ops::MovLRmAtDispRn as u16));
577            parts.push(InstructionPart::basic(reg_m));
578            parts.push(InstructionPart::separator());
579            parts.push(InstructionPart::basic("@("));
580            parts.push(InstructionPart::unsigned((op & 0xf) * 4));
581            parts.push(InstructionPart::separator());
582            parts.push(InstructionPart::basic(reg_n));
583            parts.push(InstructionPart::basic(")"));
584        }
585        0x5000 => {
586            parts.push(InstructionPart::opcode("mov.l", Ops::MovLRDispRmRn as u16));
587            parts.push(InstructionPart::basic("@("));
588            parts.push(InstructionPart::unsigned((op & 0xf) * 4));
589            parts.push(InstructionPart::separator());
590            parts.push(InstructionPart::basic(reg_m));
591            parts.push(InstructionPart::basic(")"));
592            parts.push(InstructionPart::separator());
593            parts.push(InstructionPart::basic(reg_n));
594        }
595        _ => match_d_f(v_addr, op, mode, parts, resolved, branch_dest),
596    }
597}
598fn match_ff00(
599    v_addr: u32,
600    op: u16,
601    mode: bool,
602    parts: &mut Vec<InstructionPart>,
603    resolved: &ResolvedInstructionRef,
604    branch_dest: &mut Option<u64>,
605) {
606    match op & 0xff00 {
607        0x8400 => {
608            parts.push(InstructionPart::opcode("mov.b", Ops::MovBAtDispRnR0 as u16));
609            parts.push(InstructionPart::basic("@("));
610            if (op & 0x100) == 0x100 {
611                parts.push(InstructionPart::unsigned((op & 0xf) * 2));
612            } else {
613                parts.push(InstructionPart::unsigned(op & 0xf));
614            }
615            parts.push(InstructionPart::separator());
616            parts.push(InstructionPart::opaque(REG_NAMES[((op >> 4) & 0xf) as usize]));
617            parts.push(InstructionPart::basic(")"));
618            parts.push(InstructionPart::separator());
619            parts.push(InstructionPart::opaque("r0"));
620        }
621        0x8500 => {
622            parts.push(InstructionPart::opcode("mov.w", Ops::MovWAtDispRnR0 as u16));
623            parts.push(InstructionPart::basic("@("));
624            if (op & 0x100) == 0x100 {
625                parts.push(InstructionPart::unsigned((op & 0xf) * 2));
626            } else {
627                parts.push(InstructionPart::unsigned(op & 0xf));
628            }
629            parts.push(InstructionPart::separator());
630            parts.push(InstructionPart::opaque(REG_NAMES[((op >> 4) & 0xf) as usize]));
631            parts.push(InstructionPart::basic(")"));
632            parts.push(InstructionPart::separator());
633            parts.push(InstructionPart::opaque("r0"));
634        }
635        0x8000 => {
636            parts.push(InstructionPart::opcode("mov.b", Ops::MovBR0AtDispRn as u16));
637            parts.push(InstructionPart::opaque("r0"));
638            parts.push(InstructionPart::separator());
639            parts.push(InstructionPart::basic("@("));
640            if (op & 0x100) == 0x100 {
641                parts.push(InstructionPart::unsigned((op & 0xf) * 2));
642            } else {
643                parts.push(InstructionPart::unsigned(op & 0xf));
644            }
645            parts.push(InstructionPart::separator());
646            parts.push(InstructionPart::opaque(REG_NAMES[((op >> 4) & 0xf) as usize]));
647            parts.push(InstructionPart::basic(")"));
648        }
649        0x8100 => {
650            parts.push(InstructionPart::opcode("mov.w", Ops::MovWR0AtDispRn as u16));
651            parts.push(InstructionPart::opaque("r0"));
652            parts.push(InstructionPart::separator());
653            parts.push(InstructionPart::basic("@("));
654            if (op & 0x100) == 0x100 {
655                parts.push(InstructionPart::unsigned((op & 0xf) * 2));
656            } else {
657                parts.push(InstructionPart::unsigned(op & 0xf));
658            }
659            parts.push(InstructionPart::separator());
660            parts.push(InstructionPart::opaque(REG_NAMES[((op >> 4) & 0xf) as usize]));
661            parts.push(InstructionPart::basic(")"));
662        }
663        _ => match_nmd_f(v_addr, op, mode, parts, resolved, branch_dest),
664    }
665}
666
667fn match_f00f(
668    v_addr: u32,
669    op: u16,
670    mode: bool,
671    parts: &mut Vec<InstructionPart>,
672    resolved: &ResolvedInstructionRef,
673    branch_dest: &mut Option<u64>,
674) {
675    let reg_m = REG_NAMES[((op >> 4) & 0xf) as usize];
676    let reg_n = REG_NAMES[((op >> 8) & 0xf) as usize];
677
678    match op & 0xf00f {
679        0x300c => {
680            parts.push(InstructionPart::opcode("add", Ops::AddRmRn as u16));
681            parts.push(InstructionPart::opaque(reg_m));
682            parts.push(InstructionPart::separator());
683            parts.push(InstructionPart::opaque(reg_n));
684        }
685        0x300e => {
686            parts.push(InstructionPart::opcode("addc", Ops::AddcRmRn as u16));
687            parts.push(InstructionPart::opaque(reg_m));
688            parts.push(InstructionPart::separator());
689            parts.push(InstructionPart::opaque(reg_n));
690        }
691        0x300f => {
692            parts.push(InstructionPart::opcode("addv", Ops::AddvRmRn as u16));
693            parts.push(InstructionPart::opaque(reg_m));
694            parts.push(InstructionPart::separator());
695            parts.push(InstructionPart::opaque(reg_n));
696        }
697        0x2009 => {
698            parts.push(InstructionPart::opcode("and", Ops::AndRmRn as u16));
699            parts.push(InstructionPart::opaque(reg_m));
700            parts.push(InstructionPart::separator());
701            parts.push(InstructionPart::opaque(reg_n));
702        }
703        0x3000 => {
704            parts.push(InstructionPart::opcode("cmp/eq", Ops::CmpEqRmRn as u16));
705            parts.push(InstructionPart::opaque(reg_m));
706            parts.push(InstructionPart::separator());
707            parts.push(InstructionPart::opaque(reg_n));
708        }
709        0x3002 => {
710            parts.push(InstructionPart::opcode("cmp/hs", Ops::CmpHsRmRn as u16));
711            parts.push(InstructionPart::opaque(reg_m));
712            parts.push(InstructionPart::separator());
713            parts.push(InstructionPart::opaque(reg_n));
714        }
715        0x3003 => {
716            parts.push(InstructionPart::opcode("cmp/ge", Ops::CmpGeRmRn as u16));
717            parts.push(InstructionPart::opaque(reg_m));
718            parts.push(InstructionPart::separator());
719            parts.push(InstructionPart::opaque(reg_n));
720        }
721        0x3006 => {
722            parts.push(InstructionPart::opcode("cmp/hi", Ops::CmpHiRmRn as u16));
723            parts.push(InstructionPart::opaque(reg_m));
724            parts.push(InstructionPart::separator());
725            parts.push(InstructionPart::opaque(reg_n));
726        }
727        0x3007 => {
728            parts.push(InstructionPart::opcode("cmp/gt", Ops::CmpGtRmRn as u16));
729            parts.push(InstructionPart::opaque(reg_m));
730            parts.push(InstructionPart::separator());
731            parts.push(InstructionPart::opaque(reg_n));
732        }
733        0x200c => {
734            parts.push(InstructionPart::opcode("cmp/str", Ops::CmpStrRmRn as u16));
735            parts.push(InstructionPart::opaque(reg_m));
736            parts.push(InstructionPart::separator());
737            parts.push(InstructionPart::opaque(reg_n));
738        }
739        0x3004 => {
740            parts.push(InstructionPart::opcode("div1", Ops::Div1RmRn as u16));
741            parts.push(InstructionPart::opaque(reg_m));
742            parts.push(InstructionPart::separator());
743            parts.push(InstructionPart::opaque(reg_n));
744        }
745        0x2007 => {
746            parts.push(InstructionPart::opcode("div0s", Ops::Div0sRmRn as u16));
747            parts.push(InstructionPart::opaque(reg_m));
748            parts.push(InstructionPart::separator());
749            parts.push(InstructionPart::opaque(reg_n));
750        }
751        0x300d => {
752            parts.push(InstructionPart::opcode("dmuls.l", Ops::DmulsLRmRn as u16));
753            parts.push(InstructionPart::opaque(reg_m));
754            parts.push(InstructionPart::separator());
755            parts.push(InstructionPart::opaque(reg_n));
756        }
757        0x3005 => {
758            parts.push(InstructionPart::opcode("dmulu.l", Ops::DmuluLRmRn as u16));
759            parts.push(InstructionPart::opaque(reg_m));
760            parts.push(InstructionPart::separator());
761            parts.push(InstructionPart::opaque(reg_n));
762        }
763        0x600e => {
764            parts.push(InstructionPart::opcode("exts.b", Ops::ExtsBRmRn as u16));
765            parts.push(InstructionPart::opaque(reg_m));
766            parts.push(InstructionPart::separator());
767            parts.push(InstructionPart::opaque(reg_n));
768        }
769        0x600f => {
770            parts.push(InstructionPart::opcode("exts.w", Ops::ExtsWRmRn as u16));
771            parts.push(InstructionPart::opaque(reg_m));
772            parts.push(InstructionPart::separator());
773            parts.push(InstructionPart::opaque(reg_n));
774        }
775        0x600c => {
776            parts.push(InstructionPart::opcode("extu.b", Ops::ExtuBRmRn as u16));
777            parts.push(InstructionPart::opaque(reg_m));
778            parts.push(InstructionPart::separator());
779            parts.push(InstructionPart::opaque(reg_n));
780        }
781        0x600d => {
782            parts.push(InstructionPart::opcode("extu.w", Ops::ExtuWRmRn as u16));
783            parts.push(InstructionPart::opaque(reg_m));
784            parts.push(InstructionPart::separator());
785            parts.push(InstructionPart::opaque(reg_n));
786        }
787        0x6003 => {
788            parts.push(InstructionPart::opcode("mov", Ops::MovRmRn as u16));
789            parts.push(InstructionPart::opaque(reg_m));
790            parts.push(InstructionPart::separator());
791            parts.push(InstructionPart::opaque(reg_n));
792        }
793        0x0007 => {
794            parts.push(InstructionPart::opcode("mul.l", Ops::MulLRmRn as u16));
795            parts.push(InstructionPart::opaque(reg_m));
796            parts.push(InstructionPart::separator());
797            parts.push(InstructionPart::opaque(reg_n));
798        }
799        0x200f => {
800            parts.push(InstructionPart::opcode("muls", Ops::MulsRmRn as u16));
801            parts.push(InstructionPart::opaque(reg_m));
802            parts.push(InstructionPart::separator());
803            parts.push(InstructionPart::opaque(reg_n));
804        }
805        0x200e => {
806            parts.push(InstructionPart::opcode("mulu", Ops::MuluRmRn as u16));
807            parts.push(InstructionPart::opaque(reg_m));
808            parts.push(InstructionPart::separator());
809            parts.push(InstructionPart::opaque(reg_n));
810        }
811        0x600b => {
812            parts.push(InstructionPart::opcode("neg", Ops::NegRmRn as u16));
813            parts.push(InstructionPart::opaque(reg_m));
814            parts.push(InstructionPart::separator());
815            parts.push(InstructionPart::opaque(reg_n));
816        }
817        0x600a => {
818            parts.push(InstructionPart::opcode("negc", Ops::NegcRmRn as u16));
819            parts.push(InstructionPart::opaque(reg_m));
820            parts.push(InstructionPart::separator());
821            parts.push(InstructionPart::opaque(reg_n));
822        }
823        0x6007 => {
824            parts.push(InstructionPart::opcode("not", Ops::NotRmRn as u16));
825            parts.push(InstructionPart::opaque(reg_m));
826            parts.push(InstructionPart::separator());
827            parts.push(InstructionPart::opaque(reg_n));
828        }
829        0x200b => {
830            parts.push(InstructionPart::opcode("or", Ops::OrRmRn as u16));
831            parts.push(InstructionPart::opaque(reg_m));
832            parts.push(InstructionPart::separator());
833            parts.push(InstructionPart::opaque(reg_n));
834        }
835        0x3008 => {
836            parts.push(InstructionPart::opcode("sub", Ops::SubRmRn as u16));
837            parts.push(InstructionPart::opaque(reg_m));
838            parts.push(InstructionPart::separator());
839            parts.push(InstructionPart::opaque(reg_n));
840        }
841        0x300a => {
842            parts.push(InstructionPart::opcode("subc", Ops::SubcRmRn as u16));
843            parts.push(InstructionPart::opaque(reg_m));
844            parts.push(InstructionPart::separator());
845            parts.push(InstructionPart::opaque(reg_n));
846        }
847        0x300b => {
848            parts.push(InstructionPart::opcode("subv", Ops::SubvRmRn as u16));
849            parts.push(InstructionPart::opaque(reg_m));
850            parts.push(InstructionPart::separator());
851            parts.push(InstructionPart::opaque(reg_n));
852        }
853        0x6008 => {
854            parts.push(InstructionPart::opcode("swap.b", Ops::SwapBRmRn as u16));
855            parts.push(InstructionPart::opaque(reg_m));
856            parts.push(InstructionPart::separator());
857            parts.push(InstructionPart::opaque(reg_n));
858        }
859        0x6009 => {
860            parts.push(InstructionPart::opcode("swap.w", Ops::SwapWRmRn as u16));
861            parts.push(InstructionPart::opaque(reg_m));
862            parts.push(InstructionPart::separator());
863            parts.push(InstructionPart::opaque(reg_n));
864        }
865        0x2008 => {
866            parts.push(InstructionPart::opcode("tst", Ops::TstRmRn as u16));
867            parts.push(InstructionPart::opaque(reg_m));
868            parts.push(InstructionPart::separator());
869            parts.push(InstructionPart::opaque(reg_n));
870        }
871        0x200a => {
872            parts.push(InstructionPart::opcode("xor", Ops::XorRmRn as u16));
873            parts.push(InstructionPart::opaque(reg_m));
874            parts.push(InstructionPart::separator());
875            parts.push(InstructionPart::opaque(reg_n));
876        }
877        0x200d => {
878            parts.push(InstructionPart::opcode("xtrct", Ops::XtrctRmRn as u16));
879            parts.push(InstructionPart::opaque(reg_m));
880            parts.push(InstructionPart::separator());
881            parts.push(InstructionPart::opaque(reg_n));
882        }
883        0x2000 => {
884            parts.push(InstructionPart::opcode("mov.b", Ops::MovBRmAtRn as u16));
885            parts.push(InstructionPart::opaque(reg_m));
886            parts.push(InstructionPart::separator());
887            parts.push(InstructionPart::basic("@"));
888            parts.push(InstructionPart::opaque(reg_n));
889        }
890        0x2001 => {
891            parts.push(InstructionPart::opcode("mov.w", Ops::MovWRmAtRn as u16));
892            parts.push(InstructionPart::opaque(reg_m));
893            parts.push(InstructionPart::separator());
894            parts.push(InstructionPart::basic("@"));
895            parts.push(InstructionPart::opaque(reg_n));
896        }
897        0x2002 => {
898            parts.push(InstructionPart::opcode("mov.l", Ops::MovLRmAtRn as u16));
899            parts.push(InstructionPart::opaque(reg_m));
900            parts.push(InstructionPart::separator());
901            parts.push(InstructionPart::basic("@"));
902            parts.push(InstructionPart::opaque(reg_n));
903        }
904        0x6000 => {
905            parts.push(InstructionPart::opcode("mov.b", Ops::MovBAtRmRn as u16));
906            parts.push(InstructionPart::basic("@"));
907            parts.push(InstructionPart::opaque(reg_m));
908            parts.push(InstructionPart::separator());
909            parts.push(InstructionPart::opaque(reg_n));
910        }
911        0x6001 => {
912            parts.push(InstructionPart::opcode("mov.w", Ops::MovWAtRmRn as u16));
913            parts.push(InstructionPart::basic("@"));
914            parts.push(InstructionPart::opaque(reg_m));
915            parts.push(InstructionPart::separator());
916            parts.push(InstructionPart::opaque(reg_n));
917        }
918        0x6002 => {
919            parts.push(InstructionPart::opcode("mov.l", Ops::MovLAtRmRn as u16));
920            parts.push(InstructionPart::basic("@"));
921            parts.push(InstructionPart::opaque(reg_m));
922            parts.push(InstructionPart::separator());
923            parts.push(InstructionPart::opaque(reg_n));
924        }
925        0x000f => {
926            parts.push(InstructionPart::opcode("mac.l", Ops::MacLAtRmIncAtRnInc as u16));
927            parts.push(InstructionPart::basic("@"));
928            parts.push(InstructionPart::opaque(reg_m));
929            parts.push(InstructionPart::basic("+"));
930            parts.push(InstructionPart::separator());
931            parts.push(InstructionPart::basic("@"));
932            parts.push(InstructionPart::opaque(reg_n));
933            parts.push(InstructionPart::basic("+"));
934        }
935        0x400f => {
936            parts.push(InstructionPart::opcode("mac.w", Ops::MacWAtRmIncAtRnInc as u16));
937            parts.push(InstructionPart::basic("@"));
938            parts.push(InstructionPart::opaque(reg_m));
939            parts.push(InstructionPart::basic("+"));
940            parts.push(InstructionPart::separator());
941            parts.push(InstructionPart::basic("@"));
942            parts.push(InstructionPart::opaque(reg_n));
943            parts.push(InstructionPart::basic("+"));
944        }
945        0x6004 => {
946            parts.push(InstructionPart::opcode("mov.b", Ops::MovBAtRmIncRn as u16));
947            parts.push(InstructionPart::basic("@"));
948            parts.push(InstructionPart::opaque(reg_m));
949            parts.push(InstructionPart::basic("+"));
950            parts.push(InstructionPart::separator());
951            parts.push(InstructionPart::opaque(reg_n));
952        }
953        0x6005 => {
954            parts.push(InstructionPart::opcode("mov.w", Ops::MovWAtRmIncRn as u16));
955            parts.push(InstructionPart::basic("@"));
956            parts.push(InstructionPart::opaque(reg_m));
957            parts.push(InstructionPart::basic("+"));
958            parts.push(InstructionPart::separator());
959            parts.push(InstructionPart::opaque(reg_n));
960        }
961        0x6006 => {
962            parts.push(InstructionPart::opcode("mov.l", Ops::MovLAtRmIncRn as u16));
963            parts.push(InstructionPart::basic("@"));
964            parts.push(InstructionPart::opaque(reg_m));
965            parts.push(InstructionPart::basic("+"));
966            parts.push(InstructionPart::separator());
967            parts.push(InstructionPart::opaque(reg_n));
968        }
969        0x2004 => {
970            parts.push(InstructionPart::opcode("mov.b", Ops::MovBRmAtDecRn as u16));
971            parts.push(InstructionPart::opaque(reg_m));
972            parts.push(InstructionPart::separator());
973            parts.push(InstructionPart::basic("@-"));
974            parts.push(InstructionPart::opaque(reg_n));
975        }
976        0x2005 => {
977            parts.push(InstructionPart::opcode("mov.w", Ops::MovWRmAtDecRn as u16));
978            parts.push(InstructionPart::opaque(reg_m));
979            parts.push(InstructionPart::separator());
980            parts.push(InstructionPart::basic("@-"));
981            parts.push(InstructionPart::opaque(reg_n));
982        }
983        0x2006 => {
984            parts.push(InstructionPart::opcode("mov.l", Ops::MovLRmAtDecRn as u16));
985            parts.push(InstructionPart::opaque(reg_m));
986            parts.push(InstructionPart::separator());
987            parts.push(InstructionPart::basic("@-"));
988            parts.push(InstructionPart::opaque(reg_n));
989        }
990        0x0004 => {
991            parts.push(InstructionPart::opcode("mov.b", Ops::MovBRmAtR0Rn as u16));
992            parts.push(InstructionPart::opaque(reg_m));
993            parts.push(InstructionPart::separator());
994            parts.push(InstructionPart::basic("@("));
995            parts.push(InstructionPart::opaque("r0"));
996            parts.push(InstructionPart::separator());
997            parts.push(InstructionPart::opaque(reg_n));
998            parts.push(InstructionPart::basic(")"));
999        }
1000        0x0005 => {
1001            parts.push(InstructionPart::opcode("mov.w", Ops::MovWRmAtR0Rn as u16));
1002            parts.push(InstructionPart::opaque(reg_m));
1003            parts.push(InstructionPart::separator());
1004            parts.push(InstructionPart::basic("@("));
1005            parts.push(InstructionPart::opaque("r0"));
1006            parts.push(InstructionPart::separator());
1007            parts.push(InstructionPart::opaque(reg_n));
1008            parts.push(InstructionPart::basic(")"));
1009        }
1010        0x0006 => {
1011            parts.push(InstructionPart::opcode("mov.l", Ops::MovLRmAtR0Rn as u16));
1012            parts.push(InstructionPart::opaque(reg_m));
1013            parts.push(InstructionPart::separator());
1014            parts.push(InstructionPart::basic("@("));
1015            parts.push(InstructionPart::opaque("r0"));
1016            parts.push(InstructionPart::separator());
1017            parts.push(InstructionPart::opaque(reg_n));
1018            parts.push(InstructionPart::basic(")"));
1019        }
1020        0x000c => {
1021            parts.push(InstructionPart::opcode("mov.b", Ops::MovBAtR0RmRn as u16));
1022            parts.push(InstructionPart::basic("@("));
1023            parts.push(InstructionPart::opaque("r0"));
1024            parts.push(InstructionPart::separator());
1025            parts.push(InstructionPart::opaque(reg_m));
1026            parts.push(InstructionPart::basic(")"));
1027            parts.push(InstructionPart::separator());
1028            parts.push(InstructionPart::opaque(reg_n));
1029        }
1030        0x000d => {
1031            parts.push(InstructionPart::opcode("mov.w", Ops::MovWAtR0RmRn as u16));
1032            parts.push(InstructionPart::basic("@("));
1033            parts.push(InstructionPart::opaque("r0"));
1034            parts.push(InstructionPart::separator());
1035            parts.push(InstructionPart::opaque(reg_m));
1036            parts.push(InstructionPart::basic(")"));
1037            parts.push(InstructionPart::separator());
1038            parts.push(InstructionPart::opaque(reg_n));
1039        }
1040        0x000e => {
1041            parts.push(InstructionPart::opcode("mov.l", Ops::MovLAtR0RmRn as u16));
1042            parts.push(InstructionPart::basic("@("));
1043            parts.push(InstructionPart::opaque("r0"));
1044            parts.push(InstructionPart::separator());
1045            parts.push(InstructionPart::opaque(reg_m));
1046            parts.push(InstructionPart::basic(")"));
1047            parts.push(InstructionPart::separator());
1048            parts.push(InstructionPart::opaque(reg_n));
1049        }
1050        _ => match_ff00(v_addr, op, mode, parts, resolved, branch_dest),
1051    }
1052}
1053
1054fn match_f0ff(
1055    v_addr: u32,
1056    op: u16,
1057    mode: bool,
1058    parts: &mut Vec<InstructionPart>,
1059    resolved: &ResolvedInstructionRef,
1060    branch_dest: &mut Option<u64>,
1061) {
1062    let reg = REG_NAMES[((op >> 8) & 0xf) as usize];
1063    match op & 0xf0ff {
1064        0x4015 => {
1065            // CMP/PL Rn
1066            parts.push(InstructionPart::opcode("cmp/pl", Ops::CmpPlRn as u16));
1067            parts.push(InstructionPart::opaque(reg));
1068        }
1069        0x4011 => {
1070            // CMP/PZ Rn
1071            parts.push(InstructionPart::opcode("cmp/pz", Ops::CmpPzRn as u16));
1072            parts.push(InstructionPart::opaque(reg));
1073        }
1074        0x4010 => {
1075            // DT Rn
1076            parts.push(InstructionPart::opcode("dt", Ops::DtRn as u16));
1077            parts.push(InstructionPart::opaque(reg));
1078        }
1079        0x0029 => {
1080            // MOVT Rn
1081            parts.push(InstructionPart::opcode("movt", Ops::MovtRn as u16));
1082            parts.push(InstructionPart::opaque(reg));
1083        }
1084        0x4004 => {
1085            // ROTL Rn
1086            parts.push(InstructionPart::opcode("rotl", Ops::RotlRn as u16));
1087            parts.push(InstructionPart::opaque(reg));
1088        }
1089        0x4005 => {
1090            // ROTR Rn
1091            parts.push(InstructionPart::opcode("rotr", Ops::RotrRn as u16));
1092            parts.push(InstructionPart::opaque(reg));
1093        }
1094        0x4024 => {
1095            // ROTCL Rn
1096            parts.push(InstructionPart::opcode("rotcl", Ops::RotclRn as u16));
1097            parts.push(InstructionPart::opaque(reg));
1098        }
1099        0x4025 => {
1100            // ROTCR Rn
1101            parts.push(InstructionPart::opcode("rotcr", Ops::RotcrRn as u16));
1102            parts.push(InstructionPart::opaque(reg));
1103        }
1104        0x4020 => {
1105            // SHAL Rn
1106            parts.push(InstructionPart::opcode("shal", Ops::ShalRn as u16));
1107            parts.push(InstructionPart::opaque(reg));
1108        }
1109        0x4021 => {
1110            // SHAR Rn
1111            parts.push(InstructionPart::opcode("shar", Ops::SharRn as u16));
1112            parts.push(InstructionPart::opaque(reg));
1113        }
1114        0x4000 => {
1115            // SHLL Rn
1116            parts.push(InstructionPart::opcode("shll", Ops::ShllRn as u16));
1117            parts.push(InstructionPart::opaque(reg));
1118        }
1119        0x4001 => {
1120            // SHLR Rn
1121            parts.push(InstructionPart::opcode("shlr", Ops::ShlrRn as u16));
1122            parts.push(InstructionPart::opaque(reg));
1123        }
1124        0x4008 => {
1125            // SHLL2 Rn
1126            parts.push(InstructionPart::opcode("shll2", Ops::Shll2Rn as u16));
1127            parts.push(InstructionPart::opaque(reg));
1128        }
1129        0x4009 => {
1130            // SHLR2 Rn
1131            parts.push(InstructionPart::opcode("shlr2", Ops::Shlr2Rn as u16));
1132            parts.push(InstructionPart::opaque(reg));
1133        }
1134        0x4018 => {
1135            // SHLL8 Rn
1136            parts.push(InstructionPart::opcode("shll8", Ops::Shll8Rn as u16));
1137            parts.push(InstructionPart::opaque(reg));
1138        }
1139        0x4019 => {
1140            // SHLR8 Rn
1141            parts.push(InstructionPart::opcode("shlr8", Ops::Shlr8Rn as u16));
1142            parts.push(InstructionPart::opaque(reg));
1143        }
1144        0x4028 => {
1145            // SHLL16 Rn
1146            parts.push(InstructionPart::opcode("shll16", Ops::Shll16Rn as u16));
1147            parts.push(InstructionPart::opaque(reg));
1148        }
1149        0x4029 => {
1150            // SHLR16 Rn
1151            parts.push(InstructionPart::opcode("shlr16", Ops::Shlr16Rn as u16));
1152            parts.push(InstructionPart::opaque(reg));
1153        }
1154        0x0002 => {
1155            // STC SR,Rn
1156            parts.push(InstructionPart::opcode("stc", Ops::StcSrRn as u16));
1157            parts.push(InstructionPart::opaque("sr"));
1158            parts.push(InstructionPart::separator());
1159            parts.push(InstructionPart::opaque(reg));
1160        }
1161        0x0012 => {
1162            // STC GBR,Rn
1163            parts.push(InstructionPart::opcode("stc", Ops::StcGbrRn as u16));
1164            parts.push(InstructionPart::opaque("gbr"));
1165            parts.push(InstructionPart::separator());
1166            parts.push(InstructionPart::opaque(reg));
1167        }
1168        0x0022 => {
1169            // STC VBR,Rn
1170            parts.push(InstructionPart::opcode("stc", Ops::StcVbrRn as u16));
1171            parts.push(InstructionPart::opaque("vbr"));
1172            parts.push(InstructionPart::separator());
1173            parts.push(InstructionPart::opaque(reg));
1174        }
1175        0x000a => {
1176            // STS MACH,Rn
1177            parts.push(InstructionPart::opcode("sts", Ops::StsMachRn as u16));
1178            parts.push(InstructionPart::opaque("mach"));
1179            parts.push(InstructionPart::separator());
1180            parts.push(InstructionPart::opaque(reg));
1181        }
1182        0x001a => {
1183            // STS MACL,Rn
1184            parts.push(InstructionPart::opcode("sts", Ops::StsMaclRn as u16));
1185            parts.push(InstructionPart::opaque("macl"));
1186            parts.push(InstructionPart::separator());
1187            parts.push(InstructionPart::opaque(reg));
1188        }
1189        0x002a => {
1190            // STS PR,Rn
1191            parts.push(InstructionPart::opcode("sts", Ops::StsPrRn as u16));
1192            parts.push(InstructionPart::opaque("pr"));
1193            parts.push(InstructionPart::separator());
1194            parts.push(InstructionPart::opaque(reg));
1195        }
1196        0x401b => {
1197            // TAS.B
1198            parts.push(InstructionPart::opcode("tas.b", Ops::TasB as u16));
1199            parts.push(InstructionPart::opaque(reg));
1200        }
1201        0x4003 => {
1202            parts.push(InstructionPart::opcode("stc.l", Ops::StcLSrAtDecrementRn as u16));
1203            parts.push(InstructionPart::opaque("sr"));
1204            parts.push(InstructionPart::separator());
1205            parts.push(InstructionPart::basic("@-"));
1206            parts.push(InstructionPart::opaque(reg));
1207        }
1208        0x4013 => {
1209            parts.push(InstructionPart::opcode("stc.l", Ops::StcLGbrAtDecrementRn as u16));
1210            parts.push(InstructionPart::opaque("gbr"));
1211            parts.push(InstructionPart::separator());
1212            parts.push(InstructionPart::basic("@-"));
1213            parts.push(InstructionPart::opaque(reg));
1214        }
1215        0x4023 => {
1216            parts.push(InstructionPart::opcode("stc.l", Ops::StcLVbrAtDecrementRn as u16));
1217            parts.push(InstructionPart::opaque("vbr"));
1218            parts.push(InstructionPart::separator());
1219            parts.push(InstructionPart::basic("@-"));
1220            parts.push(InstructionPart::opaque(reg));
1221        }
1222        0x4002 => {
1223            parts.push(InstructionPart::opcode("sts.l", Ops::StsLMachAtDecrementRn as u16));
1224            parts.push(InstructionPart::opaque("mach"));
1225            parts.push(InstructionPart::separator());
1226            parts.push(InstructionPart::basic("@-"));
1227            parts.push(InstructionPart::opaque(reg));
1228        }
1229        0x4012 => {
1230            parts.push(InstructionPart::opcode("sts.l", Ops::StsLMaclAtDecrementRn as u16));
1231            parts.push(InstructionPart::opaque("macl"));
1232            parts.push(InstructionPart::separator());
1233            parts.push(InstructionPart::basic("@-"));
1234            parts.push(InstructionPart::opaque(reg));
1235        }
1236        0x4022 => {
1237            parts.push(InstructionPart::opcode("sts.l", Ops::StsLPrAtDecrementRn as u16));
1238            parts.push(InstructionPart::opaque("pr"));
1239            parts.push(InstructionPart::separator());
1240            parts.push(InstructionPart::basic("@-"));
1241            parts.push(InstructionPart::opaque(reg));
1242        }
1243        0x400e => {
1244            parts.push(InstructionPart::opcode("ldc", Ops::LdcRnSr as u16));
1245            parts.push(InstructionPart::opaque(reg));
1246            parts.push(InstructionPart::separator());
1247            parts.push(InstructionPart::opaque("sr"));
1248        }
1249        0x401e => {
1250            parts.push(InstructionPart::opcode("ldc", Ops::LdcRnGbr as u16));
1251            parts.push(InstructionPart::opaque(reg));
1252            parts.push(InstructionPart::separator());
1253            parts.push(InstructionPart::opaque("gbr"));
1254        }
1255        0x402e => {
1256            parts.push(InstructionPart::opcode("ldc", Ops::LdcRnVbr as u16));
1257            parts.push(InstructionPart::opaque(reg));
1258            parts.push(InstructionPart::separator());
1259            parts.push(InstructionPart::opaque("vbr"));
1260        }
1261        0x400a => {
1262            parts.push(InstructionPart::opcode("lds", Ops::LdsRnMach as u16));
1263            parts.push(InstructionPart::opaque(reg));
1264            parts.push(InstructionPart::separator());
1265            parts.push(InstructionPart::opaque("mach"));
1266        }
1267        0x401a => {
1268            parts.push(InstructionPart::opcode("lds", Ops::LdsRnMacl as u16));
1269            parts.push(InstructionPart::opaque(reg));
1270            parts.push(InstructionPart::separator());
1271            parts.push(InstructionPart::opaque("macl"));
1272        }
1273        0x402a => {
1274            parts.push(InstructionPart::opcode("lds", Ops::LdsRnPr as u16));
1275            parts.push(InstructionPart::opaque(reg));
1276            parts.push(InstructionPart::separator());
1277            parts.push(InstructionPart::opaque("pr"));
1278        }
1279        0x402b => {
1280            parts.push(InstructionPart::opcode("jmp", Ops::JmpAtRn as u16));
1281            parts.push(InstructionPart::basic("@"));
1282            parts.push(InstructionPart::opaque(reg));
1283        }
1284        0x400b => {
1285            parts.push(InstructionPart::opcode("jsr", Ops::JsrAtRn as u16));
1286            parts.push(InstructionPart::basic("@"));
1287            parts.push(InstructionPart::opaque(reg));
1288        }
1289        0x4007 => {
1290            parts.push(InstructionPart::opcode("ldc.l", Ops::LdcLAtRnIncSr as u16));
1291            parts.push(InstructionPart::basic("@"));
1292            parts.push(InstructionPart::opaque(reg));
1293            parts.push(InstructionPart::basic("+"));
1294            parts.push(InstructionPart::separator());
1295            parts.push(InstructionPart::opaque("sr"));
1296        }
1297        0x4017 => {
1298            parts.push(InstructionPart::opcode("ldc.l", Ops::LdcLAtRnIncGbr as u16));
1299            parts.push(InstructionPart::basic("@"));
1300            parts.push(InstructionPart::opaque(reg));
1301            parts.push(InstructionPart::basic("+"));
1302            parts.push(InstructionPart::separator());
1303            parts.push(InstructionPart::opaque("gbr"));
1304        }
1305        0x4027 => {
1306            parts.push(InstructionPart::opcode("ldc.l", Ops::LdcLAtRnIncVbr as u16));
1307            parts.push(InstructionPart::basic("@"));
1308            parts.push(InstructionPart::opaque(reg));
1309            parts.push(InstructionPart::basic("+"));
1310            parts.push(InstructionPart::separator());
1311            parts.push(InstructionPart::opaque("vbr"));
1312        }
1313        0x4006 => {
1314            parts.push(InstructionPart::opcode("lds.l", Ops::LdsLAtRnIncMach as u16));
1315            parts.push(InstructionPart::basic("@"));
1316            parts.push(InstructionPart::opaque(reg));
1317            parts.push(InstructionPart::basic("+"));
1318            parts.push(InstructionPart::separator());
1319            parts.push(InstructionPart::opaque("mach"));
1320        }
1321        0x4016 => {
1322            parts.push(InstructionPart::opcode("lds.l", Ops::LdsLAtRnIncMacl as u16));
1323            parts.push(InstructionPart::basic("@"));
1324            parts.push(InstructionPart::opaque(reg));
1325            parts.push(InstructionPart::basic("+"));
1326            parts.push(InstructionPart::separator());
1327            parts.push(InstructionPart::opaque("macl"));
1328        }
1329        0x4026 => {
1330            parts.push(InstructionPart::opcode("lds.l", Ops::LdsLAtRnIncPr as u16));
1331            parts.push(InstructionPart::basic("@"));
1332            parts.push(InstructionPart::opaque(reg));
1333            parts.push(InstructionPart::basic("+"));
1334            parts.push(InstructionPart::separator());
1335            parts.push(InstructionPart::opaque("pr"));
1336        }
1337        0x0023 => {
1338            parts.push(InstructionPart::opcode("braf", Ops::BrafRn as u16));
1339            parts.push(InstructionPart::opaque(reg));
1340        }
1341        0x0003 => {
1342            parts.push(InstructionPart::opcode("bsrf", Ops::BsrfRn as u16));
1343            parts.push(InstructionPart::opaque(reg));
1344        }
1345        _ => {
1346            match_f00f(v_addr, op, mode, parts, resolved, branch_dest);
1347        }
1348    }
1349}
1350
1351pub fn sh2_disasm(
1352    v_addr: u32,
1353    op: u16,
1354    mode: bool,
1355    parts: &mut Vec<InstructionPart>,
1356    resolved: &ResolvedInstructionRef,
1357    branch_dest: &mut Option<u64>,
1358) {
1359    match op {
1360        0x0008 => parts.push(InstructionPart::opcode("clrt", Ops::Clrt as u16)),
1361        0x0028 => parts.push(InstructionPart::opcode("clrmac", Ops::Clrmac as u16)),
1362        0x0019 => parts.push(InstructionPart::opcode("div0u", Ops::Div0u as u16)),
1363        0x0009 => parts.push(InstructionPart::opcode("nop", Ops::Nop as u16)),
1364        0x002b => parts.push(InstructionPart::opcode("rte", Ops::Rte as u16)),
1365        0x000b => parts.push(InstructionPart::opcode("rts", Ops::Rts as u16)),
1366        0x0018 => parts.push(InstructionPart::opcode("sett", Ops::Sett as u16)),
1367        0x001b => parts.push(InstructionPart::opcode("sleep", Ops::Sleep as u16)),
1368        _ => {
1369            match_f0ff(v_addr, op, mode, parts, resolved, branch_dest);
1370        }
1371    }
1372}