ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_68k.cpp
Revision: 1.5
Committed: 2000-04-24T13:10:08Z (24 years, 6 months ago) by cebix
Branch: MAIN
Changes since 1.4: +1 -1 lines
Log Message:
- added binary dump command
- converted to automake

File Contents

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