ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_68k.cpp
Revision: 1.2
Committed: 1999-10-04T21:16:02Z (24 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.1: +21 -14 lines
Log Message:
- GPL'ified sources
- added provisions for autoconf stuff

File Contents

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