1use crate::instruction::{Direction, Instruction};
8use crate::isa::Isa;
9use crate::status_register::disassemble_conditional_test;
10use crate::utils::bits;
11
12pub fn disassemble_unknown_instruction(inst: &Instruction) -> String {
13 format!("Unknown instruction {:04X} at {:#X}", inst.opcode, inst.pc)
14}
15
16pub fn disassemble_abcd(inst: &Instruction) -> String {
17 let (rx, _, mode, ry) = inst.operands.register_size_mode_register();
18 if mode == Direction::MemoryToMemory {
19 format!("ABCD -(A{}), -(A{})", ry, rx)
20 } else {
21 format!("ABCD D{}, D{}", ry, rx)
22 }
23}
24
25pub fn disassemble_add(inst: &Instruction) -> String {
26 let (r, d, s, am) = inst.operands.register_direction_size_effective_address();
27 if d == Direction::DstEa {
28 format!("ADD.{} D{}, {}", s, r, am)
29 } else {
30 format!("ADD.{} {}, D{}", s, am, r)
31 }
32}
33
34pub fn disassemble_adda(inst: &Instruction) -> String {
35 let (r, s, am) = inst.operands.register_size_effective_address();
36 format!("ADDA.{} {}, A{}", s, am, r)
37}
38
39pub fn disassemble_addi(inst: &Instruction) -> String {
40 let (s, am, imm) = inst.operands.size_effective_address_immediate();
41 format!("ADDI.{} #{}, {}", s, imm, am)
42}
43
44pub fn disassemble_addq(inst: &Instruction) -> String {
45 let (d, s, am) = inst.operands.data_size_effective_address();
46 let d = if d == 0 { 8 } else { d };
47 format!("ADDQ.{} #{}, {}", s, d, am)
48}
49
50pub fn disassemble_addx(inst: &Instruction) -> String {
51 let (rx, s, mode, ry) = inst.operands.register_size_mode_register();
52 if mode == Direction::MemoryToMemory {
53 format!("ADDX.{} -(A{}), -(A{})", s, ry, rx)
54 } else {
55 format!("ADDX.{} D{}, D{}", s, ry, rx)
56 }
57}
58
59pub fn disassemble_and(inst: &Instruction) -> String {
60 let (r, d, s, am) = inst.operands.register_direction_size_effective_address();
61 if d == Direction::DstEa {
62 format!("AND.{} D{}, {}", s, r, am)
63 } else {
64 format!("AND.{} {}, D{}", s, am, r)
65 }
66}
67
68pub fn disassemble_andi(inst: &Instruction) -> String {
69 let (s, am, imm) = inst.operands.size_effective_address_immediate();
70 format!("ANDI.{} #{}, {}", s, imm, am)
71}
72
73pub fn disassemble_andiccr(inst: &Instruction) -> String {
74 let imm = inst.operands.immediate();
75 format!("ANDI {:#X}, CCR", imm)
76}
77
78pub fn disassemble_andisr(inst: &Instruction) -> String {
79 let imm = inst.operands.immediate();
80 format!("ANDI {:#X}, SR", imm)
81}
82
83pub fn disassemble_asm(inst: &Instruction) -> String {
84 let (d, am) = inst.operands.direction_effective_address();
85 format!("AS{} {}", d, am)
86}
87
88pub fn disassemble_asr(inst: &Instruction) -> String {
89 let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
90 if ir {
91 format!("AS{}.{} D{}, D{}", d, s, rot, reg)
92 } else {
93 let rot = if rot == 0 { 8 } else { rot };
94 format!("AS{}.{} #{}, D{}", d, s, rot, reg)
95 }
96}
97
98pub fn disassemble_bcc(inst: &Instruction) -> String {
99 let (cc, disp) = inst.operands.condition_displacement();
100 format!("B{} {} <{:#X}>", disassemble_conditional_test(cc), disp, inst.pc.wrapping_add(2).wrapping_add(disp as u32))
101}
102
103pub fn disassemble_bchg(inst: &Instruction) -> String {
104 let (am, count) = inst.operands.effective_address_count();
105 if bits(inst.opcode, 8, 8) != 0 {
106 format!("BCHG D{}, {}", count, am)
107 } else {
108 format!("BCHG #{}, {}", count, am)
109 }
110}
111
112pub fn disassemble_bclr(inst: &Instruction) -> String {
113 let (am, count) = inst.operands.effective_address_count();
114 if bits(inst.opcode, 8, 8) != 0 {
115 format!("BCLR D{}, {}", count, am)
116 } else {
117 format!("BCLR #{}, {}", count, am)
118 }
119}
120
121pub fn disassemble_bra(inst: &Instruction) -> String {
122 let disp = inst.operands.displacement();
123 format!("BRA {} <{:#X}>", disp, inst.pc.wrapping_add(2).wrapping_add(disp as u32))
124}
125
126pub fn disassemble_bset(inst: &Instruction) -> String {
127 let (am, count) = inst.operands.effective_address_count();
128 if bits(inst.opcode, 8, 8) != 0 {
129 format!("BSET D{}, {}", count, am)
130 } else {
131 format!("BSET #{}, {}", count, am)
132 }
133}
134
135pub fn disassemble_bsr(inst: &Instruction) -> String {
136 let disp = inst.operands.displacement();
137 format!("BSR {} <{:#X}>", disp, inst.pc.wrapping_add(2).wrapping_add(disp as u32))
138}
139
140pub fn disassemble_btst(inst: &Instruction) -> String {
141 let (am, count) = inst.operands.effective_address_count();
142 if bits(inst.opcode, 8, 8) != 0 {
143 format!("BTST D{}, {}", count, am)
144 } else {
145 format!("BTST #{}, {}", count, am)
146 }
147}
148
149pub fn disassemble_chk(inst: &Instruction) -> String {
150 let (r, am) = inst.operands.register_effective_address();
151 format!("CHK.W {}, D{}", am, r)
152}
153
154pub fn disassemble_clr(inst: &Instruction) -> String {
155 let (s, am) = inst.operands.size_effective_address();
156 format!("CLR.{} {}", s, am)
157}
158
159pub fn disassemble_cmp(inst: &Instruction) -> String {
160 let (r, _, s, am) = inst.operands.register_direction_size_effective_address();
161 format!("CMP.{} {}, D{}", s, am, r)
162}
163
164pub fn disassemble_cmpa(inst: &Instruction) -> String {
165 let (r, s, am) = inst.operands.register_size_effective_address();
166 format!("CMPA.{} {}, A{}", s, am, r)
167}
168
169pub fn disassemble_cmpi(inst: &Instruction) -> String {
170 let (s, am, imm) = inst.operands.size_effective_address_immediate();
171 format!("CMPI.{} #{}, {}", s, imm, am)
172}
173
174pub fn disassemble_cmpm(inst: &Instruction) -> String {
175 let (rx, s, ry) = inst.operands.register_size_register();
176 format!("CMPM.{} (A{})+, (A{})+", s, ry, rx)
177}
178
179pub fn disassemble_dbcc(inst: &Instruction) -> String {
180 let (cc, r, disp) = inst.operands.condition_register_displacement();
181 format!("DB{} D{}, {} <{:#X}>", disassemble_conditional_test(cc), r, disp, inst.pc.wrapping_add(2).wrapping_add(disp as u32))
182}
183
184pub fn disassemble_divs(inst: &Instruction) -> String {
185 let (r, am) = inst.operands.register_effective_address();
186 format!("DIVS.W {}, D{}", am, r)
187}
188
189pub fn disassemble_divu(inst: &Instruction) -> String {
190 let (r, am) = inst.operands.register_effective_address();
191 format!("DIVU.W {}, D{}", am, r)
192}
193
194pub fn disassemble_eor(inst: &Instruction) -> String {
195 let (r, _, s, am) = inst.operands.register_direction_size_effective_address();
196 format!("EOR.{} D{}, {}", s, r, am)
197}
198
199pub fn disassemble_eori(inst: &Instruction) -> String {
200 let (s, am, imm) = inst.operands.size_effective_address_immediate();
201 format!("EORI.{} #{}, {}", s, imm, am)
202}
203
204pub fn disassemble_eoriccr(inst: &Instruction) -> String {
205 let imm = inst.operands.immediate();
206 format!("EORI {:#X}, CCR", imm)
207}
208
209pub fn disassemble_eorisr(inst: &Instruction) -> String {
210 let imm = inst.operands.immediate();
211 format!("EORI {:#X}, SR", imm)
212}
213
214pub fn disassemble_exg(inst: &Instruction) -> String {
215 let (rx, mode, ry) = inst.operands.register_opmode_register();
216 if mode == Direction::ExchangeData {
217 format!("EXG D{}, D{}", rx, ry)
218 } else if mode == Direction::ExchangeAddress {
219 format!("EXG A{}, A{}", rx, ry)
220 } else {
221 format!("EXG D{}, A{}", rx, ry)
222 }
223}
224
225pub fn disassemble_ext(inst: &Instruction) -> String {
226 let (mode, r) = inst.operands.opmode_register();
227 if mode == 0b010 {
228 format!("EXT.W D{}", r)
229 } else {
230 format!("EXT.L D{}", r)
231 }
232}
233
234pub fn disassemble_illegal(_: &Instruction) -> String {
235 "ILLEGAL".to_string()
236}
237
238pub fn disassemble_jmp(inst: &Instruction) -> String {
239 let am = inst.operands.effective_address();
240 format!("JMP {}", am)
241}
242
243pub fn disassemble_jsr(inst: &Instruction) -> String {
244 let am = inst.operands.effective_address();
245 format!("JSR {}", am)
246}
247
248pub fn disassemble_lea(inst: &Instruction) -> String {
249 let (r, am) = inst.operands.register_effective_address();
250 format!("LEA {}, A{}", am, r)
251}
252
253pub fn disassemble_link(inst: &Instruction) -> String {
254 let (r, disp) = inst.operands.register_displacement();
255 format!("LINK.W A{}, #{}", r, disp)
256}
257
258pub fn disassemble_lsm(inst: &Instruction) -> String {
259 let (d, am) = inst.operands.direction_effective_address();
260 format!("LS{} {}", d, am)
261}
262
263pub fn disassemble_lsr(inst: &Instruction) -> String {
264 let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
265 if ir {
266 format!("LS{}.{} D{}, D{}", d, s, rot, reg)
267 } else {
268 let rot = if rot == 0 { 8 } else { rot };
269 format!("LS{}.{} #{}, D{}", d, s, rot, reg)
270 }
271}
272
273pub fn disassemble_move(inst: &Instruction) -> String {
274 let (s, dst, src) = inst.operands.size_effective_address_effective_address();
275 format!("MOVE.{} {}, {}", s, src, dst)
276}
277
278pub fn disassemble_movea(inst: &Instruction) -> String {
279 let (s, r, am) = inst.operands.size_register_effective_address();
280 format!("MOVEA.{} {:#X}, A{}", s, am, r)
281}
282
283pub fn disassemble_moveccr(inst: &Instruction) -> String {
284 let am = inst.operands.effective_address();
285 format!("MOVE {:#X}, CCR", am)
286}
287
288pub fn disassemble_movefsr(inst: &Instruction) -> String {
289 let am = inst.operands.effective_address();
290 format!("MOVE SR, {:#X}", am)
291}
292
293pub fn disassemble_movesr(inst: &Instruction) -> String {
294 let am = inst.operands.effective_address();
295 format!("MOVE {:#X}, SR", am)
296}
297
298pub fn disassemble_moveusp(inst: &Instruction) -> String {
299 let (dir, reg) = inst.operands.direction_register();
300 if dir == Direction::UspToRegister {
301 format!("MOVE USP, A{}", reg)
302 } else {
303 format!("MOVE A{}, USP", reg)
304 }
305}
306
307pub fn disassemble_movem(inst: &Instruction) -> String {
308 let (d, s, am, list) = inst.operands.direction_size_effective_address_list();
310 if d == Direction::MemoryToRegister {
311 format!("MOVEM.{} {}, {:#X}", s, am, list)
312 } else {
313 format!("MOVEM.{} {:#X}, {}", s, list, am)
314 }
315}
316
317pub fn disassemble_movep(inst: &Instruction) -> String {
318 let (dreg, d, s, areg, disp) = inst.operands.register_direction_size_register_displacement();
319 if d == Direction::RegisterToMemory {
320 format!("MOVEP.{} D{}, ({}, A{})", s, dreg, disp, areg)
321 } else {
322 format!("MOVEP.{} ({}, A{}), D{}", s, disp, areg, dreg)
323 }
324}
325
326pub fn disassemble_moveq(inst: &Instruction) -> String {
327 let (r, d) = inst.operands.register_data();
328 format!("MOVEQ.L #{}, D{}", d, r)
329}
330
331pub fn disassemble_muls(inst: &Instruction) -> String {
332 let (r, am) = inst.operands.register_effective_address();
333 format!("MULS.W {}, D{}", am, r)
334}
335
336pub fn disassemble_mulu(inst: &Instruction) -> String {
337 let (r, am) = inst.operands.register_effective_address();
338 format!("MULU.W {}, D{}", am, r)
339}
340
341pub fn disassemble_nbcd(inst: &Instruction) -> String {
342 let am = inst.operands.effective_address();
343 format!("NBCD {}", am)
344}
345
346pub fn disassemble_neg(inst: &Instruction) -> String {
347 let (s, am) = inst.operands.size_effective_address();
348 format!("NEG.{} {}", s, am)
349}
350
351pub fn disassemble_negx(inst: &Instruction) -> String {
352 let (s, am) = inst.operands.size_effective_address();
353 format!("NEGX.{} {}", s, am)
354}
355
356pub fn disassemble_nop(_: &Instruction) -> String {
357 "NOP".to_string()
358}
359
360pub fn disassemble_not(inst: &Instruction) -> String {
361 let (s, am) = inst.operands.size_effective_address();
362 format!("NOT.{} {}", s, am)
363}
364
365pub fn disassemble_or(inst: &Instruction) -> String {
366 let (r, d, s, am) = inst.operands.register_direction_size_effective_address();
367 if d == Direction::DstEa {
368 format!("OR.{} D{}, {}", s, r, am)
369 } else {
370 format!("OR.{} {}, D{}", s, am, r)
371 }
372}
373
374pub fn disassemble_ori(inst: &Instruction) -> String {
375 let (s, am, imm) = inst.operands.size_effective_address_immediate();
376 format!("ORI.{} #{}, {}", s, imm, am)
377}
378
379pub fn disassemble_oriccr(inst: &Instruction) -> String {
380 let imm = inst.operands.immediate();
381 format!("ORI {:#X}, CCR", imm)
382}
383
384pub fn disassemble_orisr(inst: &Instruction) -> String {
385 let imm = inst.operands.immediate();
386 format!("ORI {:#X}, SR", imm)
387}
388
389pub fn disassemble_pea(inst: &Instruction) -> String {
390 let am = inst.operands.effective_address();
391 format!("PEA {}", am)
392}
393
394pub fn disassemble_reset(_: &Instruction) -> String {
395 "RESET".to_owned()
396}
397
398pub fn disassemble_rom(inst: &Instruction) -> String {
399 let (d, am) = inst.operands.direction_effective_address();
400 format!("RO{} {}", d, am)
401}
402
403pub fn disassemble_ror(inst: &Instruction) -> String {
404 let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
405 if ir {
406 format!("RO{}.{} D{}, D{}", d, s, rot, reg)
407 } else {
408 let rot = if rot == 0 { 8 } else { rot };
409 format!("RO{}.{} #{}, D{}", d, s, rot, reg)
410 }
411}
412
413pub fn disassemble_roxm(inst: &Instruction) -> String {
414 let (d, am) = inst.operands.direction_effective_address();
415 format!("ROX{} {}", d, am)
416}
417
418pub fn disassemble_roxr(inst: &Instruction) -> String {
419 let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
420 if ir {
421 format!("ROX{}.{} D{}, D{}", d, s, rot, reg)
422 } else {
423 let rot = if rot == 0 { 8 } else { rot };
424 format!("ROX{}.{} #{}, D{}", d, s, rot, reg)
425 }
426}
427
428pub fn disassemble_rte(_: &Instruction) -> String {
429 "RTE".to_string()
430}
431
432pub fn disassemble_rtr(_: &Instruction) -> String {
433 "RTR".to_string()
434}
435
436pub fn disassemble_rts(_: &Instruction) -> String {
437 "RTS".to_string()
438}
439
440pub fn disassemble_sbcd(inst: &Instruction) -> String {
441 let (ry, _, mode, rx) = inst.operands.register_size_mode_register();
442 if mode == Direction::MemoryToMemory {
443 format!("SBCD -(A{}), -(A{})", rx, ry)
444 } else {
445 format!("SBCD D{}, D{}", rx, ry)
446 }
447}
448
449pub fn disassemble_scc(inst: &Instruction) -> String {
450 let (cc, am) = inst.operands.condition_effective_address();
451 format!("S{} {}", disassemble_conditional_test(cc), am)
452}
453
454pub fn disassemble_stop(inst: &Instruction) -> String {
455 let imm = inst.operands.immediate();
456 format!("STOP #{:#X}", imm)
457}
458
459pub fn disassemble_sub(inst: &Instruction) -> String {
460 let (r, d, s, am) = inst.operands.register_direction_size_effective_address();
461 if d == Direction::DstEa {
462 format!("SUB.{} D{}, {}", s, r, am)
463 } else {
464 format!("SUB.{} {}, D{}", s, am, r)
465 }
466}
467
468pub fn disassemble_suba(inst: &Instruction) -> String {
469 let (r, s, am) = inst.operands.register_size_effective_address();
470 format!("SUBA.{} {}, A{}", s, am, r)
471}
472
473pub fn disassemble_subi(inst: &Instruction) -> String {
474 let (s, am, imm) = inst.operands.size_effective_address_immediate();
475 format!("SUBI.{} #{}, {}", s, imm, am)
476}
477
478pub fn disassemble_subq(inst: &Instruction) -> String {
479 let (d, s, am) = inst.operands.data_size_effective_address();
480 let d = if d == 0 { 8 } else { d };
481 format!("SUBQ.{} #{}, {}", s, d, am)
482}
483
484pub fn disassemble_subx(inst: &Instruction) -> String {
485 let (ry, s, mode, rx) = inst.operands.register_size_mode_register();
486 if mode == Direction::MemoryToMemory {
487 format!("SUBX.{} -(A{}), -(A{})", s, rx, ry)
488 } else {
489 format!("SUBX.{} D{}, D{}", s, rx, ry)
490 }
491}
492
493pub fn disassemble_swap(inst: &Instruction) -> String {
494 let r = inst.operands.register();
495 format!("SWAP D{}", r)
496}
497
498pub fn disassemble_tas(inst: &Instruction) -> String {
499 let am = inst.operands.effective_address();
500 format!("TAS {}", am)
501}
502
503pub fn disassemble_trap(inst: &Instruction) -> String {
504 let v = inst.operands.vector();
505 format!("TRAP #{}", v)
506}
507
508pub fn disassemble_trapv(_: &Instruction) -> String {
509 "TRAPV".to_string()
510}
511
512pub fn disassemble_tst(inst: &Instruction) -> String {
513 let (s, am) = inst.operands.size_effective_address();
514 format!("TST.{} {}", s, am)
515}
516
517pub fn disassemble_unlk(inst: &Instruction) -> String {
518 let r = inst.operands.register();
519 format!("UNLK A{}", r)
520}
521
522pub const DLUT: [fn(&Instruction) -> String; Isa::_Size as usize] = [
540 disassemble_unknown_instruction,
541 disassemble_abcd,
542 disassemble_add,
543 disassemble_adda,
544 disassemble_addi,
545 disassemble_addq,
546 disassemble_addx,
547 disassemble_and,
548 disassemble_andi,
549 disassemble_andiccr,
550 disassemble_andisr,
551 disassemble_asm,
552 disassemble_asr,
553 disassemble_bcc,
554 disassemble_bchg,
555 disassemble_bclr,
556 disassemble_bra,
557 disassemble_bset,
558 disassemble_bsr,
559 disassemble_btst,
560 disassemble_chk,
561 disassemble_clr,
562 disassemble_cmp,
563 disassemble_cmpa,
564 disassemble_cmpi,
565 disassemble_cmpm,
566 disassemble_dbcc,
567 disassemble_divs,
568 disassemble_divu,
569 disassemble_eor,
570 disassemble_eori,
571 disassemble_eoriccr,
572 disassemble_eorisr,
573 disassemble_exg,
574 disassemble_ext,
575 disassemble_illegal,
576 disassemble_jmp,
577 disassemble_jsr,
578 disassemble_lea,
579 disassemble_link,
580 disassemble_lsm,
581 disassemble_lsr,
582 disassemble_move,
583 disassemble_movea,
584 disassemble_moveccr,
585 disassemble_movefsr,
586 disassemble_movesr,
587 disassemble_moveusp,
588 disassemble_movem,
589 disassemble_movep,
590 disassemble_moveq,
591 disassemble_muls,
592 disassemble_mulu,
593 disassemble_nbcd,
594 disassemble_neg,
595 disassemble_negx,
596 disassemble_nop,
597 disassemble_not,
598 disassemble_or,
599 disassemble_ori,
600 disassemble_oriccr,
601 disassemble_orisr,
602 disassemble_pea,
603 disassemble_reset,
604 disassemble_rom,
605 disassemble_ror,
606 disassemble_roxm,
607 disassemble_roxr,
608 disassemble_rte,
609 disassemble_rtr,
610 disassemble_rts,
611 disassemble_sbcd,
612 disassemble_scc,
613 disassemble_stop,
614 disassemble_sub,
615 disassemble_suba,
616 disassemble_subi,
617 disassemble_subq,
618 disassemble_subx,
619 disassemble_swap,
620 disassemble_tas,
621 disassemble_trap,
622 disassemble_trapv,
623 disassemble_tst,
624 disassemble_unlk,
625];