1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
#include "disasm.h"
#include "data_buffer.h"
#include "common.h"
#include <cstdio>
static size_t disasm_verbatim(
char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t, const DataBuffer &)
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes;
}
return Min(out_sz, snprintf(out, out_sz, " .short 0x%04x", instr));
}
static size_t disasm_mfff0_v4e70(
char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer &code)
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes;
}
if (instr == 0x4e70) {
return Min(out_sz, snprintf(out, out_sz, " reset"));
} else if (instr == 0x4e71) {
return Min(out_sz, snprintf(out, out_sz, " nop"));
} else if (instr == 0x4e73) {
return Min(out_sz, snprintf(out, out_sz, " rte"));
} else if (instr == 0x4e75) {
return Min(out_sz, snprintf(out, out_sz, " rts"));
} else if (instr == 0x4e76) {
return Min(out_sz, snprintf(out, out_sz, " trapv"));
} else if (instr == 0x4e77) {
return Min(out_sz, snprintf(out, out_sz, " rtr"));
}
return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
}
enum class JsrJmp {
kJsr,
kJmp,
};
static size_t disasm_jsr_jmp(
char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer & code, JsrJmp jsrjmp)
{
const char *instr_repr = (jsrjmp == JsrJmp::kJsr) ? "jsr" : "jmp";
const int addrmode = instr & 0x3f;
const int m = (addrmode >> 3) & 0x7;
const int xn = addrmode & 0x7;
switch (m) {
case 0: // 4e80 .. 4e87
case 1: // 4e88 .. 4e8f
break;
case 2: // 4e90 .. 4e97
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes;
}
return Min(out_sz, snprintf(out, out_sz, " %s %%a%d@", instr_repr, xn));
case 3: // 4e98 .. 4e9f
case 4: // 4ea0 .. 4ea7
break;
case 5: // 4ea8 .. 4eaf, Displacement
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes * 2;
}
const int16_t dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes);
return Min(out_sz, snprintf(out, out_sz, " %s %%a%d@(%d:w)", instr_repr, xn, dispmt));
}
case 6: // 4eb0 .. 4eb7, Brief Extension Word
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes * 2;
}
const uint16_t briefext = GetU16BE(code.buffer + offset + kInstructionSizeStepBytes);
const char reg = ((briefext >> 15) & 1) ? 'a' : 'd';
const int xn2 = (briefext >> 12) & 7;
const char size_spec = ((briefext >> 11) & 1) ? 'l' : 'w';
const int8_t dispmt = briefext & 0xff;
return Min(out_sz, snprintf(
out, out_sz, " %s %%a%d@(%d,%%%c%d:%c)",
instr_repr, xn, dispmt, reg, xn2, size_spec));
}
case 7: // 4eb8 .. 4ebf, some are with Brief Extension Word
switch (xn) {
case 0: // 4eb8 (xxx).W
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes * 2;
}
const int32_t dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes);
return Min(out_sz, snprintf(out, out_sz, " %s 0x%x:w", instr_repr, dispmt));
}
case 1: // 4eb9 (xxx).L
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes * 3;
}
const int32_t dispmt = GetI32BE(code.buffer + offset + kInstructionSizeStepBytes);
return Min(out_sz, snprintf(out, out_sz, " %s 0x%x:l", instr_repr, dispmt));
}
case 2: // 4eba, Displacement
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes * 2;
}
const int16_t dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes);
return Min(out_sz, snprintf(out, out_sz, " %s %%pc@(%d:w)", instr_repr, dispmt));
}
case 3: // 4ebb
{
if (instr_sz) {
*instr_sz = kInstructionSizeStepBytes * 2;
}
const uint16_t briefext = GetU16BE(
code.buffer + offset + kInstructionSizeStepBytes);
const char reg = ((briefext >> 15) & 1) ? 'a' : 'd';
const int xn2 = (briefext >> 12) & 7;
const char size_spec = ((briefext >> 11) & 1) ? 'l' : 'w';
const int8_t dispmt = briefext & 0xff;
return Min(out_sz, snprintf(
out, out_sz, " %s %%pc@(%d,%%%c%d:%c)", instr_repr, dispmt, reg, xn2, size_spec));
}
case 4: // 4ebc
case 5: // 4ebd
case 6: // 4ebe
break;
}
break;
}
return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
}
size_t m68k_disasm(
char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer &code)
{
if ((instr & 0xfff0) == 0x4e70) {
return disasm_mfff0_v4e70(out, out_sz, instr_sz, instr, offset, code);
} else if ((instr & 0xffc0) == 0x4e80) {
return disasm_jsr_jmp(out, out_sz, instr_sz, instr, offset, code, JsrJmp::kJsr);
} else if ((instr & 0xffc0) == 0x4ec0) {
return disasm_jsr_jmp(out, out_sz, instr_sz, instr, offset, code, JsrJmp::kJmp);
}
return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
}
size_t m68k_render_raw_data_comment(
char *out, size_t out_sz, uint32_t offset, size_t instr_sz, const DataBuffer &code)
{
size_t overall_sz = Min(out_sz, snprintf(out, out_sz, " |"));
for (size_t i = 0; i < instr_sz; i += kInstructionSizeStepBytes)
{
overall_sz += Min(
out_sz - overall_sz,
snprintf(
out + overall_sz,
out_sz - overall_sz,
" %04x",
GetU16BE(code.buffer + offset + i)));
}
overall_sz += Min(
out_sz - overall_sz,
snprintf(out + overall_sz, out_sz - overall_sz, " @%08x", offset));
return overall_sz;
}
|