ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_68k.cpp
Revision: 1.3
Committed: 1999-10-05T14:43:43Z (24 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.2: +3 -5 lines
Log Message:
- fixed some compiler warnings
- sorted mon_atraps.h

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 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 break;
806 default:
807 abort();
808 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 }