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

# User Rev Content
1 cebix 1.1 /*
2     * mon_m68k.cpp - 68k disassembler
3     *
4 cebix 1.2 * mon (C) 1997-1999 Christian Bauer, Marc Hellwig
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 cebix 1.1 */
20    
21     /*
22 cebix 1.2 * TODO
23     * - add missing f-lines
24     * - MULx.L/DIVx.L
25     * - use tab instead of spaces
26 cebix 1.1 */
27 cebix 1.2
28     #include "sysdeps.h"
29 cebix 1.1
30     #include "mon.h"
31     #include "mon_68k.h"
32     #include "mon_atraps.h"
33    
34     enum t_size {BYTE, WORD, LONG, NOSIZE, BYTE_SILENT, WORD_SILENT, LONG_SILENT}; // "silent" means "don't append size qualifier to opcode"
35     enum t_errors {ER_UNKNOWN_ADDRESS_MODE, ER_UNKNOWN_OPCODE, ER_ILLEGAL_OPCODE};
36     enum t_address {AD_C=1000, AD_BRANCH, AD_MULT, AD_DATA, AD_DATA_IMM, AD_CACHE};
37    
38     static void error(t_errors code);
39     static int8 read_int8(void);
40     static uint16 read_uint16(void);
41     static int16 read_int16(void);
42     static int32 read_int32(void);
43     static void parse ();
44     static void add_int32_str (char *old,int32 value);
45     static void add_int16_str (char *old,int16 value);
46     static void add_int8_str (char *old,int8 value);
47     static void add_dec_int_str (char *old,int32 value);
48     static void 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     }