1 |
cebix |
1.1 |
/* |
2 |
|
|
* mon_m68k.cpp - 68k disassembler |
3 |
|
|
* |
4 |
cebix |
1.2 |
* mon (C) 1997-1999 Christian Bauer, Marc Hellwig |
5 |
|
|
* |
6 |
|
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
|
* it under the terms of the GNU General Public License as published by |
8 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
9 |
|
|
* (at your option) any later version. |
10 |
|
|
* |
11 |
|
|
* This program is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with this program; if not, write to the Free Software |
18 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
cebix |
1.1 |
*/ |
20 |
|
|
|
21 |
|
|
/* |
22 |
cebix |
1.2 |
* TODO |
23 |
|
|
* - add missing f-lines |
24 |
|
|
* - MULx.L/DIVx.L |
25 |
|
|
* - use tab instead of spaces |
26 |
cebix |
1.1 |
*/ |
27 |
cebix |
1.2 |
|
28 |
|
|
#include "sysdeps.h" |
29 |
cebix |
1.1 |
|
30 |
|
|
#include "mon.h" |
31 |
|
|
#include "mon_68k.h" |
32 |
|
|
#include "mon_atraps.h" |
33 |
|
|
|
34 |
|
|
enum t_size {BYTE, WORD, LONG, NOSIZE, BYTE_SILENT, WORD_SILENT, LONG_SILENT}; // "silent" means "don't append size qualifier to opcode" |
35 |
|
|
enum t_errors {ER_UNKNOWN_ADDRESS_MODE, ER_UNKNOWN_OPCODE, ER_ILLEGAL_OPCODE}; |
36 |
|
|
enum t_address {AD_C=1000, AD_BRANCH, AD_MULT, AD_DATA, AD_DATA_IMM, AD_CACHE}; |
37 |
|
|
|
38 |
|
|
static void error(t_errors code); |
39 |
|
|
static int8 read_int8(void); |
40 |
|
|
static uint16 read_uint16(void); |
41 |
|
|
static int16 read_int16(void); |
42 |
|
|
static int32 read_int32(void); |
43 |
|
|
static void parse (); |
44 |
|
|
static void add_int32_str (char *old,int32 value); |
45 |
|
|
static void add_int16_str (char *old,int16 value); |
46 |
|
|
static void add_int8_str (char *old,int8 value); |
47 |
|
|
static void add_dec_int_str (char *old,int32 value); |
48 |
|
|
static void print_range (int from,int to); |
49 |
|
|
static int decode_address_mode (uint16 eee,uint16 aaa,t_size size); |
50 |
|
|
static void diss (char *ndest,uint16 *nmem,int &npos,unsigned int adr); |
51 |
|
|
|
52 |
|
|
enum t_control {C_UNKNOWN,C_SR,C_CCR,C_SFC,C_DFC,C_CACR,C_TC,C_ITT0,C_ITT1,C_DTT0,C_DTT1,C_BUSCR,C_USP,C_VBR,C_CAAR,C_MSP,C_ISP,C_MMUSR,C_URP,C_SRP,C_PCR}; |
53 |
|
|
static char *con_str[]={"???","sr","ccr","sfc","dfc","cacr","tc","itt0","itt1","dtt0","dtt1","buscr","usp","vbr","caar","msp","isp","mmusr","urp","srp","pcr"}; |
54 |
|
|
static char *cc_str[]= {"t","f","hi","ls","cc","cs","ne","eq","vc","vs","pl", |
55 |
|
|
"mi","ge","lt","gt","le","ra","sr"}; |
56 |
|
|
static uint16 opcode; |
57 |
|
|
static uint16 source_eee; |
58 |
|
|
static uint16 source_aaa; |
59 |
|
|
static uint16 dest_eee; |
60 |
|
|
static uint16 dest_aaa; |
61 |
|
|
static int32 data_val; |
62 |
|
|
static uint16 mask; // for movem !!! aaarrrggglll ... |
63 |
|
|
static t_size size; |
64 |
|
|
static int count_param; |
65 |
|
|
static uint16 *mem; |
66 |
|
|
static int mem_pos; |
67 |
|
|
static char *dest; |
68 |
|
|
static char op_name[50]; |
69 |
|
|
static unsigned int adr_off; |
70 |
|
|
|
71 |
|
|
static void error (t_errors code) { |
72 |
|
|
switch (code) { |
73 |
|
|
case ER_UNKNOWN_ADDRESS_MODE: |
74 |
|
|
printf ("unknown address mode\n"); |
75 |
|
|
break; |
76 |
|
|
case ER_UNKNOWN_OPCODE: |
77 |
|
|
printf ("unknown opcode\n"); |
78 |
|
|
break; |
79 |
|
|
case ER_ILLEGAL_OPCODE: |
80 |
|
|
printf ("illegal opcode\n"); |
81 |
|
|
break; |
82 |
|
|
default: |
83 |
|
|
printf ("general error\n"); |
84 |
|
|
} |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
static int8 read_int8(void) { |
88 |
|
|
return mem[mem_pos++]; |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
static uint16 read_uint16(void) { |
92 |
|
|
return mem[mem_pos++]; |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
static int16 read_int16(void) { |
96 |
|
|
return (int16)(mem[mem_pos++]); |
97 |
|
|
} |
98 |
|
|
|
99 |
|
|
static int32 read_int32(void) { |
100 |
|
|
int32 val = (mem[mem_pos] << 16) | mem[mem_pos+1]; |
101 |
|
|
mem_pos+=2; |
102 |
|
|
return val; |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
// opcode table |
106 |
|
|
#define def_param(n,c,s,se,sa,de,da) \ |
107 |
|
|
strcpy(op_name,n);\ |
108 |
|
|
count_param=c;\ |
109 |
|
|
size=s;\ |
110 |
|
|
source_eee=se;\ |
111 |
|
|
source_aaa=sa;\ |
112 |
|
|
dest_eee=de;\ |
113 |
|
|
dest_aaa=da; |
114 |
|
|
#define no_param(n) \ |
115 |
|
|
def_param(n,0,NOSIZE,0,0,0,0) |
116 |
|
|
#define bits(pos,count) ((opcode >> pos)&((1<<count)-1)) |
117 |
|
|
#define mshort(s) \ |
118 |
|
|
if (bits(6,3)==1) \ |
119 |
|
|
{def_param("movea",2,s,bits(3,3),bits(0,3),1,bits(9,3))}\ |
120 |
|
|
else\ |
121 |
|
|
{def_param("move",2,s,bits(3,3),bits(0,3),bits(6,3),bits(9,3))} |
122 |
|
|
#define imshort(n) \ |
123 |
|
|
if (bits(6,2)<2) data_val = read_int16(); else data_val = read_int32();\ |
124 |
|
|
def_param(n,2,(t_size)bits(6,2),AD_DATA_IMM,0,bits(3,3),bits(0,3)) |
125 |
|
|
#define imshortcs(n) \ |
126 |
|
|
switch (bits(0,8)) { \ |
127 |
|
|
case 0x3c: \ |
128 |
|
|
data_val = read_int16();\ |
129 |
|
|
def_param(n,2,BYTE_SILENT,AD_DATA_IMM,0,AD_C,C_CCR) break; \ |
130 |
|
|
case 0x7c: \ |
131 |
|
|
data_val = read_int16();\ |
132 |
|
|
def_param(n,2,WORD_SILENT,AD_DATA_IMM,0,AD_C,C_SR) break; \ |
133 |
|
|
break; \ |
134 |
|
|
default: \ |
135 |
|
|
imshort(n) \ |
136 |
|
|
break;\ |
137 |
|
|
} |
138 |
|
|
#define addshort(n) \ |
139 |
|
|
if (bits(8,1)==0)\ |
140 |
|
|
{def_param(n,2,(t_size)bits(6,2),bits(3,3),bits(0,3),0,bits(9,3))}\ |
141 |
|
|
else\ |
142 |
|
|
{def_param(n,2,(t_size)bits(6,2),0,bits(9,3),bits(3,3),bits(0,3))} |
143 |
|
|
#define addxshort(n) \ |
144 |
|
|
if (bits(3,1)==0) {\ |
145 |
|
|
def_param(n,2,(t_size)bits(6,2),0,bits(0,3),0,bits(9,3))\ |
146 |
|
|
} else {\ |
147 |
|
|
def_param(n,2,(t_size)bits(6,2),4,bits(0,3),4,bits(9,3))\ |
148 |
|
|
} |
149 |
|
|
#define addashort(n) \ |
150 |
|
|
def_param(n,2,NOSIZE,bits(3,3),bits(0,3),1,bits(9,3))\ |
151 |
|
|
if (bits(8,1)==0) size=WORD; else size=LONG; |
152 |
|
|
#define deashort(n) \ |
153 |
|
|
def_param(n,2,(t_size)bits(6,2),0,bits(9,3),bits(3,3),bits(0,3)) |
154 |
|
|
#define bitshort(n) \ |
155 |
|
|
def_param(n,2,BYTE_SILENT,AD_DATA_IMM,0,bits(3,3),bits(0,3))\ |
156 |
|
|
data_val=read_int8(); |
157 |
|
|
#define bitdynshort(n) \ |
158 |
|
|
def_param(n,2,BYTE_SILENT,0,bits(9,3),bits(3,3),bits(0,3)) |
159 |
|
|
#define prwshort(n) \ |
160 |
|
|
if (((op2 >> 9) & 1)==1) \ |
161 |
|
|
{def_param(n,2,LONG,AD_C,C_UNKNOWN,bits(3,3),bits(0,3))}\ |
162 |
|
|
else\ |
163 |
|
|
{def_param(n,2,LONG,bits(3,3),bits(0,3),AD_C,C_UNKNOWN)} |
164 |
|
|
#define mshiftshort(n) \ |
165 |
|
|
def_param(n,1,WORD,bits(3,3),bits(0,3),0,0)\ |
166 |
|
|
if (bits(8,1)==0) {\ |
167 |
|
|
strcat(op_name,"r");\ |
168 |
|
|
} else {\ |
169 |
|
|
strcat(op_name,"l");\ |
170 |
|
|
} |
171 |
|
|
#define rshiftshort(n) \ |
172 |
|
|
if (bits(5,1)==0) {\ |
173 |
|
|
data_val=bits(9,3);\ |
174 |
|
|
if (data_val==0) data_val=8;\ |
175 |
|
|
def_param(n,2,(t_size)bits(6,2),AD_DATA_IMM,0,0,bits(0,3))\ |
176 |
|
|
} else {\ |
177 |
|
|
def_param(n,2,(t_size)bits(6,2),0,bits(9,3) % 64,0,bits(0,3))\ |
178 |
|
|
}\ |
179 |
|
|
if (bits(8,1)==0) {\ |
180 |
|
|
strcat(op_name,"r");\ |
181 |
|
|
} else {\ |
182 |
|
|
strcat(op_name,"l");\ |
183 |
|
|
} |
184 |
|
|
#define abcdshort(n) \ |
185 |
|
|
if (bits(3,1)==0) {\ |
186 |
|
|
def_param(n,2,BYTE,0,bits(0,3),0,bits(9,3))\ |
187 |
|
|
} else {\ |
188 |
|
|
def_param(n,2,BYTE,4,bits(0,3),4,bits(9,3))\ |
189 |
|
|
} |
190 |
|
|
#define cinvpush(n) \ |
191 |
|
|
def_param(n,bits(3,2) == 3 ? 1 : 2,NOSIZE,AD_CACHE,bits(6,2),2,bits(0,3))\ |
192 |
|
|
switch (bits(3,2)) {\ |
193 |
|
|
case 1: strcat(op_name, "l"); break;\ |
194 |
|
|
case 2: strcat(op_name, "p"); break;\ |
195 |
|
|
case 3: strcat(op_name, "a"); count_param = 1;\ |
196 |
|
|
} |
197 |
|
|
|
198 |
|
|
static void parse () { |
199 |
|
|
switch (bits(12,4)) { |
200 |
|
|
case 0: // Bit Manipulation/MOVEP/Immediate |
201 |
|
|
if (bits(8,1)==0) { // Immediate + Bit Manipulation static |
202 |
|
|
if (bits(6,2)==3) { // RTM, CALLM, CMP2, CHK2, BSET, CAS2, CAS |
203 |
|
|
switch (bits(9,3)) { |
204 |
|
|
case 3: // RTM, CALLM |
205 |
|
|
break; |
206 |
|
|
case 0: case 1: case 2: // CMP2, CHK2 |
207 |
|
|
break; |
208 |
|
|
case 4: // BSET ! |
209 |
|
|
bitshort("bset") break; |
210 |
|
|
default: // CAS2, CAS |
211 |
|
|
break; |
212 |
|
|
} |
213 |
|
|
} else { |
214 |
|
|
switch (bits(9,3)) { |
215 |
|
|
case 0: // ORI |
216 |
|
|
imshortcs("ori") break; |
217 |
|
|
case 1: // ANDI |
218 |
|
|
imshortcs("andi") break; |
219 |
|
|
case 2: // SUBI |
220 |
|
|
imshort("subi") break; |
221 |
|
|
case 3: // ADDI |
222 |
|
|
imshort("addi") break; |
223 |
|
|
case 4: // BTST, BCHG, BCLR static |
224 |
|
|
switch (bits(6,2)) { |
225 |
|
|
case 0: // BTST |
226 |
|
|
bitshort("btst") break; |
227 |
|
|
case 1: // BCHG |
228 |
|
|
bitshort("bchg") break; |
229 |
|
|
case 2: // BCLR |
230 |
|
|
bitshort ("bclr") break; |
231 |
|
|
} |
232 |
|
|
break; |
233 |
|
|
case 5: // EORI |
234 |
|
|
imshortcs("eori"); break; |
235 |
|
|
case 6: // CMPI |
236 |
|
|
imshort("cmpi"); break; |
237 |
|
|
case 7: // MOVES |
238 |
|
|
break; |
239 |
|
|
} |
240 |
|
|
} |
241 |
|
|
} else { // Bit Manipulation dynamic, MOVEP |
242 |
|
|
if (bits(3,3)==1) { // MOVEP |
243 |
|
|
if (bits(7,1)==0) { // MOVEP d(Ay),Dx |
244 |
|
|
def_param("movep",2,NOSIZE,5,bits(0,3),0,bits(9,3)) |
245 |
|
|
} else { // MOVEP Dx,d(Ay) |
246 |
|
|
def_param("movep",2,NOSIZE,0,bits(9,3),5,bits(0,3)) |
247 |
|
|
} |
248 |
|
|
if (bits(6,1)==0) size=WORD; else size=LONG; |
249 |
|
|
} else { // Bit Manipulation |
250 |
|
|
switch (bits(6,2)) { |
251 |
|
|
case 0: // BTST |
252 |
|
|
bitdynshort("btst") break; |
253 |
|
|
case 1: // BCHG |
254 |
|
|
bitdynshort("bchg") break; |
255 |
|
|
case 2: // BCLR |
256 |
|
|
bitdynshort ("bclr") break; |
257 |
|
|
case 3: // BSET |
258 |
|
|
bitdynshort ("bset") break; |
259 |
|
|
} |
260 |
|
|
} |
261 |
|
|
} |
262 |
|
|
break; |
263 |
|
|
case 1: // Move Byte |
264 |
|
|
mshort(BYTE) |
265 |
|
|
break; |
266 |
|
|
case 2: // Move Long |
267 |
|
|
mshort(LONG) |
268 |
|
|
break; |
269 |
|
|
case 3: // Move Word |
270 |
|
|
mshort(WORD) |
271 |
|
|
break; |
272 |
|
|
case 4: // Miscellaneous |
273 |
|
|
switch (bits(0,12)) { // First all fixed opcodes ... |
274 |
|
|
case 0xcfa: // BGND |
275 |
|
|
no_param("bgnd") |
276 |
|
|
break; |
277 |
|
|
case 0xafc: // ILLEGAL |
278 |
|
|
no_param("illegal") |
279 |
|
|
break; |
280 |
|
|
case 0xe70: // RESET |
281 |
|
|
no_param("reset") |
282 |
|
|
break; |
283 |
|
|
case 0xe71: // NOP |
284 |
|
|
no_param("nop") |
285 |
|
|
break; |
286 |
|
|
case 0xe72: // STOP |
287 |
|
|
data_val=read_int16(); |
288 |
|
|
def_param("stop",1,WORD_SILENT,AD_DATA_IMM,0,0,0) break; |
289 |
|
|
case 0xe73: // RTE |
290 |
|
|
no_param("rte") |
291 |
|
|
break; |
292 |
|
|
case 0xe74: // RTD |
293 |
|
|
data_val=read_int16(); |
294 |
|
|
def_param("rtd",1,WORD_SILENT,AD_DATA,0,0,0) break; |
295 |
|
|
case 0xe75: // RTS |
296 |
|
|
no_param("rts") |
297 |
|
|
break; |
298 |
|
|
case 0xe76: // TRAPV |
299 |
|
|
no_param("trapv") |
300 |
|
|
break; |
301 |
|
|
case 0xe77: // RTR |
302 |
|
|
no_param("rtr") |
303 |
|
|
break; |
304 |
|
|
case 0xe7a: case 0xe7b: { // MOVEC |
305 |
|
|
uint16 op2 = read_uint16(); |
306 |
|
|
uint16 val; |
307 |
|
|
switch (op2 & 0xfff) { |
308 |
|
|
case 0: val=C_SFC; break; |
309 |
|
|
case 1: val=C_DFC; break; |
310 |
|
|
case 2: val=C_CACR; break; |
311 |
|
|
case 3: val=C_TC; break; |
312 |
|
|
case 4: val=C_ITT0; break; |
313 |
|
|
case 5: val=C_ITT1; break; |
314 |
|
|
case 6: val=C_DTT0; break; |
315 |
|
|
case 7: val=C_DTT1; break; |
316 |
|
|
case 8: val=C_BUSCR; break; |
317 |
|
|
case 0x800: val=C_USP; break; |
318 |
|
|
case 0x801: val=C_VBR; break; |
319 |
|
|
case 0x802: val=C_CAAR; break; |
320 |
|
|
case 0x803: val=C_MSP; break; |
321 |
|
|
case 0x804: val=C_ISP; break; |
322 |
|
|
case 0x805: val=C_MMUSR; break; |
323 |
|
|
case 0x806: val=C_URP; break; |
324 |
|
|
case 0x807: val=C_SRP; break; |
325 |
|
|
case 0x808: val=C_PCR; break; |
326 |
|
|
default: val=C_UNKNOWN; break; // ERROR unknown control_reg |
327 |
|
|
} |
328 |
|
|
if (bits(0,1)==0) { // MOVEC Ctrl,AD |
329 |
|
|
def_param("movec",2,NOSIZE,AD_C,val,((op2 >> 15) & 1),((op2 >> 12) & 7)) |
330 |
|
|
} else { // MOVEC AD,Ctrl |
331 |
|
|
def_param("movec",2,NOSIZE,((op2 >> 15) & 1),((op2 >> 12) & 7),AD_C,val) |
332 |
|
|
} |
333 |
|
|
break; |
334 |
|
|
} |
335 |
|
|
default: |
336 |
|
|
switch (bits(3,9)) { |
337 |
|
|
case 0x110: case 0x118: // EXT maybe more ??? nicht ganz sauber |
338 |
|
|
def_param("ext",1,((bits(6,2)==2) ? WORD : LONG),0,bits(0,3),0,0) break; |
339 |
|
|
case 0x101: // LINK |
340 |
|
|
data_val=read_int32(); |
341 |
|
|
def_param("link",2,LONG,1,bits(0,3),AD_DATA_IMM,0) break; |
342 |
|
|
case 0x108: // SWAP |
343 |
|
|
def_param("swap",1,NOSIZE,0,bits(0,3),0,0) break; |
344 |
|
|
case 0x109: // BKPT |
345 |
|
|
data_val=bits(0,3); |
346 |
|
|
def_param("bkpt",1,BYTE,AD_DATA,0,0,0) break; |
347 |
|
|
case 0x1c8: case 0x1c9: // TRAP |
348 |
|
|
data_val=bits(0,4); |
349 |
|
|
def_param("trap",1,BYTE,AD_DATA,0,0,0) break; |
350 |
|
|
case 0x1ca: // LINK |
351 |
|
|
data_val=read_int16(); |
352 |
|
|
def_param("link",2,WORD_SILENT,1,bits(0,3),AD_DATA_IMM,0) break; |
353 |
|
|
case 0x1cb: // UNLK |
354 |
|
|
def_param("unlk",1,NOSIZE,1,bits(0,3),0,0) break; |
355 |
|
|
case 0x1cc: case 0x1cd: // MOVE USP |
356 |
|
|
if (bits(3,1)==0) { // MOVE An,USP |
357 |
|
|
def_param("move",2,LONG,1,bits(0,3),AD_C,C_USP) |
358 |
|
|
} else { // MOVE USP,An |
359 |
|
|
def_param("move",2,LONG,AD_C,C_USP,1,bits(0,3)) |
360 |
|
|
} |
361 |
|
|
break; |
362 |
|
|
default: |
363 |
|
|
switch (bits(6,6)) { |
364 |
|
|
case 3: // MOVE from SR |
365 |
|
|
def_param("move",2,WORD_SILENT,AD_C,C_SR,bits(3,3),bits(0,3)) break; |
366 |
|
|
case 0xb: // MOVE from CCR |
367 |
|
|
def_param("move",2,WORD_SILENT,AD_C,C_CCR,bits(3,3),bits(0,3)) break; |
368 |
|
|
case 0: case 1: case 2: // NEGX |
369 |
|
|
def_param("negx",1,(t_size)bits(6,2),bits(3,3),bits(0,3),0,0) break; |
370 |
|
|
case 8: case 9: case 0xa: // CLR |
371 |
|
|
def_param("clr",1,(t_size)bits(6,2),bits(3,3),bits(0,3),0,0) break; |
372 |
|
|
case 0x13: // MOVE to CCR |
373 |
|
|
def_param("move",2,WORD_SILENT,bits(3,3),bits(0,3),AD_C,C_CCR) break; |
374 |
|
|
case 0x10: case 0x11: case 0x12:// NEG |
375 |
|
|
def_param("neg",1,(t_size)bits(6,2),bits(3,3),bits(0,3),0,0) break; |
376 |
|
|
case 0x18: case 0x19: case 0x1a:// NOT |
377 |
|
|
def_param("not",1,(t_size)bits(6,2),bits(3,3),bits(0,3),0,0) break; |
378 |
|
|
case 0x1b: // MOVE to SR |
379 |
|
|
def_param("move",2,WORD_SILENT,bits(3,3),bits(0,3),AD_C,C_SR) break; |
380 |
|
|
case 0x20: // NBCD |
381 |
|
|
def_param("nbcd",1,BYTE,bits(3,3),bits(0,3),0,0) break; |
382 |
|
|
case 0x21: // PEA |
383 |
|
|
def_param("pea",1,LONG,bits(3,3),bits(0,3),0,0) break; |
384 |
|
|
case 0x2b: // TAS |
385 |
|
|
def_param("tas",1,BYTE,bits(3,3),bits(0,3),0,0) break; |
386 |
|
|
case 0x28: case 0x29: case 0x2a:// TST |
387 |
|
|
def_param("tst",1,(t_size)bits(6,2),bits(3,3),bits(0,3),0,0) break; |
388 |
|
|
case 0x30: // MULU, MULS, DIVU, DIVUL |
389 |
|
|
//!! |
390 |
|
|
break; |
391 |
|
|
case 0x31: // DIVS, DIVSL |
392 |
|
|
//!! |
393 |
|
|
break; |
394 |
|
|
case 0x3a: // JSR |
395 |
|
|
def_param("jsr ",1,NOSIZE,bits(3,3),bits(0,3),0,0) break; |
396 |
|
|
case 0x3b: // JMP |
397 |
|
|
def_param("jmp ",1,NOSIZE,bits(3,3),bits(0,3),0,0) break; |
398 |
|
|
case 0x22: case 0x23: case 0x32: case 0x33:// MOVEM |
399 |
|
|
mask=read_uint16(); |
400 |
|
|
if (bits(10,1)!=0) |
401 |
|
|
{def_param("movem",2,NOSIZE,bits(3,3),bits(0,3),AD_MULT,0)} |
402 |
|
|
else |
403 |
|
|
{def_param("movem",2,NOSIZE,AD_MULT,((bits(3,3)==4) ? 1 : 0),bits(3,3),bits(0,3))} |
404 |
|
|
if (bits(6,1)==0) size=WORD; else size=LONG; |
405 |
|
|
break; |
406 |
|
|
default: |
407 |
|
|
switch (bits(6,3)) { |
408 |
|
|
case 7: // LEA |
409 |
|
|
def_param("lea",2,NOSIZE,bits(3,3),bits(0,3),1,bits(9,3)) break; |
410 |
|
|
case 0: case 2: case 4: case 6:// CHK -> possible error ! check ! |
411 |
|
|
def_param("chk",2,WORD,bits(3,3),bits(0,3),0,bits(9,3)) break; |
412 |
|
|
default: // ERROR unknown opcode |
413 |
|
|
break; |
414 |
|
|
} |
415 |
|
|
} |
416 |
|
|
} |
417 |
|
|
} |
418 |
|
|
break; |
419 |
|
|
case 5: // ADDQ/SUBQ/Scc/DBcc/TRAPcc |
420 |
|
|
if (bits(6,2)==3) { // DBcc/TRAPcc/Scc |
421 |
|
|
switch (bits(3,3)) { |
422 |
|
|
case 1: // DBcc |
423 |
|
|
def_param("db",2,WORD_SILENT,0,bits(0,3),AD_BRANCH,bits(8,4)) |
424 |
|
|
break; |
425 |
|
|
case 7: // TRAPcc |
426 |
|
|
// not yet implemented |
427 |
|
|
break; |
428 |
|
|
default: // Scc |
429 |
|
|
def_param("s",1,BYTE,bits(3,3),bits(0,3),AD_BRANCH,bits(8,4)) |
430 |
|
|
} |
431 |
|
|
} else { // ADDQ/SUBQ |
432 |
|
|
if (bits(8,1)==0) { // ADDQ |
433 |
|
|
data_val=bits(9,3); |
434 |
|
|
def_param("addq",2,(t_size)bits(6,2),AD_DATA_IMM,0,bits(3,3),bits(0,3)) |
435 |
|
|
} else { // SUBQ |
436 |
|
|
data_val=bits(9,3); |
437 |
|
|
def_param("subq",2,(t_size)bits(6,2),AD_DATA_IMM,0,bits(3,3),bits(0,3)) |
438 |
|
|
} |
439 |
|
|
} |
440 |
|
|
break; |
441 |
|
|
case 6: // Bcc/BSR/BRA |
442 |
|
|
def_param("b",1,NOSIZE,AD_BRANCH,bits(0,8),AD_BRANCH,bits(8,4)) |
443 |
|
|
if (dest_aaa < 2) dest_aaa += 16; //Bcc -> BSR,BRA |
444 |
|
|
switch (bits(0,8)) { |
445 |
|
|
case 0: size = WORD; break; |
446 |
|
|
case 0xff: size = LONG; break; |
447 |
|
|
default: size = BYTE; |
448 |
|
|
} |
449 |
|
|
break; |
450 |
|
|
case 7: // MOVEQ |
451 |
|
|
data_val=bits(0,8); |
452 |
|
|
def_param("moveq",2,BYTE_SILENT,AD_DATA_IMM,0,0,bits(9,3)) |
453 |
|
|
break; |
454 |
|
|
case 8: // OR/DIV/SBCD |
455 |
|
|
switch (bits(4,5)) { |
456 |
|
|
case 0x10: // SBCD |
457 |
|
|
abcdshort("sbcd") break; |
458 |
|
|
case 0x14: // PACK |
459 |
|
|
break; |
460 |
|
|
case 0x18: // UNPK |
461 |
|
|
break; |
462 |
|
|
default: |
463 |
|
|
switch (bits(6,3)) { |
464 |
|
|
case 3: // DIVU/DIVUL |
465 |
|
|
def_param("divu",2,WORD,bits(3,3),bits(0,3),0,bits(9,3)) break; |
466 |
|
|
case 7: // DIVS/DIVSL |
467 |
|
|
def_param("divs",2,WORD,bits(3,3),bits(0,3),0,bits(9,3)) break; |
468 |
|
|
default: // OR |
469 |
|
|
addshort("or") |
470 |
|
|
break; |
471 |
|
|
} |
472 |
|
|
} |
473 |
|
|
break; |
474 |
|
|
case 9: // SUB/SUBX |
475 |
|
|
if (bits(6,2)==3) { // SUBA |
476 |
|
|
addashort("suba") |
477 |
|
|
} else { |
478 |
|
|
if ((bits(4,2)==0)&&(bits(8,1)==1)) {// SUBX |
479 |
|
|
addxshort("subx") |
480 |
|
|
} else { // SUB |
481 |
|
|
addshort("sub") |
482 |
|
|
} |
483 |
|
|
} |
484 |
|
|
break; |
485 |
|
|
case 0xa: { // (Unassigned, Reserved) |
486 |
|
|
int position = 0; |
487 |
|
|
no_param("a-line") |
488 |
|
|
while (atraps[position].word!=0) { |
489 |
|
|
if (atraps[position].word == opcode) { |
490 |
|
|
no_param(atraps[position].name) |
491 |
|
|
break; |
492 |
|
|
} |
493 |
|
|
position++; |
494 |
|
|
} |
495 |
|
|
break; |
496 |
|
|
} |
497 |
|
|
case 0xb: // CMP/EOR |
498 |
|
|
if (bits(6,2)==3) { // CMPA |
499 |
|
|
def_param("cmpa",2,((bits(8,1)==0) ? WORD : LONG),bits(3,3),bits(0,3),1,bits(9,3)) |
500 |
|
|
} else { |
501 |
|
|
if (bits(8,1)==1) { // CMPM/EOR |
502 |
|
|
if (bits(3,3)==1) { // CMPM |
503 |
|
|
def_param("cmpm",2,(t_size)bits(6,2),3,bits(0,3),3,bits(9,3)) |
504 |
|
|
} else { // EOR |
505 |
|
|
deashort("eor") |
506 |
|
|
} |
507 |
|
|
} else { // CMP |
508 |
|
|
deashort("cmp") |
509 |
|
|
} |
510 |
|
|
} |
511 |
|
|
break; |
512 |
|
|
case 0xc: // AND/MUL/ABCD/EXG |
513 |
|
|
switch (bits(6,3)) { |
514 |
|
|
case 3: // MULU |
515 |
|
|
def_param("mulu",2,WORD,bits(3,3),bits(0,3),0,bits(9,3)) break; |
516 |
|
|
case 7: // MULS |
517 |
|
|
def_param("muls",2,WORD,bits(3,3),bits(0,3),0,bits(9,3)) break; |
518 |
|
|
default: // ABCD/EXG/AND |
519 |
|
|
if (bits(4,5)==0x10) { // ABCD |
520 |
|
|
abcdshort("abcd") |
521 |
|
|
} else { // EXG/AND |
522 |
|
|
if ((bits(3,6)==0x28)||(bits(3,6)==0x29)||(bits(3,6)==0x31)) {//EXG |
523 |
|
|
switch (bits(3,5)) { |
524 |
|
|
case 8: def_param("exg",2,LONG,0,bits(0,3),0,bits(9,3)) break; |
525 |
|
|
case 9: def_param("exg",2,LONG,1,bits(0,3),1,bits(9,3)) break; |
526 |
|
|
case 0x11: def_param("exg",2,LONG,1,bits(0,3),0,bits(9,3)) break; |
527 |
|
|
} |
528 |
|
|
} else { // AND |
529 |
|
|
addshort("and") |
530 |
|
|
} |
531 |
|
|
} |
532 |
|
|
} |
533 |
|
|
break; |
534 |
|
|
case 0xd: // ADD/ADDX |
535 |
|
|
if (bits(6,2)==3) { // ADDA |
536 |
|
|
addashort("adda") |
537 |
|
|
} else { // ADDX/ADD |
538 |
|
|
if ((bits(4,2)==0)&&(bits(8,1)==1)) {// ADDX |
539 |
|
|
addxshort("addx") |
540 |
|
|
} else { // ADD |
541 |
|
|
addshort("add") |
542 |
|
|
} |
543 |
|
|
} |
544 |
|
|
break; |
545 |
|
|
case 0xe: // Shift/Rotate/Bit Field |
546 |
|
|
if (bits(6,2)==3) { // Mem Shift/Rotate, Bit Field |
547 |
|
|
if (bits(11,1)==0) { // Mem Shift/Rotate |
548 |
|
|
switch (bits(9,2)) { |
549 |
|
|
case 0: // ASL/ASR |
550 |
|
|
mshiftshort("as") break; |
551 |
|
|
case 1: // LSL/LSR |
552 |
|
|
mshiftshort("ls") break; |
553 |
|
|
case 2: // ROXL/ROXR |
554 |
|
|
mshiftshort("rox") break; |
555 |
|
|
case 3: // ROL/ROR |
556 |
|
|
mshiftshort ("ro") break; |
557 |
|
|
} |
558 |
|
|
} else { // Bit Field |
559 |
|
|
switch (bits(8,3)) { |
560 |
|
|
case 0: // BFTST |
561 |
|
|
break; |
562 |
|
|
case 1: // BFEXTU |
563 |
|
|
break; |
564 |
|
|
case 2: // BFCHG |
565 |
|
|
break; |
566 |
|
|
case 3: // BFEXTS |
567 |
|
|
break; |
568 |
|
|
case 4: // BFCLR |
569 |
|
|
break; |
570 |
|
|
case 5: // BFFFO |
571 |
|
|
break; |
572 |
|
|
case 6: // BFSET |
573 |
|
|
break; |
574 |
|
|
case 7: // BFINS |
575 |
|
|
break; |
576 |
|
|
} |
577 |
|
|
} |
578 |
|
|
} else { // Register Shift/Rotate |
579 |
|
|
switch (bits(3,2)) { |
580 |
|
|
case 0: // ASL/ASR |
581 |
|
|
rshiftshort("as") break; |
582 |
|
|
case 1: // LSL/LSR |
583 |
|
|
rshiftshort("ls") break; |
584 |
|
|
case 2: // ROXL/ROXR |
585 |
|
|
rshiftshort("rox") break; |
586 |
|
|
case 3: // ROL/ROR |
587 |
|
|
rshiftshort("ro") break; |
588 |
|
|
} |
589 |
|
|
} |
590 |
|
|
break; |
591 |
|
|
case 0xf: // Coprocessor Interface/MC68040 |
592 |
|
|
// and CPU32 Extensions |
593 |
|
|
switch (bits(6,6)) { |
594 |
|
|
case 0: { // P... |
595 |
|
|
uint16 op2 = read_uint16(); |
596 |
|
|
switch ((op2 >> 13) & 7) { |
597 |
|
|
case 0: // PMOVE |
598 |
|
|
prwshort("pmove") break; |
599 |
|
|
case 1: // PLOAD/PVALID/PFLUSH |
600 |
|
|
no_param("pload/pvalid/pflush") break; |
601 |
|
|
case 2: // PMOVE |
602 |
|
|
prwshort ("pmove") break; |
603 |
|
|
case 3: // PMOVE |
604 |
|
|
prwshort ("pmove") break; |
605 |
|
|
case 4: // PTST |
606 |
|
|
prwshort ("ptest") break; |
607 |
|
|
case 5: // PFLUSHR |
608 |
|
|
def_param ("pflushhr",1,LONG,bits(3,3),bits(0,3),0,0) break; |
609 |
|
|
} |
610 |
|
|
break; |
611 |
|
|
} |
612 |
|
|
case 0x10: case 0x11: case 0x12: case 0x13:// Cache |
613 |
|
|
if (bits(5,1)==0) { // CINV |
614 |
|
|
cinvpush("cinv"); |
615 |
|
|
} else { // CPUSH |
616 |
|
|
cinvpush("cpush"); |
617 |
|
|
} |
618 |
|
|
break; |
619 |
|
|
} |
620 |
|
|
break; |
621 |
|
|
default: // should never happen |
622 |
|
|
break; |
623 |
|
|
}} |
624 |
|
|
// |
625 |
|
|
|
626 |
|
|
static void add_int32_str (char *old,int32 value) { |
627 |
|
|
sprintf (&(old[strlen(old)]),"$%08x",value); |
628 |
|
|
} |
629 |
|
|
|
630 |
|
|
static void add_int16_str (char *old,int16 value) { |
631 |
|
|
sprintf (&(old[strlen(old)]),"$%04x",value); |
632 |
|
|
} |
633 |
|
|
|
634 |
|
|
static void add_int8_str (char *old,int8 value) { |
635 |
|
|
sprintf (&(old[strlen(old)]),"$%02x",value); |
636 |
|
|
} |
637 |
|
|
|
638 |
|
|
static void add_dec_int_str (char *old,int32 value) { |
639 |
|
|
sprintf (&(old[strlen(old)]),"%d",value); |
640 |
|
|
} |
641 |
|
|
|
642 |
|
|
static void print_range (int from,int to) { |
643 |
|
|
if (from < 8) dest = strcat (dest,"d"); else dest = strcat(dest,"a"); |
644 |
|
|
add_dec_int_str(dest,from & 7); |
645 |
|
|
if (to > from) { |
646 |
|
|
dest = strcat(dest,"-"); |
647 |
|
|
if (to < 8) dest = strcat (dest,"d"); else dest = strcat(dest,"a"); |
648 |
|
|
add_dec_int_str(dest,to & 7); |
649 |
|
|
} |
650 |
|
|
} |
651 |
|
|
|
652 |
|
|
static void decode_extended (bool a_reg,uint16 aaa,int32 old_mem) { |
653 |
|
|
uint16 value = read_uint16(); |
654 |
|
|
uint16 scale = 1 << ((value >> 9) & 3); |
655 |
|
|
uint16 d_a = (value >> 15) & 1; |
656 |
|
|
uint16 reg = (value >> 12) & 7; |
657 |
|
|
uint16 w_l = (value >> 11) & 1; |
658 |
|
|
strcat (dest,"("); |
659 |
|
|
if (((value >> 8) & 1)==0) { // standard format |
660 |
|
|
if (a_reg) { |
661 |
|
|
add_int8_str(dest,value & 0xff); |
662 |
|
|
strcat (dest,",a"); |
663 |
|
|
add_dec_int_str(dest,aaa); |
664 |
|
|
} else { |
665 |
|
|
add_int32_str(dest,old_mem*2+adr_off+(int32)(int8)(value)); |
666 |
|
|
strcat (dest,",pc"); |
667 |
|
|
} |
668 |
|
|
if (d_a==0) strcat (dest,",d"); else strcat (dest,",a"); |
669 |
|
|
add_dec_int_str(dest,reg); |
670 |
|
|
if (w_l==0) strcat (dest,".w"); else strcat (dest,".l"); |
671 |
|
|
if (scale > 1) { |
672 |
|
|
strcat (dest,"*"); |
673 |
|
|
add_dec_int_str(dest,scale); |
674 |
|
|
} |
675 |
|
|
} else { // extended format |
676 |
|
|
uint16 i_is = value & 3; |
677 |
|
|
uint16 bd_size = (value >> 4) & 3; |
678 |
|
|
uint16 bs = (value >> 7) & 1; |
679 |
|
|
uint16 is = (value >> 6) & 1; |
680 |
|
|
if (i_is!=0) strcat(dest,"["); |
681 |
|
|
if (bd_size!=1) { // base displacement |
682 |
|
|
switch (bd_size) { |
683 |
|
|
case 2: if (a_reg) |
684 |
|
|
add_int32_str(dest,read_int16()); |
685 |
|
|
else |
686 |
|
|
add_int32_str(dest,old_mem*2+adr_off+(int32)read_int16()); |
687 |
|
|
break; |
688 |
|
|
case 3: if (a_reg) |
689 |
|
|
add_int32_str(dest,read_int32()); |
690 |
|
|
else |
691 |
|
|
add_int32_str(dest,old_mem*2+adr_off+read_int32()); |
692 |
|
|
break; |
693 |
|
|
default: |
694 |
|
|
strcat (dest,"illegal base displacement "); |
695 |
|
|
} |
696 |
|
|
} |
697 |
|
|
if (bs==0) { |
698 |
|
|
if (bd_size!=1) strcat(dest,","); |
699 |
|
|
if (a_reg) { |
700 |
|
|
strcat (dest,"a"); |
701 |
|
|
add_dec_int_str(dest,aaa); |
702 |
|
|
} else { |
703 |
|
|
strcat (dest,"pc"); |
704 |
|
|
} |
705 |
|
|
} |
706 |
|
|
if ((is==0)&&(i_is>4)&&(i_is<8)) strcat(dest,"]"); |
707 |
|
|
if (is==0) { |
708 |
|
|
if (bs==0||bd_size!=1) strcat(dest,","); |
709 |
|
|
if (d_a==0) strcat (dest,",d"); else strcat (dest,",a"); |
710 |
|
|
add_dec_int_str(dest,reg); |
711 |
|
|
if (w_l==0) strcat (dest,".w"); else strcat (dest,".l"); |
712 |
|
|
if (scale > 1) { |
713 |
|
|
strcat (dest,"*"); |
714 |
|
|
add_dec_int_str(dest,scale); |
715 |
|
|
} |
716 |
|
|
} |
717 |
|
|
if ((i_is>0)&&(i_is<4)) strcat(dest,"]"); |
718 |
|
|
if (((is==0)&&(i_is==4))||((is==1)&&(i_is>4))) strcat(dest,"reserved"); else |
719 |
|
|
switch (i_is & 3) { |
720 |
|
|
case 2: strcat(dest,","); |
721 |
|
|
add_int32_str(dest,read_int16()); |
722 |
|
|
break; |
723 |
|
|
case 3: strcat(dest,","); |
724 |
|
|
add_int32_str(dest,read_int32()); |
725 |
|
|
break; |
726 |
|
|
} |
727 |
|
|
} |
728 |
|
|
strcat (dest,")"); |
729 |
|
|
} |
730 |
|
|
|
731 |
|
|
static int decode_address_mode (uint16 eee,uint16 aaa,t_size size) { |
732 |
|
|
int32 old_mem = mem_pos; |
733 |
|
|
switch (eee) { |
734 |
|
|
case 0: strcat (dest,"d"); |
735 |
|
|
add_dec_int_str(dest,aaa); |
736 |
|
|
break; |
737 |
|
|
case 1: strcat (dest,"a"); |
738 |
|
|
add_dec_int_str(dest,aaa); |
739 |
|
|
break; |
740 |
|
|
case 2: strcat (dest,"(a"); |
741 |
|
|
add_dec_int_str(dest,aaa); |
742 |
|
|
strcat (dest,")"); |
743 |
|
|
break; |
744 |
|
|
case 3: strcat (dest,"(a"); |
745 |
|
|
add_dec_int_str(dest,aaa); |
746 |
|
|
strcat (dest,")+"); |
747 |
|
|
break; |
748 |
|
|
case 4: strcat (dest,"-(a"); |
749 |
|
|
add_dec_int_str(dest,aaa); |
750 |
|
|
strcat (dest,")"); |
751 |
|
|
break; |
752 |
|
|
case 5: strcat (dest,"("); |
753 |
|
|
add_int16_str(dest,read_int16()); |
754 |
|
|
strcat (dest,",a"); |
755 |
|
|
add_dec_int_str(dest,aaa); |
756 |
|
|
strcat (dest,")"); |
757 |
|
|
break; |
758 |
|
|
case 6: decode_extended(true,aaa,0); |
759 |
|
|
break; |
760 |
|
|
case 7: switch (aaa) { |
761 |
|
|
case 0: add_int16_str(dest,read_int16()); |
762 |
|
|
strcat (dest,".w"); |
763 |
|
|
break; |
764 |
|
|
case 1: add_int32_str(dest,read_int32()); |
765 |
|
|
strcat (dest,".l"); |
766 |
|
|
break; |
767 |
|
|
case 2: strcat (dest,"("); |
768 |
|
|
add_int32_str(dest,old_mem*2+adr_off+(int32)read_int16()); |
769 |
|
|
strcat (dest,",pc)"); |
770 |
|
|
break; |
771 |
|
|
case 3: decode_extended(false,0,old_mem); |
772 |
|
|
break; |
773 |
|
|
case 4: strcat (dest,"#"); |
774 |
|
|
switch (size) { |
775 |
|
|
case BYTE_SILENT: |
776 |
|
|
case BYTE: add_int8_str(dest,read_int8() & 0xff); |
777 |
|
|
break; |
778 |
|
|
case WORD_SILENT: |
779 |
|
|
case WORD: add_int16_str(dest,read_int16()); |
780 |
|
|
break; |
781 |
|
|
case LONG_SILENT: |
782 |
|
|
case LONG: add_int32_str(dest,read_int32()); |
783 |
|
|
break; |
784 |
|
|
case NOSIZE: add_int8_str(dest,opcode & 0xff); |
785 |
|
|
break; |
786 |
|
|
default: ; |
787 |
|
|
} |
788 |
|
|
break; |
789 |
|
|
default: error (ER_UNKNOWN_ADDRESS_MODE); |
790 |
|
|
return -1; |
791 |
|
|
} |
792 |
|
|
break; |
793 |
|
|
case AD_C: strcat (dest,con_str[aaa]); |
794 |
|
|
break; |
795 |
|
|
case AD_BRANCH: |
796 |
|
|
switch (size){ |
797 |
|
|
case BYTE_SILENT: |
798 |
|
|
case BYTE: add_int32_str(dest, (int32)(int8)aaa+old_mem*2+adr_off); |
799 |
|
|
break; |
800 |
|
|
case WORD_SILENT: |
801 |
|
|
case WORD: add_int32_str(dest, (int32)read_int16()+old_mem*2+adr_off); |
802 |
|
|
break; |
803 |
|
|
case LONG_SILENT: |
804 |
|
|
case LONG: add_int32_str(dest, read_int32()+old_mem*2+adr_off); |
805 |
cebix |
1.3 |
break; |
806 |
|
|
default: |
807 |
|
|
abort(); |
808 |
cebix |
1.1 |
break; |
809 |
|
|
} |
810 |
|
|
break; |
811 |
|
|
case AD_MULT: { |
812 |
|
|
int dir = 1; |
813 |
|
|
int off = 0; |
814 |
|
|
if (aaa != 0) { |
815 |
|
|
dir = -1; |
816 |
|
|
off = 15; |
817 |
|
|
} |
818 |
|
|
int lend = -1; |
819 |
|
|
bool first = true; |
820 |
|
|
for (int i=0;i < 16;i++) { |
821 |
|
|
if (((mask >> (off + dir * i))& 1) == 0) { |
822 |
|
|
// print reg from lend+1 to i-1 |
823 |
|
|
if ((lend+1) <= (i-1)) { |
824 |
|
|
if (!first) dest = strcat (dest,"/"); else first = false; |
825 |
|
|
if (((lend + 1) < 8) && ((i-1) > 7)) { |
826 |
|
|
print_range (lend+1,7); |
827 |
|
|
dest = strcat (dest,"/"); |
828 |
|
|
print_range (8,i-1); |
829 |
|
|
} else { |
830 |
|
|
print_range (lend+1,i-1); |
831 |
|
|
} |
832 |
|
|
} |
833 |
|
|
lend = i; |
834 |
|
|
} |
835 |
|
|
} |
836 |
|
|
if (((mask >> (off + dir * 15)) & 1) == 1) { // print last regs |
837 |
|
|
if (!first) dest = strcat (dest,"/"); |
838 |
|
|
print_range (lend+1,15); |
839 |
|
|
} |
840 |
|
|
break; |
841 |
|
|
} |
842 |
|
|
case AD_DATA_IMM: |
843 |
|
|
strcat (dest,"#"); |
844 |
|
|
switch (size) { |
845 |
|
|
case BYTE: case BYTE_SILENT: add_int8_str(dest,data_val); break; |
846 |
|
|
case WORD: case WORD_SILENT: add_int16_str(dest,data_val); break; |
847 |
|
|
case LONG: case LONG_SILENT: add_int32_str(dest,data_val); break; |
848 |
|
|
default: ; |
849 |
|
|
} |
850 |
|
|
break; |
851 |
|
|
case AD_DATA: |
852 |
|
|
switch (size) { |
853 |
|
|
case BYTE: case BYTE_SILENT: add_int8_str(dest,data_val); break; |
854 |
|
|
case WORD: case WORD_SILENT: add_int16_str(dest,data_val); break; |
855 |
|
|
case LONG: case LONG_SILENT: add_int32_str(dest,data_val); break; |
856 |
|
|
default: ; |
857 |
|
|
} |
858 |
|
|
break; |
859 |
|
|
case AD_CACHE: |
860 |
|
|
switch (aaa) { |
861 |
|
|
case 1: strcat(dest, "dc"); break; |
862 |
|
|
case 2: strcat(dest, "ic"); break; |
863 |
|
|
case 3: strcat(dest, "dc/ic"); break; |
864 |
|
|
default: strcat(dest, "?"); break; |
865 |
|
|
} |
866 |
|
|
break; |
867 |
|
|
default: |
868 |
|
|
error (ER_UNKNOWN_ADDRESS_MODE); |
869 |
|
|
return -1; |
870 |
|
|
} |
871 |
|
|
return 0; |
872 |
|
|
} |
873 |
|
|
|
874 |
|
|
static void diss (char *ndest,uint16 *nmem,int &npos,unsigned int adr) { |
875 |
|
|
dest = ndest; mem = nmem; mem_pos = npos; adr_off=adr; |
876 |
|
|
dest[0]=0; |
877 |
|
|
opcode = read_uint16 (); |
878 |
|
|
strcat(dest,"\t"); |
879 |
|
|
|
880 |
|
|
no_param("?") |
881 |
|
|
parse(); |
882 |
|
|
|
883 |
|
|
dest = strcat(dest,op_name); |
884 |
|
|
if ((dest_eee == AD_BRANCH) && (size != NOSIZE)) dest = strcat (dest,cc_str[dest_aaa]); |
885 |
|
|
switch (size) { |
886 |
|
|
case BYTE: strcat (dest,source_eee == AD_BRANCH ? ".s\t" : ".b\t"); break; |
887 |
|
|
case WORD: strcat (dest,source_eee == AD_BRANCH ? "\t" : ".w\t"); break; |
888 |
|
|
case LONG: strcat (dest,".l\t"); break; |
889 |
|
|
default: dest = strcat (dest,"\t"); break; |
890 |
|
|
} |
891 |
|
|
if (count_param > 0) { |
892 |
|
|
if (decode_address_mode(source_eee,source_aaa,size) == -1) { |
893 |
|
|
npos = mem_pos; |
894 |
|
|
return; |
895 |
|
|
} |
896 |
|
|
if (count_param > 1) { |
897 |
|
|
strcat (dest, ","); |
898 |
|
|
if (decode_address_mode(dest_eee,dest_aaa,size) == -1) { |
899 |
|
|
npos = mem_pos; |
900 |
|
|
return; |
901 |
|
|
} |
902 |
|
|
} |
903 |
|
|
} |
904 |
|
|
npos = mem_pos; |
905 |
|
|
} |
906 |
|
|
|
907 |
|
|
|
908 |
|
|
/* |
909 |
|
|
* Disassemble one instruction, return number of bytes |
910 |
|
|
*/ |
911 |
|
|
|
912 |
|
|
int disass_68k(FILE *f, uint32 adr, uint16 *m) |
913 |
|
|
{ |
914 |
|
|
char output[80]; |
915 |
|
|
int mem_pos = 0; |
916 |
|
|
diss(output, m, mem_pos,adr); |
917 |
|
|
for (int i=0;i<4;i++) if (i<mem_pos) fprintf(f,"%04x ", m[i]); else fprintf(f," "); |
918 |
|
|
fprintf(f, "%s\n", output); |
919 |
|
|
return mem_pos << 1; |
920 |
|
|
} |