ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_68k.cpp
Revision: 1.6
Committed: 2000-09-25T12:44:32Z (24 years, 1 month ago) by cebix
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +0 -0 lines
State: FILE REMOVED
Log Message:
- replaced 680x0 and 80x86 disassemblers with the ones from GNU binutils
- 680x0 disassembler shows symbolic MacOS low memory globals

File Contents

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