ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_68k.cpp
Revision: 1.1.1.1 (vendor branch)
Committed: 1999-10-04T19:31:09Z (24 years, 9 months ago) by cebix
Branch: cebix
CVS Tags: start
Changes since 1.1: +0 -0 lines
Log Message:
Imported sources

File Contents

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